[llvm] a0a9c9e - [InstCombine] avoid breaking up min/max (cmp+sel) idioms

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 11 09:48:18 PDT 2021


Author: Sanjay Patel
Date: 2021-08-11T12:48:11-04:00
New Revision: a0a9c9e188f5b97ff8b74287d1536f57ec5dda54

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

LOG: [InstCombine] avoid breaking up min/max (cmp+sel) idioms

This is a quick fix for a motivating case that looks like this:
https://godbolt.org/z/GeMqzMc38

As noted, we might be able to restore the min/max patterns
with select folds, or we just wait for this to become easier
with canonicalization to min/max intrinsics.

Added: 
    

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

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 2e20bca300d3f..71037616585c9 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -5755,9 +5755,6 @@ Instruction *InstCombinerImpl::visitICmpInst(ICmpInst &I) {
   if (Instruction *Res = foldICmpWithDominatingICmp(I))
     return Res;
 
-  if (Instruction *Res = foldICmpBinOp(I, Q))
-    return Res;
-
   if (Instruction *Res = foldICmpUsingKnownBits(I))
     return Res;
 
@@ -5803,6 +5800,15 @@ Instruction *InstCombinerImpl::visitICmpInst(ICmpInst &I) {
     }
   }
 
+  // The folds in here may rely on wrapping flags and special constants, so
+  // they can break up min/max idioms in some cases but not seemingly similar
+  // patterns.
+  // FIXME: It may be possible to enhance select folding to make this
+  //        unnecessary. It may also be moot if we canonicalize to min/max
+  //        intrinsics.
+  if (Instruction *Res = foldICmpBinOp(I, Q))
+    return Res;
+
   if (Instruction *Res = foldICmpInstWithConstant(I))
     return Res;
 

diff  --git a/llvm/test/Transforms/InstCombine/icmp-add.ll b/llvm/test/Transforms/InstCombine/icmp-add.ll
index 187e0ad1a31bf..1750b5685c50d 100644
--- a/llvm/test/Transforms/InstCombine/icmp-add.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-add.ll
@@ -972,7 +972,6 @@ define i1 @slt_offset_nsw(i8 %a, i8 %c) {
   ret i1 %ov
 }
 
-; FIXME:
 ; In the following 4 tests, we could push the inc/dec
 ; through the min/max, but we should not break up the
 ; min/max idiom by using 
diff erent icmp and select
@@ -980,9 +979,9 @@ define i1 @slt_offset_nsw(i8 %a, i8 %c) {
 
 define i32 @increment_max(i32 %x) {
 ; CHECK-LABEL: @increment_max(
-; CHECK-NEXT:    [[A:%.*]] = add nsw i32 [[X:%.*]], 1
-; CHECK-NEXT:    [[C_INV:%.*]] = icmp slt i32 [[X]], 0
-; CHECK-NEXT:    [[S:%.*]] = select i1 [[C_INV]], i32 0, i32 [[A]]
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i32 [[X:%.*]], -1
+; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i32 [[X]], i32 -1
+; CHECK-NEXT:    [[S:%.*]] = add nsw i32 [[TMP2]], 1
 ; CHECK-NEXT:    ret i32 [[S]]
 ;
   %a = add nsw i32 %x, 1
@@ -1019,9 +1018,9 @@ define i32 @increment_min(i32 %x) {
 
 define i32 @decrement_min(i32 %x) {
 ; CHECK-LABEL: @decrement_min(
-; CHECK-NEXT:    [[A:%.*]] = add nsw i32 [[X:%.*]], -1
-; CHECK-NEXT:    [[C_INV:%.*]] = icmp sgt i32 [[X]], 0
-; CHECK-NEXT:    [[S:%.*]] = select i1 [[C_INV]], i32 0, i32 [[A]]
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], 1
+; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i32 [[X]], i32 1
+; CHECK-NEXT:    [[S:%.*]] = add nsw i32 [[TMP2]], -1
 ; CHECK-NEXT:    ret i32 [[S]]
 ;
   %a = add nsw i32 %x, -1


        


More information about the llvm-commits mailing list