Skip to content

Simplify urem to icmp+select in (x + 1) % n #60546

Closed
@scottmcm

Description

@scottmcm

(Inspired by someone doing self.write_index = (self.write_index + 1) % self.container.len(); in a circular buffer.)

If x < n (such as because it was just used to index an array of that length), then there's no need to modulo in (x + 1) % n, since there's only one case where the modulo does anything, and thus we could detect that case instead.

Alive2 proof: https://alive2.llvm.org/ce/z/UNmz9j

define i64 @src(i64 noundef %x, i64 noundef %n) noundef {
%start:
  %_3 = icmp ult i64 noundef %x, noundef %n
  assume i1 %_3
  %_6 = add nuw i64 noundef %x, 1
  %0 = urem i64 %_6, noundef %n
  ret i64 %0
}
; =>
define i64 @tgt(i64 noundef %x, i64 noundef %n) noundef {
%start:
  %_3 = icmp ult i64 noundef %x, noundef %n
  assume i1 %_3
  %_6 = add nuw i64 noundef %x, 1
  %w = icmp eq i64 %_6, noundef %n
  %0 = select i1 %w, i64 0, i64 %_6
  ret i64 %0
}
; Transformation seems to be correct!

Repro in opt: https://llvm.godbolt.org/z/5vP7T8fE7

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions