[llvm] 02a27b3 - [InstCombine] fold X*X == 0 --> X == 0

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 15 09:30:22 PDT 2022


Author: Sanjay Patel
Date: 2022-09-15T12:02:50-04:00
New Revision: 02a27b38909edc46c41732f79a837c95c9992d5a

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

LOG: [InstCombine] fold X*X == 0 --> X == 0

This is safe when the mul does not overflow:
https://alive2.llvm.org/ce/z/LedVVP

This could be extended to handle non-zero compare constants
and non-squared multiplies.

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
    llvm/test/Transforms/InstCombine/icmp-mul.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 0969e9fcf614d..239cd16c5db69 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -2053,6 +2053,16 @@ Instruction *InstCombinerImpl::foldICmpOrConstant(ICmpInst &Cmp,
 Instruction *InstCombinerImpl::foldICmpMulConstant(ICmpInst &Cmp,
                                                    BinaryOperator *Mul,
                                                    const APInt &C) {
+  // If there's no overflow:
+  // X * X == 0 --> X == 0
+  // X * X != 0 --> X != 0
+  Type *MulTy = Mul->getType();
+  if (Cmp.isEquality() && C.isZero() &&
+      Mul->getOperand(0) == Mul->getOperand(1) &&
+      (Mul->hasNoUnsignedWrap() || Mul->hasNoSignedWrap()))
+    return new ICmpInst(Cmp.getPredicate(), Mul->getOperand(0),
+                        ConstantInt::getNullValue(MulTy));
+
   const APInt *MulC;
   if (!match(Mul->getOperand(1), m_APInt(MulC)))
     return nullptr;

diff  --git a/llvm/test/Transforms/InstCombine/icmp-mul.ll b/llvm/test/Transforms/InstCombine/icmp-mul.ll
index 0f8ee5dcf3219..f2aa0db1b326e 100644
--- a/llvm/test/Transforms/InstCombine/icmp-mul.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-mul.ll
@@ -5,8 +5,7 @@ declare void @use(i8)
 
 define i1 @squared_nsw_eq0(i5 %x) {
 ; CHECK-LABEL: @squared_nsw_eq0(
-; CHECK-NEXT:    [[M:%.*]] = mul nsw i5 [[X:%.*]], [[X]]
-; CHECK-NEXT:    [[R:%.*]] = icmp eq i5 [[M]], 0
+; CHECK-NEXT:    [[R:%.*]] = icmp eq i5 [[X:%.*]], 0
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
   %m = mul nsw i5 %x, %x
@@ -16,8 +15,7 @@ define i1 @squared_nsw_eq0(i5 %x) {
 
 define <2 x i1> @squared_nuw_eq0(<2 x i8> %x) {
 ; CHECK-LABEL: @squared_nuw_eq0(
-; CHECK-NEXT:    [[M:%.*]] = mul nuw <2 x i8> [[X:%.*]], [[X]]
-; CHECK-NEXT:    [[R:%.*]] = icmp eq <2 x i8> [[M]], zeroinitializer
+; CHECK-NEXT:    [[R:%.*]] = icmp eq <2 x i8> [[X:%.*]], zeroinitializer
 ; CHECK-NEXT:    ret <2 x i1> [[R]]
 ;
   %m = mul nuw <2 x i8> %x, %x
@@ -25,11 +23,13 @@ define <2 x i1> @squared_nuw_eq0(<2 x i8> %x) {
   ret <2 x i1> %r
 }
 
+; extra use is ok
+
 define i1 @squared_nsw_nuw_ne0(i8 %x) {
 ; CHECK-LABEL: @squared_nsw_nuw_ne0(
 ; CHECK-NEXT:    [[M:%.*]] = mul nuw nsw i8 [[X:%.*]], [[X]]
 ; CHECK-NEXT:    call void @use(i8 [[M]])
-; CHECK-NEXT:    [[R:%.*]] = icmp ne i8 [[M]], 0
+; CHECK-NEXT:    [[R:%.*]] = icmp ne i8 [[X]], 0
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
   %m = mul nsw nuw i8 %x, %x
@@ -38,6 +38,8 @@ define i1 @squared_nsw_nuw_ne0(i8 %x) {
   ret i1 %r
 }
 
+; negative test - must have no-overflow
+
 define i1 @squared_eq0(i8 %x) {
 ; CHECK-LABEL: @squared_eq0(
 ; CHECK-NEXT:    [[M:%.*]] = mul i8 [[X:%.*]], [[X]]
@@ -49,6 +51,9 @@ define i1 @squared_eq0(i8 %x) {
   ret i1 %r
 }
 
+; negative test - not squared
+; TODO: This could be or-of-icmps.
+
 define i1 @mul_nsw_eq0(i5 %x, i5 %y) {
 ; CHECK-LABEL: @mul_nsw_eq0(
 ; CHECK-NEXT:    [[M:%.*]] = mul nsw i5 [[X:%.*]], [[Y:%.*]]
@@ -60,6 +65,8 @@ define i1 @mul_nsw_eq0(i5 %x, i5 %y) {
   ret i1 %r
 }
 
+; negative test - non-zero cmp
+
 define i1 @squared_nsw_eq1(i5 %x) {
 ; CHECK-LABEL: @squared_nsw_eq1(
 ; CHECK-NEXT:    [[M:%.*]] = mul nsw i5 [[X:%.*]], [[X]]
@@ -73,8 +80,7 @@ define i1 @squared_nsw_eq1(i5 %x) {
 
 define i1 @squared_nsw_sgt0(i5 %x) {
 ; CHECK-LABEL: @squared_nsw_sgt0(
-; CHECK-NEXT:    [[M:%.*]] = mul nsw i5 [[X:%.*]], [[X]]
-; CHECK-NEXT:    [[R:%.*]] = icmp ne i5 [[M]], 0
+; CHECK-NEXT:    [[R:%.*]] = icmp ne i5 [[X:%.*]], 0
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
   %m = mul nsw i5 %x, %x


        


More information about the llvm-commits mailing list