[llvm] [InstCombine] Simplify `icmp pred (sdiv exact X, C), (sdiv exact Y, C)` into `icmp pred X, Y` when C is positive (PR #76409)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Tue Dec 26 12:59:03 PST 2023


https://github.com/dtcxzyw created https://github.com/llvm/llvm-project/pull/76409

Alive2: https://alive2.llvm.org/ce/z/u49dQ9
It will improve the codegen of `std::_Vector_base<T>::~_Vector_base()` when `sizeof(T)` is not a power of 2.
Related patch: #76384

NOTE: We can also fold `icmp signed-pred (sdiv exact X, C), (sdiv exact Y, C)` into `icmp signed-pred (sdiv exact Y, C), (sdiv exact X, C)` when C is negative. But I don't think it enables more optimizations for real-world applications.


>From 34cbcec13111a97cb6aff6c9a12f1b2710678304 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Wed, 27 Dec 2023 04:33:13 +0800
Subject: [PATCH 1/2] [InstCombine] Add pre-commit tests. NFC.

---
 llvm/test/Transforms/InstCombine/icmp.ll | 117 +++++++++++++++++++++++
 1 file changed, 117 insertions(+)

diff --git a/llvm/test/Transforms/InstCombine/icmp.ll b/llvm/test/Transforms/InstCombine/icmp.ll
index 1c7bb36f0d34c0..e1bfe8d5e8b303 100644
--- a/llvm/test/Transforms/InstCombine/icmp.ll
+++ b/llvm/test/Transforms/InstCombine/icmp.ll
@@ -854,6 +854,123 @@ define i1 @PR32949(i32 %X, i32 %Y, i32 %Z) {
   ret i1 %C
 }
 
+define i1 @test_sdiv_pos_slt(i32 %x, i32 %y) {
+; CHECK-LABEL: @test_sdiv_pos_slt(
+; CHECK-NEXT:    [[DIVX:%.*]] = sdiv exact i32 [[X:%.*]], 40
+; CHECK-NEXT:    [[DIVY:%.*]] = sdiv exact i32 [[Y:%.*]], 40
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[DIVX]], [[DIVY]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %divx = sdiv exact i32 %x, 40
+  %divy = sdiv exact i32 %y, 40
+  %cmp = icmp slt i32 %divx, %divy
+  ret i1 %cmp
+}
+
+define i1 @test_sdiv_pos_sle(i32 %x, i32 %y) {
+; CHECK-LABEL: @test_sdiv_pos_sle(
+; CHECK-NEXT:    [[DIVX:%.*]] = sdiv exact i32 [[X:%.*]], 40
+; CHECK-NEXT:    [[DIVY:%.*]] = sdiv exact i32 [[Y:%.*]], 40
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i32 [[DIVX]], [[DIVY]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %divx = sdiv exact i32 %x, 40
+  %divy = sdiv exact i32 %y, 40
+  %cmp = icmp sle i32 %divx, %divy
+  ret i1 %cmp
+}
+
+define i1 @test_sdiv_pos_sgt(i32 %x, i32 %y) {
+; CHECK-LABEL: @test_sdiv_pos_sgt(
+; CHECK-NEXT:    [[DIVX:%.*]] = sdiv exact i32 [[X:%.*]], 40
+; CHECK-NEXT:    [[DIVY:%.*]] = sdiv exact i32 [[Y:%.*]], 40
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[DIVX]], [[DIVY]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %divx = sdiv exact i32 %x, 40
+  %divy = sdiv exact i32 %y, 40
+  %cmp = icmp sgt i32 %divx, %divy
+  ret i1 %cmp
+}
+
+define i1 @test_sdiv_pos_sge(i32 %x, i32 %y) {
+; CHECK-LABEL: @test_sdiv_pos_sge(
+; CHECK-NEXT:    [[DIVX:%.*]] = sdiv exact i32 [[X:%.*]], 40
+; CHECK-NEXT:    [[DIVY:%.*]] = sdiv exact i32 [[Y:%.*]], 40
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i32 [[DIVX]], [[DIVY]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %divx = sdiv exact i32 %x, 40
+  %divy = sdiv exact i32 %y, 40
+  %cmp = icmp sge i32 %divx, %divy
+  ret i1 %cmp
+}
+
+define i1 @test_sdiv_pos_ult(i32 %x, i32 %y) {
+; CHECK-LABEL: @test_sdiv_pos_ult(
+; CHECK-NEXT:    [[DIVX:%.*]] = sdiv exact i32 [[X:%.*]], 40
+; CHECK-NEXT:    [[DIVY:%.*]] = sdiv exact i32 [[Y:%.*]], 40
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[DIVX]], [[DIVY]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %divx = sdiv exact i32 %x, 40
+  %divy = sdiv exact i32 %y, 40
+  %cmp = icmp ult i32 %divx, %divy
+  ret i1 %cmp
+}
+
+define i1 @test_sdiv_pos_ule(i32 %x, i32 %y) {
+; CHECK-LABEL: @test_sdiv_pos_ule(
+; CHECK-NEXT:    [[DIVX:%.*]] = sdiv exact i32 [[X:%.*]], 40
+; CHECK-NEXT:    [[DIVY:%.*]] = sdiv exact i32 [[Y:%.*]], 40
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ule i32 [[DIVX]], [[DIVY]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %divx = sdiv exact i32 %x, 40
+  %divy = sdiv exact i32 %y, 40
+  %cmp = icmp ule i32 %divx, %divy
+  ret i1 %cmp
+}
+
+define i1 @test_sdiv_pos_ugt(i32 %x, i32 %y) {
+; CHECK-LABEL: @test_sdiv_pos_ugt(
+; CHECK-NEXT:    [[DIVX:%.*]] = sdiv exact i32 [[X:%.*]], 40
+; CHECK-NEXT:    [[DIVY:%.*]] = sdiv exact i32 [[Y:%.*]], 40
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[DIVX]], [[DIVY]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %divx = sdiv exact i32 %x, 40
+  %divy = sdiv exact i32 %y, 40
+  %cmp = icmp ugt i32 %divx, %divy
+  ret i1 %cmp
+}
+
+define i1 @test_sdiv_pos_uge(i32 %x, i32 %y) {
+; CHECK-LABEL: @test_sdiv_pos_uge(
+; CHECK-NEXT:    [[DIVX:%.*]] = sdiv exact i32 [[X:%.*]], 40
+; CHECK-NEXT:    [[DIVY:%.*]] = sdiv exact i32 [[Y:%.*]], 40
+; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i32 [[DIVX]], [[DIVY]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %divx = sdiv exact i32 %x, 40
+  %divy = sdiv exact i32 %y, 40
+  %cmp = icmp uge i32 %divx, %divy
+  ret i1 %cmp
+}
+
+define i1 @test_sdiv_neg_slt(i32 %x, i32 %y) {
+; CHECK-LABEL: @test_sdiv_neg_slt(
+; CHECK-NEXT:    [[DIVX:%.*]] = sdiv exact i32 [[X:%.*]], -40
+; CHECK-NEXT:    [[DIVY:%.*]] = sdiv exact i32 [[Y:%.*]], -40
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[DIVX]], [[DIVY]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %divx = sdiv exact i32 %x, -40
+  %divy = sdiv exact i32 %y, -40
+  %cmp = icmp slt i32 %divx, %divy
+  ret i1 %cmp
+}
+
 ; PR8469
 define <2 x i1> @test49(<2 x i32> %i3) {
 ; CHECK-LABEL: @test49(

>From a4f471d70ea912cc41a92a045bfe8d02b717cb56 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Wed, 27 Dec 2023 04:50:40 +0800
Subject: [PATCH 2/2] [InstCombine] Simplify `icmp pred (sdiv exact X, C),
 (sdiv exact Y, C)` into `icmp pred X, Y` when C is positive

---
 .../InstCombine/InstCombineCompares.cpp       |  3 +-
 llvm/test/Transforms/InstCombine/icmp.ll      | 32 +++++--------------
 2 files changed, 10 insertions(+), 25 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 289976718e52f3..0222c93faf24e9 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -4966,7 +4966,8 @@ Instruction *InstCombinerImpl::foldICmpBinOp(ICmpInst &I,
       return new ICmpInst(Pred, BO0->getOperand(0), BO1->getOperand(0));
 
     case Instruction::SDiv:
-      if (!I.isEquality() || !BO0->isExact() || !BO1->isExact())
+      if (!(I.isEquality() || match(BO0->getOperand(1), m_NonNegative())) ||
+          !BO0->isExact() || !BO1->isExact())
         break;
       return new ICmpInst(Pred, BO0->getOperand(0), BO1->getOperand(0));
 
diff --git a/llvm/test/Transforms/InstCombine/icmp.ll b/llvm/test/Transforms/InstCombine/icmp.ll
index e1bfe8d5e8b303..9b2e141bdb0506 100644
--- a/llvm/test/Transforms/InstCombine/icmp.ll
+++ b/llvm/test/Transforms/InstCombine/icmp.ll
@@ -856,9 +856,7 @@ define i1 @PR32949(i32 %X, i32 %Y, i32 %Z) {
 
 define i1 @test_sdiv_pos_slt(i32 %x, i32 %y) {
 ; CHECK-LABEL: @test_sdiv_pos_slt(
-; CHECK-NEXT:    [[DIVX:%.*]] = sdiv exact i32 [[X:%.*]], 40
-; CHECK-NEXT:    [[DIVY:%.*]] = sdiv exact i32 [[Y:%.*]], 40
-; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[DIVX]], [[DIVY]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %divx = sdiv exact i32 %x, 40
@@ -869,9 +867,7 @@ define i1 @test_sdiv_pos_slt(i32 %x, i32 %y) {
 
 define i1 @test_sdiv_pos_sle(i32 %x, i32 %y) {
 ; CHECK-LABEL: @test_sdiv_pos_sle(
-; CHECK-NEXT:    [[DIVX:%.*]] = sdiv exact i32 [[X:%.*]], 40
-; CHECK-NEXT:    [[DIVY:%.*]] = sdiv exact i32 [[Y:%.*]], 40
-; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i32 [[DIVX]], [[DIVY]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i32 [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %divx = sdiv exact i32 %x, 40
@@ -882,9 +878,7 @@ define i1 @test_sdiv_pos_sle(i32 %x, i32 %y) {
 
 define i1 @test_sdiv_pos_sgt(i32 %x, i32 %y) {
 ; CHECK-LABEL: @test_sdiv_pos_sgt(
-; CHECK-NEXT:    [[DIVX:%.*]] = sdiv exact i32 [[X:%.*]], 40
-; CHECK-NEXT:    [[DIVY:%.*]] = sdiv exact i32 [[Y:%.*]], 40
-; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[DIVX]], [[DIVY]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %divx = sdiv exact i32 %x, 40
@@ -895,9 +889,7 @@ define i1 @test_sdiv_pos_sgt(i32 %x, i32 %y) {
 
 define i1 @test_sdiv_pos_sge(i32 %x, i32 %y) {
 ; CHECK-LABEL: @test_sdiv_pos_sge(
-; CHECK-NEXT:    [[DIVX:%.*]] = sdiv exact i32 [[X:%.*]], 40
-; CHECK-NEXT:    [[DIVY:%.*]] = sdiv exact i32 [[Y:%.*]], 40
-; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i32 [[DIVX]], [[DIVY]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i32 [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %divx = sdiv exact i32 %x, 40
@@ -908,9 +900,7 @@ define i1 @test_sdiv_pos_sge(i32 %x, i32 %y) {
 
 define i1 @test_sdiv_pos_ult(i32 %x, i32 %y) {
 ; CHECK-LABEL: @test_sdiv_pos_ult(
-; CHECK-NEXT:    [[DIVX:%.*]] = sdiv exact i32 [[X:%.*]], 40
-; CHECK-NEXT:    [[DIVY:%.*]] = sdiv exact i32 [[Y:%.*]], 40
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[DIVX]], [[DIVY]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %divx = sdiv exact i32 %x, 40
@@ -921,9 +911,7 @@ define i1 @test_sdiv_pos_ult(i32 %x, i32 %y) {
 
 define i1 @test_sdiv_pos_ule(i32 %x, i32 %y) {
 ; CHECK-LABEL: @test_sdiv_pos_ule(
-; CHECK-NEXT:    [[DIVX:%.*]] = sdiv exact i32 [[X:%.*]], 40
-; CHECK-NEXT:    [[DIVY:%.*]] = sdiv exact i32 [[Y:%.*]], 40
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ule i32 [[DIVX]], [[DIVY]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ule i32 [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %divx = sdiv exact i32 %x, 40
@@ -934,9 +922,7 @@ define i1 @test_sdiv_pos_ule(i32 %x, i32 %y) {
 
 define i1 @test_sdiv_pos_ugt(i32 %x, i32 %y) {
 ; CHECK-LABEL: @test_sdiv_pos_ugt(
-; CHECK-NEXT:    [[DIVX:%.*]] = sdiv exact i32 [[X:%.*]], 40
-; CHECK-NEXT:    [[DIVY:%.*]] = sdiv exact i32 [[Y:%.*]], 40
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[DIVX]], [[DIVY]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %divx = sdiv exact i32 %x, 40
@@ -947,9 +933,7 @@ define i1 @test_sdiv_pos_ugt(i32 %x, i32 %y) {
 
 define i1 @test_sdiv_pos_uge(i32 %x, i32 %y) {
 ; CHECK-LABEL: @test_sdiv_pos_uge(
-; CHECK-NEXT:    [[DIVX:%.*]] = sdiv exact i32 [[X:%.*]], 40
-; CHECK-NEXT:    [[DIVY:%.*]] = sdiv exact i32 [[Y:%.*]], 40
-; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i32 [[DIVX]], [[DIVY]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i32 [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %divx = sdiv exact i32 %x, 40



More information about the llvm-commits mailing list