[llvm] 29fe3fe - [InstSimplify] Peephole optimization for icmp (urem X, Y), X

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 4 11:50:05 PDT 2020


Author: Xavier Denis
Date: 2020-08-04T20:48:37+02:00
New Revision: 29fe3fe6155fd79ce731a119ce8065a8a0d26b56

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

LOG: [InstSimplify] Peephole optimization for icmp (urem X, Y), X

This revision adds the following peephole optimization
and it's negation:

    %a = urem i64 %x, %y
    %b = icmp ule i64 %a, %x
    ====>
    %b = true

With John Regehr's help this optimization was checked with Alive2
which suggests it should be valid.

This pattern occurs in the bound checks of Rust code, the program

    const N: usize = 3;
    const T = u8;

    pub fn split_mutiple(slice: &[T]) -> (&[T], &[T]) {
        let len = slice.len() / N;
        slice.split_at(len * N)
    }

the method call slice.split_at will check that len * N is within
the bounds of slice, this bounds check is after some transformations
turned into the urem seen above and then LLVM fails to optimize it
any further. Adding this optimization would cause this bounds check
to be fully optimized away.

ref: https://github.com/rust-lang/rust/issues/74938

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

Added: 
    

Modified: 
    llvm/lib/Analysis/InstructionSimplify.cpp
    llvm/test/Transforms/InstSimplify/compare.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 8dd047ecb8b2..97ac9ab458cc 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -2814,6 +2814,14 @@ static Value *simplifyICmpWithBinOpOnLHS(
     }
   }
 
+  // icmp pred (urem X, Y), X
+  if (match(LBO, m_URem(m_Specific(RHS), m_Value()))) {
+    if (Pred == ICmpInst::ICMP_ULE)
+      return getTrue(ITy);
+    if (Pred == ICmpInst::ICMP_UGT)
+      return getFalse(ITy);
+  }
+
   // x >> y <=u x
   // x udiv y <=u x.
   if (match(LBO, m_LShr(m_Specific(RHS), m_Value())) ||

diff  --git a/llvm/test/Transforms/InstSimplify/compare.ll b/llvm/test/Transforms/InstSimplify/compare.ll
index 7f665018a6fd..f9bef673f34e 100644
--- a/llvm/test/Transforms/InstSimplify/compare.ll
+++ b/llvm/test/Transforms/InstSimplify/compare.ll
@@ -725,9 +725,7 @@ define i1 @urem7(i32 %X) {
 
 define i1 @urem8(i8 %X, i8 %Y) {
 ; CHECK-LABEL: @urem8(
-; CHECK-NEXT:    [[A:%.*]] = urem i8 [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[B:%.*]] = icmp ule i8 [[A]], [[X]]
-; CHECK-NEXT:    ret i1 [[B]]
+; CHECK-NEXT:    ret i1 true
 ;
   %A = urem i8 %X, %Y
   %B = icmp ule i8 %A, %X
@@ -736,9 +734,7 @@ define i1 @urem8(i8 %X, i8 %Y) {
 
 define i1 @urem9(i8 %X, i8 %Y) {
 ; CHECK-LABEL: @urem9(
-; CHECK-NEXT:    [[A:%.*]] = urem i8 [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[B:%.*]] = icmp ugt i8 [[A]], [[X]]
-; CHECK-NEXT:    ret i1 [[B]]
+; CHECK-NEXT:    ret i1 false
 ;
   %A = urem i8 %X, %Y
   %B = icmp ugt i8 %A, %X
@@ -747,9 +743,7 @@ define i1 @urem9(i8 %X, i8 %Y) {
 
 define i1 @urem10(i8 %X, i8 %Y) {
 ; CHECK-LABEL: @urem10(
-; CHECK-NEXT:    [[A:%.*]] = urem i8 [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[B:%.*]] = icmp uge i8 [[X]], [[A]]
-; CHECK-NEXT:    ret i1 [[B]]
+; CHECK-NEXT:    ret i1 true
 ;
   %A = urem i8 %X, %Y
   %B = icmp uge i8 %X, %A
@@ -758,9 +752,7 @@ define i1 @urem10(i8 %X, i8 %Y) {
 
 define i1 @urem11(i8 %X, i8 %Y) {
 ; CHECK-LABEL: @urem11(
-; CHECK-NEXT:    [[A:%.*]] = urem i8 [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[B:%.*]] = icmp ult i8 [[X]], [[A]]
-; CHECK-NEXT:    ret i1 [[B]]
+; CHECK-NEXT:    ret i1 false
 ;
   %A = urem i8 %X, %Y
   %B = icmp ult i8 %X, %A


        


More information about the llvm-commits mailing list