Max Kazantsev 5fe915bb8c [SCEV] Canonicalize ext(min/max(x, y)) to min/max(ext(x), ext(y))
I stumbled over this while trying to improve our exit count work. These expressions
are equivalent for complementary signed/unsigned ext and min/max (including umin_seq),
but they are not canonicalized and SCEV cannot recognize them as the same.

The benefit of this canonicalization is that SCEV can prove some new equivalences which
it coudln't prove because of different forms. There is 1 test where trip count seems pessimized,
I could not directly figure out why, but it just seems an unrelated issue that we can fix.
Other changes seem neutral or positive to me.

Differential Revision: https://reviews.llvm.org/D141481
Reviewed By: nikic
2023-02-20 16:12:58 +07:00

156 lines
7.8 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py
; RUN: opt -S -disable-output "-passes=print<scalar-evolution>" < %s 2>&1 | FileCheck %s
; TODO: Make sure that zext(umin(x, y)) has same SCEV as umin(zext(x), zext(y)).
; Equality proof: https://alive2.llvm.org/ce/z/vdsvmp
define i1 @test_umin(i32 %x, i32 %y) {
; CHECK-LABEL: 'test_umin'
; CHECK-NEXT: Classifying expressions for: @test_umin
; CHECK-NEXT: %umin_x_y = select i1 %cmp_x_y, i32 %x, i32 %y
; CHECK-NEXT: --> (%x umin %y) U: full-set S: full-set
; CHECK-NEXT: %zext_umin_x_y = zext i32 %umin_x_y to i64
; CHECK-NEXT: --> ((zext i32 %x to i64) umin (zext i32 %y to i64)) U: [0,4294967296) S: [0,4294967296)
; CHECK-NEXT: %zext_x = zext i32 %x to i64
; CHECK-NEXT: --> (zext i32 %x to i64) U: [0,4294967296) S: [0,4294967296)
; CHECK-NEXT: %zext_y = zext i32 %y to i64
; CHECK-NEXT: --> (zext i32 %y to i64) U: [0,4294967296) S: [0,4294967296)
; CHECK-NEXT: %umin_zext_x_zext_y = select i1 %cmp_zext_x_zext_y, i64 %zext_x, i64 %zext_y
; CHECK-NEXT: --> ((zext i32 %x to i64) umin (zext i32 %y to i64)) U: [0,4294967296) S: [0,4294967296)
; CHECK-NEXT: Determining loop execution counts for: @test_umin
;
%cmp_x_y = icmp ult i32 %x, %y
%umin_x_y = select i1 %cmp_x_y, i32 %x, i32 %y
%zext_umin_x_y = zext i32 %umin_x_y to i64
%zext_x = zext i32 %x to i64
%zext_y = zext i32 %y to i64
%cmp_zext_x_zext_y = icmp ult i64 %zext_x, %zext_y
%umin_zext_x_zext_y = select i1 %cmp_zext_x_zext_y, i64 %zext_x, i64 %zext_y
%they_are_same = icmp eq i64 %zext_umin_x_y, %umin_zext_x_zext_y
ret i1 %they_are_same
}
; TODO: Make sure that zext(umax(x, y)) has same SCEV as umax(zext(x), zext(y)).
; Equality proof: https://alive2.llvm.org/ce/z/5JHgxZ
define i1 @test_umax(i32 %x, i32 %y) {
; CHECK-LABEL: 'test_umax'
; CHECK-NEXT: Classifying expressions for: @test_umax
; CHECK-NEXT: %umax_x_y = select i1 %cmp_x_y, i32 %y, i32 %x
; CHECK-NEXT: --> (%x umax %y) U: full-set S: full-set
; CHECK-NEXT: %zext_umax_x_y = zext i32 %umax_x_y to i64
; CHECK-NEXT: --> ((zext i32 %x to i64) umax (zext i32 %y to i64)) U: [0,4294967296) S: [0,4294967296)
; CHECK-NEXT: %zext_x = zext i32 %x to i64
; CHECK-NEXT: --> (zext i32 %x to i64) U: [0,4294967296) S: [0,4294967296)
; CHECK-NEXT: %zext_y = zext i32 %y to i64
; CHECK-NEXT: --> (zext i32 %y to i64) U: [0,4294967296) S: [0,4294967296)
; CHECK-NEXT: %umax_zext_x_zext_y = select i1 %cmp_zext_x_zext_y, i64 %zext_y, i64 %zext_x
; CHECK-NEXT: --> ((zext i32 %x to i64) umax (zext i32 %y to i64)) U: [0,4294967296) S: [0,4294967296)
; CHECK-NEXT: Determining loop execution counts for: @test_umax
;
%cmp_x_y = icmp ult i32 %x, %y
%umax_x_y = select i1 %cmp_x_y, i32 %y, i32 %x
%zext_umax_x_y = zext i32 %umax_x_y to i64
%zext_x = zext i32 %x to i64
%zext_y = zext i32 %y to i64
%cmp_zext_x_zext_y = icmp ult i64 %zext_x, %zext_y
%umax_zext_x_zext_y = select i1 %cmp_zext_x_zext_y, i64 %zext_y, i64 %zext_x
%they_are_same = icmp eq i64 %zext_umax_x_y, %umax_zext_x_zext_y
ret i1 %they_are_same
}
; TODO: Make sure that sext(smin(x, y)) has same SCEV as smin(sext(x), sext(y)).
; Equality proof: https://alive2.llvm.org/ce/z/HhYHzR
define i1 @test_smin(i32 %x, i32 %y) {
; CHECK-LABEL: 'test_smin'
; CHECK-NEXT: Classifying expressions for: @test_smin
; CHECK-NEXT: %smin_x_y = select i1 %cmp_x_y, i32 %x, i32 %y
; CHECK-NEXT: --> (%x smin %y) U: full-set S: full-set
; CHECK-NEXT: %sext_smin_x_y = sext i32 %smin_x_y to i64
; CHECK-NEXT: --> ((sext i32 %x to i64) smin (sext i32 %y to i64)) U: [-2147483648,2147483648) S: [-2147483648,2147483648)
; CHECK-NEXT: %sext_x = sext i32 %x to i64
; CHECK-NEXT: --> (sext i32 %x to i64) U: [-2147483648,2147483648) S: [-2147483648,2147483648)
; CHECK-NEXT: %sext_y = sext i32 %y to i64
; CHECK-NEXT: --> (sext i32 %y to i64) U: [-2147483648,2147483648) S: [-2147483648,2147483648)
; CHECK-NEXT: %smin_sext_x_sext_y = select i1 %cmp_sext_x_sext_y, i64 %sext_x, i64 %sext_y
; CHECK-NEXT: --> ((sext i32 %x to i64) smin (sext i32 %y to i64)) U: [-2147483648,2147483648) S: [-2147483648,2147483648)
; CHECK-NEXT: Determining loop execution counts for: @test_smin
;
%cmp_x_y = icmp slt i32 %x, %y
%smin_x_y = select i1 %cmp_x_y, i32 %x, i32 %y
%sext_smin_x_y = sext i32 %smin_x_y to i64
%sext_x = sext i32 %x to i64
%sext_y = sext i32 %y to i64
%cmp_sext_x_sext_y = icmp slt i64 %sext_x, %sext_y
%smin_sext_x_sext_y = select i1 %cmp_sext_x_sext_y, i64 %sext_x, i64 %sext_y
%they_are_same = icmp eq i64 %sext_smin_x_y, %smin_sext_x_sext_y
ret i1 %they_are_same
}
; TODO: Make sure that sext(smax(x, y)) has same SCEV as smax(sext(x), sext(y)).
; Equality proof: https://alive2.llvm.org/ce/z/uou_u-
define i1 @test_smax(i32 %x, i32 %y) {
; CHECK-LABEL: 'test_smax'
; CHECK-NEXT: Classifying expressions for: @test_smax
; CHECK-NEXT: %smax_x_y = select i1 %cmp_x_y, i32 %y, i32 %x
; CHECK-NEXT: --> (%x smax %y) U: full-set S: full-set
; CHECK-NEXT: %sext_smax_x_y = sext i32 %smax_x_y to i64
; CHECK-NEXT: --> ((sext i32 %x to i64) smax (sext i32 %y to i64)) U: [-2147483648,2147483648) S: [-2147483648,2147483648)
; CHECK-NEXT: %sext_x = sext i32 %x to i64
; CHECK-NEXT: --> (sext i32 %x to i64) U: [-2147483648,2147483648) S: [-2147483648,2147483648)
; CHECK-NEXT: %sext_y = sext i32 %y to i64
; CHECK-NEXT: --> (sext i32 %y to i64) U: [-2147483648,2147483648) S: [-2147483648,2147483648)
; CHECK-NEXT: %smax_sext_x_sext_y = select i1 %cmp_sext_x_sext_y, i64 %sext_y, i64 %sext_x
; CHECK-NEXT: --> ((sext i32 %x to i64) smax (sext i32 %y to i64)) U: [-2147483648,2147483648) S: [-2147483648,2147483648)
; CHECK-NEXT: Determining loop execution counts for: @test_smax
;
%cmp_x_y = icmp slt i32 %x, %y
%smax_x_y = select i1 %cmp_x_y, i32 %y, i32 %x
%sext_smax_x_y = sext i32 %smax_x_y to i64
%sext_x = sext i32 %x to i64
%sext_y = sext i32 %y to i64
%cmp_sext_x_sext_y = icmp slt i64 %sext_x, %sext_y
%smax_sext_x_sext_y = select i1 %cmp_sext_x_sext_y, i64 %sext_y, i64 %sext_x
%they_are_same = icmp eq i64 %sext_smax_x_y, %smax_sext_x_sext_y
ret i1 %they_are_same
}
; TODO: Make sure that zext(umin_seq(x, y)) has same SCEV as umin_seq(zext(x), zext(y)).
; Equality proof: https://alive2.llvm.org/ce/z/X8kaNx
define i1 @test_umin_seq(i1 %x, i1 %y) {
; CHECK-LABEL: 'test_umin_seq'
; CHECK-NEXT: Classifying expressions for: @test_umin_seq
; CHECK-NEXT: %x_umin_seq_y = select i1 %x, i1 %y, i1 false
; CHECK-NEXT: --> (%x umin_seq %y) U: full-set S: full-set
; CHECK-NEXT: %zext_x_umin_seq_y = zext i1 %x_umin_seq_y to i64
; CHECK-NEXT: --> ((zext i1 %x to i64) umin_seq (zext i1 %y to i64)) U: [0,2) S: [0,2)
; CHECK-NEXT: %zext_x = zext i1 %x to i64
; CHECK-NEXT: --> (zext i1 %x to i64) U: [0,2) S: [0,2)
; CHECK-NEXT: %zext_y = zext i1 %y to i64
; CHECK-NEXT: --> (zext i1 %y to i64) U: [0,2) S: [0,2)
; CHECK-NEXT: %umin_zext_x_zext_y = select i1 %cmp_zext_x_zext_y, i64 %zext_x, i64 %zext_y
; CHECK-NEXT: --> ((zext i1 %x to i64) umin (zext i1 %y to i64)) U: [0,2) S: [0,2)
; CHECK-NEXT: %umin_seq_zext_x_xext_y = select i1 %zext_x_is_0, i64 0, i64 %umin_zext_x_zext_y
; CHECK-NEXT: --> ((zext i1 %x to i64) umin_seq (zext i1 %y to i64)) U: [0,2) S: [0,2)
; CHECK-NEXT: Determining loop execution counts for: @test_umin_seq
;
%x_umin_seq_y = select i1 %x, i1 %y, i1 false
%zext_x_umin_seq_y = zext i1 %x_umin_seq_y to i64
%zext_x = zext i1 %x to i64
%zext_y = zext i1 %y to i64
%zext_x_is_0 = icmp eq i64 %zext_x, 0
%cmp_zext_x_zext_y = icmp ult i64 %zext_x, %zext_y
%umin_zext_x_zext_y = select i1 %cmp_zext_x_zext_y, i64 %zext_x, i64 %zext_y
%umin_seq_zext_x_xext_y = select i1 %zext_x_is_0, i64 0, i64 %umin_zext_x_zext_y
%they_are_same = icmp eq i64 %zext_x_umin_seq_y, %umin_seq_zext_x_xext_y
ret i1 %they_are_same
}