Skip to content

Commit 60f6f3e

Browse files
xldenisarichardson
authored andcommitted
[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: rust-lang/rust#74938 Differential Revision: https://reviews.llvm.org/D85092
2 parents a6d1c61 + 29fe3fe commit 60f6f3e

File tree

2 files changed

+12
-12
lines changed

2 files changed

+12
-12
lines changed

llvm/lib/Analysis/InstructionSimplify.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2817,6 +2817,14 @@ static Value *simplifyICmpWithBinOpOnLHS(
28172817
}
28182818
}
28192819

2820+
// icmp pred (urem X, Y), X
2821+
if (match(LBO, m_URem(m_Specific(RHS), m_Value()))) {
2822+
if (Pred == ICmpInst::ICMP_ULE)
2823+
return getTrue(ITy);
2824+
if (Pred == ICmpInst::ICMP_UGT)
2825+
return getFalse(ITy);
2826+
}
2827+
28202828
// x >> y <=u x
28212829
// x udiv y <=u x.
28222830
if (match(LBO, m_LShr(m_Specific(RHS), m_Value())) ||

llvm/test/Transforms/InstSimplify/compare.ll

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -725,9 +725,7 @@ define i1 @urem7(i32 %X) {
725725

726726
define i1 @urem8(i8 %X, i8 %Y) {
727727
; CHECK-LABEL: @urem8(
728-
; CHECK-NEXT: [[A:%.*]] = urem i8 [[X:%.*]], [[Y:%.*]]
729-
; CHECK-NEXT: [[B:%.*]] = icmp ule i8 [[A]], [[X]]
730-
; CHECK-NEXT: ret i1 [[B]]
728+
; CHECK-NEXT: ret i1 true
731729
;
732730
%A = urem i8 %X, %Y
733731
%B = icmp ule i8 %A, %X
@@ -736,9 +734,7 @@ define i1 @urem8(i8 %X, i8 %Y) {
736734

737735
define i1 @urem9(i8 %X, i8 %Y) {
738736
; CHECK-LABEL: @urem9(
739-
; CHECK-NEXT: [[A:%.*]] = urem i8 [[X:%.*]], [[Y:%.*]]
740-
; CHECK-NEXT: [[B:%.*]] = icmp ugt i8 [[A]], [[X]]
741-
; CHECK-NEXT: ret i1 [[B]]
737+
; CHECK-NEXT: ret i1 false
742738
;
743739
%A = urem i8 %X, %Y
744740
%B = icmp ugt i8 %A, %X
@@ -747,9 +743,7 @@ define i1 @urem9(i8 %X, i8 %Y) {
747743

748744
define i1 @urem10(i8 %X, i8 %Y) {
749745
; CHECK-LABEL: @urem10(
750-
; CHECK-NEXT: [[A:%.*]] = urem i8 [[X:%.*]], [[Y:%.*]]
751-
; CHECK-NEXT: [[B:%.*]] = icmp uge i8 [[X]], [[A]]
752-
; CHECK-NEXT: ret i1 [[B]]
746+
; CHECK-NEXT: ret i1 true
753747
;
754748
%A = urem i8 %X, %Y
755749
%B = icmp uge i8 %X, %A
@@ -758,9 +752,7 @@ define i1 @urem10(i8 %X, i8 %Y) {
758752

759753
define i1 @urem11(i8 %X, i8 %Y) {
760754
; CHECK-LABEL: @urem11(
761-
; CHECK-NEXT: [[A:%.*]] = urem i8 [[X:%.*]], [[Y:%.*]]
762-
; CHECK-NEXT: [[B:%.*]] = icmp ult i8 [[X]], [[A]]
763-
; CHECK-NEXT: ret i1 [[B]]
755+
; CHECK-NEXT: ret i1 false
764756
;
765757
%A = urem i8 %X, %Y
766758
%B = icmp ult i8 %X, %A

0 commit comments

Comments
 (0)