[llvm] d30cf77 - [InstCombine] complete fold extractvalue (any_mul_with_overflow X, -1)

Chenbing Zheng via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 1 20:00:57 PDT 2022


Author: Chenbing Zheng
Date: 2022-09-02T10:58:42+08:00
New Revision: d30cf77cb1e4f743c52adbd52bf4f079794eded3

URL: https://github.com/llvm/llvm-project/commit/d30cf77cb1e4f743c52adbd52bf4f079794eded3
DIFF: https://github.com/llvm/llvm-project/commit/d30cf77cb1e4f743c52adbd52bf4f079794eded3.diff

LOG: [InstCombine] complete fold extractvalue (any_mul_with_overflow X, -1)

When we do extractvalue (any_mul_with_overflow X, -1) --> (-X and icmp),
which left partly failed to match vector constant with poison element.
This patch try to fix it.

Alive2: https://alive2.llvm.org/ce/z/2rGp_3

Reviewed By: spatel

Differential Revision: https://reviews.llvm.org/D132996

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
    llvm/test/Transforms/InstCombine/with_overflow.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index e673593028680..8dc89b57f51fa 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -3256,11 +3256,14 @@ InstCombinerImpl::foldExtractOfOverflowIntrinsic(ExtractValueInst &EV) {
 
   // extractvalue (any_mul_with_overflow X, -1), 0 --> -X
   Intrinsic::ID OvID = WO->getIntrinsicID();
-  if (*EV.idx_begin() == 0 &&
-      (OvID == Intrinsic::smul_with_overflow ||
-       OvID == Intrinsic::umul_with_overflow) &&
-      match(WO->getArgOperand(1), m_AllOnes())) {
-    return BinaryOperator::CreateNeg(WO->getArgOperand(0));
+  const APInt *C = nullptr;
+  if (match(WO->getRHS(), m_APIntAllowUndef(C))) {
+    if (*EV.idx_begin() == 0 &&
+        (OvID == Intrinsic::smul_with_overflow ||
+         OvID == Intrinsic::umul_with_overflow) &&
+        C->isAllOnes()) {
+      return BinaryOperator::CreateNeg(WO->getArgOperand(0));
+    }
   }
 
   // We're extracting from an overflow intrinsic. See if we're the only user.
@@ -3289,8 +3292,7 @@ InstCombinerImpl::foldExtractOfOverflowIntrinsic(ExtractValueInst &EV) {
   // If only the overflow result is used, and the right hand side is a
   // constant (or constant splat), we can remove the intrinsic by directly
   // checking for overflow.
-  const APInt *C;
-  if (match(WO->getRHS(), m_APInt(C))) {
+  if (C) {
     // Compute the no-wrap range for LHS given RHS=C, then construct an
     // equivalent icmp, potentially using an offset.
     ConstantRange NWR = ConstantRange::makeExactNoWrapRegion(

diff  --git a/llvm/test/Transforms/InstCombine/with_overflow.ll b/llvm/test/Transforms/InstCombine/with_overflow.ll
index b692530554556..fc8944e90f8c9 100644
--- a/llvm/test/Transforms/InstCombine/with_overflow.ll
+++ b/llvm/test/Transforms/InstCombine/with_overflow.ll
@@ -793,13 +793,10 @@ define <4 x i8> @smul_neg1_vec(<4 x i8> %x, <4 x i1>* %p) {
   ret <4 x i8> %r
 }
 
-; TODO: partly failed to match vector constant with poison element
-
 define <4 x i8> @smul_neg1_vec_poison(<4 x i8> %x, <4 x i1>* %p) {
 ; CHECK-LABEL: @smul_neg1_vec_poison(
-; CHECK-NEXT:    [[M:%.*]] = tail call { <4 x i8>, <4 x i1> } @llvm.smul.with.overflow.v4i8(<4 x i8> [[X:%.*]], <4 x i8> <i8 -1, i8 -1, i8 poison, i8 -1>)
-; CHECK-NEXT:    [[R:%.*]] = sub <4 x i8> zeroinitializer, [[X]]
-; CHECK-NEXT:    [[OV:%.*]] = extractvalue { <4 x i8>, <4 x i1> } [[M]], 1
+; CHECK-NEXT:    [[R:%.*]] = sub <4 x i8> zeroinitializer, [[X:%.*]]
+; CHECK-NEXT:    [[OV:%.*]] = icmp eq <4 x i8> [[X]], <i8 -128, i8 -128, i8 -128, i8 -128>
 ; CHECK-NEXT:    store <4 x i1> [[OV]], <4 x i1>* [[P:%.*]], align 1
 ; CHECK-NEXT:    ret <4 x i8> [[R]]
 ;
@@ -853,13 +850,10 @@ define <4 x i8> @umul_neg1_vec(<4 x i8> %x, <4 x i1>* %p) {
   ret <4 x i8> %r
 }
 
-; TODO: partly failed to match vector constant with poison element
-
 define <4 x i8> @umul_neg1_vec_poison(<4 x i8> %x, <4 x i1>* %p) {
 ; CHECK-LABEL: @umul_neg1_vec_poison(
-; CHECK-NEXT:    [[M:%.*]] = tail call { <4 x i8>, <4 x i1> } @llvm.umul.with.overflow.v4i8(<4 x i8> [[X:%.*]], <4 x i8> <i8 poison, i8 -1, i8 -1, i8 poison>)
-; CHECK-NEXT:    [[R:%.*]] = sub <4 x i8> zeroinitializer, [[X]]
-; CHECK-NEXT:    [[OV:%.*]] = extractvalue { <4 x i8>, <4 x i1> } [[M]], 1
+; CHECK-NEXT:    [[R:%.*]] = sub <4 x i8> zeroinitializer, [[X:%.*]]
+; CHECK-NEXT:    [[OV:%.*]] = icmp ugt <4 x i8> [[X]], <i8 1, i8 1, i8 1, i8 1>
 ; CHECK-NEXT:    store <4 x i1> [[OV]], <4 x i1>* [[P:%.*]], align 1
 ; CHECK-NEXT:    ret <4 x i8> [[R]]
 ;
@@ -870,6 +864,17 @@ define <4 x i8> @umul_neg1_vec_poison(<4 x i8> %x, <4 x i1>* %p) {
   ret <4 x i8> %r
 }
 
+define <4 x i1> @smul_not_neg1_vec(<4 x i8> %x) {
+; CHECK-LABEL: @smul_not_neg1_vec(
+; CHECK-NEXT:    [[TMP1:%.*]] = add <4 x i8> [[X:%.*]], <i8 -43, i8 -43, i8 -43, i8 -43>
+; CHECK-NEXT:    [[OV:%.*]] = icmp ult <4 x i8> [[TMP1]], <i8 -85, i8 -85, i8 -85, i8 -85>
+; CHECK-NEXT:    ret <4 x i1> [[OV]]
+;
+  %m = call { <4 x i8>, <4 x i1> } @llvm.smul.with.overflow.v4i8(<4 x i8> %x, <4 x i8> <i8 -3, i8 -3, i8 poison, i8 -3>)
+  %ov = extractvalue { <4 x i8>, <4 x i1> } %m, 1
+  ret <4 x i1> %ov
+}
+
 ; TODO: this could be 'shl' and 'icmp'
 
 define i8 @umul_2(i8 %x, i1* %p) {


        


More information about the llvm-commits mailing list