Skip to content

Commit 29fe3fe

Browse files
xldenisnikic
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
1 parent b778b04 commit 29fe3fe

File tree

2 files changed

+12
-12
lines changed

2 files changed

+12
-12
lines changed

llvm/lib/Analysis/InstructionSimplify.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -2814,6 +2814,14 @@ static Value *simplifyICmpWithBinOpOnLHS(
28142814
}
28152815
}
28162816

2817+
// icmp pred (urem X, Y), X
2818+
if (match(LBO, m_URem(m_Specific(RHS), m_Value()))) {
2819+
if (Pred == ICmpInst::ICMP_ULE)
2820+
return getTrue(ITy);
2821+
if (Pred == ICmpInst::ICMP_UGT)
2822+
return getFalse(ITy);
2823+
}
2824+
28172825
// x >> y <=u x
28182826
// x udiv y <=u x.
28192827
if (match(LBO, m_LShr(m_Specific(RHS), m_Value())) ||

llvm/test/Transforms/InstSimplify/compare.ll

+4-12
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)