Files
clang-p2996/llvm/test/Analysis/ScalarEvolution/urem-0.ll
Philip Reames 8d85e945b2 [SCEV] Canonicalize X - urem X, Y patterns
There are multiple possible ways to represent the X - urem X, Y pattern. SCEV was not canonicalizing, and thus, depending on which you analyzed, you could get different results. The sub representation appears to produce strictly inferior results in practice, so I decided to canonicalize to the Y * X/Y version.

The motivation here is that runtime unroll produces the sub X - (and X, Y-1) pattern when Y is a power of two. SCEV is thus unable to recognize that an unrolled loop exits because we don't figure out that the new unrolled step evenly divides the trip count of the unrolled loop. After instcombine runs, we convert the the andn form which SCEV recognizes, so essentially, this is just fixing a nasty pass ordering dependency.

The ARM loop hardware interaction in the test diff is opague to me, but the comments in the review from others knowledge of the infrastructure appear to indicate these are improvements in loop recognition, not regressions.

Differential Revision: https://reviews.llvm.org/D114018
2021-11-16 11:59:21 -08:00

89 lines
2.9 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py
; RUN: opt < %s "-passes=print<scalar-evolution>" -disable-output 2>&1 | FileCheck %s
define i8 @foo(i8 %a) {
; CHECK-LABEL: 'foo'
; CHECK-NEXT: Classifying expressions for: @foo
; CHECK-NEXT: %t0 = urem i8 %a, 27
; CHECK-NEXT: --> ((-27 * (%a /u 27)) + %a) U: full-set S: full-set
; CHECK-NEXT: Determining loop execution counts for: @foo
;
%t0 = urem i8 %a, 27
ret i8 %t0
}
define i8 @bar(i8 %a) {
; CHECK-LABEL: 'bar'
; CHECK-NEXT: Classifying expressions for: @bar
; CHECK-NEXT: %t1 = urem i8 %a, 1
; CHECK-NEXT: --> 0 U: [0,1) S: [0,1)
; CHECK-NEXT: Determining loop execution counts for: @bar
;
%t1 = urem i8 %a, 1
ret i8 %t1
}
define i8 @baz(i8 %a) {
; CHECK-LABEL: 'baz'
; CHECK-NEXT: Classifying expressions for: @baz
; CHECK-NEXT: %t2 = urem i8 %a, 32
; CHECK-NEXT: --> (zext i5 (trunc i8 %a to i5) to i8) U: [0,32) S: [0,32)
; CHECK-NEXT: Determining loop execution counts for: @baz
;
%t2 = urem i8 %a, 32
ret i8 %t2
}
define i8 @qux(i8 %a) {
; CHECK-LABEL: 'qux'
; CHECK-NEXT: Classifying expressions for: @qux
; CHECK-NEXT: %t3 = urem i8 %a, 2
; CHECK-NEXT: --> (zext i1 (trunc i8 %a to i1) to i8) U: [0,2) S: [0,2)
; CHECK-NEXT: Determining loop execution counts for: @qux
;
%t3 = urem i8 %a, 2
ret i8 %t3
}
define i32 @test_and_not(i32 %arg) {
; CHECK-LABEL: 'test_and_not'
; CHECK-NEXT: Classifying expressions for: @test_and_not
; CHECK-NEXT: %andn = and i32 %arg, -8
; CHECK-NEXT: --> (8 * (%arg /u 8))<nuw> U: [0,-7) S: [-2147483648,2147483641)
; CHECK-NEXT: Determining loop execution counts for: @test_and_not
;
%andn = and i32 %arg, -8
ret i32 %andn
}
define i32 @test_sub_urem(i32 %arg) {
; CHECK-LABEL: 'test_sub_urem'
; CHECK-NEXT: Classifying expressions for: @test_sub_urem
; CHECK-NEXT: %urem = urem i32 %arg, 8
; CHECK-NEXT: --> (zext i3 (trunc i32 %arg to i3) to i32) U: [0,8) S: [0,8)
; CHECK-NEXT: %sub = sub i32 %arg, %urem
; CHECK-NEXT: --> (8 * (%arg /u 8))<nuw> U: [0,-7) S: [-2147483648,2147483641)
; CHECK-NEXT: Determining loop execution counts for: @test_sub_urem
;
%urem = urem i32 %arg, 8
%sub = sub i32 %arg, %urem
ret i32 %sub
}
define i32 @test_trunc_zext(i32 %arg) {
; CHECK-LABEL: 'test_trunc_zext'
; CHECK-NEXT: Classifying expressions for: @test_trunc_zext
; CHECK-NEXT: %trunc = trunc i32 %arg to i3
; CHECK-NEXT: --> (trunc i32 %arg to i3) U: full-set S: full-set
; CHECK-NEXT: %zext = zext i3 %trunc to i32
; CHECK-NEXT: --> (zext i3 (trunc i32 %arg to i3) to i32) U: [0,8) S: [0,8)
; CHECK-NEXT: %sub = sub i32 %arg, %zext
; CHECK-NEXT: --> (8 * (%arg /u 8))<nuw> U: [0,-7) S: [-2147483648,2147483641)
; CHECK-NEXT: Determining loop execution counts for: @test_trunc_zext
;
%trunc = trunc i32 %arg to i3
%zext = zext i3 %trunc to i32
%sub = sub i32 %arg, %zext
ret i32 %sub
}