Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / Transforms / InstSimplify / po2-shift-add-and-to-zero.ll
blob54dd1688ad916aa98b52bab641572b542db5593a
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
2 ; RUN: opt -passes=instsimplify -S < %s | FileCheck %s
4 ;; The and X, (add Y, -1) pattern is from an earlier instcombine pass which
5 ;; converted
7 ;; define i64 @f1() #0 {
8 ;; entry:
9 ;;   %0 = call i64 @llvm.aarch64.sve.cntb(i32 31)
10 ;;   %1 = call i64 @llvm.aarch64.sve.cnth(i32 31)
11 ;;   %rem = urem i64 %0, %1
12 ;;   ret i64 %rem
13 ;; }
15 ;; into
17 ;; define i64 @f1() #0 {
18 ;; entry:
19 ;;   %0 = call i64 @llvm.vscale.i64()
20 ;;   %1 = shl nuw nsw i64 %0, 4
21 ;;   %2 = call i64 @llvm.vscale.i64()
22 ;;   %3 = shl nuw nsw i64 %2, 3
23 ;;   %4 = add nsw i64 %3, -1
24 ;;   %rem = and i64 %1, %4
25 ;;   ret i64 %rem
26 ;; }
28 ;; InstCombine would have folded the original to returning 0 if the vscale
29 ;; calls were the same Value*, but since there's two of them it doesn't
30 ;; work and we convert the urem to add/and. CSE then gets rid of the extra
31 ;; vscale, leaving us with a new pattern to match. This only works because
32 ;; vscale is known to be a power of 2 (assuming there's a defined range for it).
34 define i64 @f1() #0 {
35 ; CHECK-LABEL: define i64 @f1
36 ; CHECK-SAME: () #[[ATTR0:[0-9]+]] {
37 ; CHECK-NEXT:  entry:
38 ; CHECK-NEXT:    ret i64 0
40 entry:
41   %0 = call i64 @llvm.vscale.i64()
42   %1 = shl i64 %0, 4
43   %2 = shl i64 %0, 3
44   %3 = add i64 %2, -1
45   %rem = and i64 %1, %3
46   ret i64 %rem
49 ;; Make sure it works if the value could also be zero.
50 define i64 @test_pow2_or_zero(i64 %arg) {
51 ; CHECK-LABEL: define i64 @test_pow2_or_zero
52 ; CHECK-SAME: (i64 [[ARG:%.*]]) {
53 ; CHECK-NEXT:    ret i64 0
55   %neg = sub i64 0, %arg
56   %x = and i64 %neg, %arg
57   %shl1 = shl i64 %x, 4
58   %shl2 = shl i64 %x, 3
59   %mask = add i64 %shl2, -1
60   %rem = and i64 %mask, %shl1
61   ret i64 %rem
64 ;; Make sure it doesn't work if the value isn't known to be a power of 2.
65 ;; In this case a vscale without a `vscale_range` attribute on the function.
66 define i64 @no_pow2() {
67 ; CHECK-LABEL: define i64 @no_pow2() {
68 ; CHECK-NEXT:  entry:
69 ; CHECK-NEXT:    [[TMP0:%.*]] = call i64 @llvm.vscale.i64()
70 ; CHECK-NEXT:    [[TMP1:%.*]] = shl i64 [[TMP0]], 4
71 ; CHECK-NEXT:    [[TMP2:%.*]] = shl i64 [[TMP0]], 3
72 ; CHECK-NEXT:    [[TMP3:%.*]] = add i64 [[TMP2]], -1
73 ; CHECK-NEXT:    [[REM:%.*]] = and i64 [[TMP1]], [[TMP3]]
74 ; CHECK-NEXT:    ret i64 [[REM]]
76 entry:
77   %0 = call i64 @llvm.vscale.i64()
78   %1 = shl i64 %0, 4
79   %2 = shl i64 %0, 3
80   %3 = add i64 %2, -1
81   %rem = and i64 %1, %3
82   ret i64 %rem
85 ;; Make sure it doesn't work if the shift on the -1 side is greater
86 define i64 @minus_shift_greater(i64 %arg) {
87 ; CHECK-LABEL: define i64 @minus_shift_greater
88 ; CHECK-SAME: (i64 [[ARG:%.*]]) {
89 ; CHECK-NEXT:    [[NEG:%.*]] = sub i64 0, [[ARG]]
90 ; CHECK-NEXT:    [[X:%.*]] = and i64 [[NEG]], [[ARG]]
91 ; CHECK-NEXT:    [[SHL1:%.*]] = shl i64 [[X]], 3
92 ; CHECK-NEXT:    [[SHL2:%.*]] = shl i64 [[X]], 4
93 ; CHECK-NEXT:    [[MASK:%.*]] = add i64 [[SHL2]], -1
94 ; CHECK-NEXT:    [[REM:%.*]] = and i64 [[SHL1]], [[MASK]]
95 ; CHECK-NEXT:    ret i64 [[REM]]
97   %neg = sub i64 0, %arg
98   %x = and i64 %neg, %arg
99   %shl1 = shl i64 %x, 3
100   %shl2 = shl i64 %x, 4
101   %mask = add i64 %shl2, -1
102   %rem = and i64 %shl1, %mask
103   ret i64 %rem
106 ;; Make sure it doesn't work if the subtract isn't one.
107 define i64 @sub2(i64 %arg) {
108 ; CHECK-LABEL: define i64 @sub2
109 ; CHECK-SAME: (i64 [[ARG:%.*]]) {
110 ; CHECK-NEXT:    [[NEG:%.*]] = sub i64 0, [[ARG]]
111 ; CHECK-NEXT:    [[X:%.*]] = and i64 [[NEG]], [[ARG]]
112 ; CHECK-NEXT:    [[SHL1:%.*]] = shl i64 [[X]], 4
113 ; CHECK-NEXT:    [[SHL2:%.*]] = shl i64 [[X]], 3
114 ; CHECK-NEXT:    [[MASK:%.*]] = add i64 [[SHL2]], -2
115 ; CHECK-NEXT:    [[REM:%.*]] = and i64 [[SHL1]], [[MASK]]
116 ; CHECK-NEXT:    ret i64 [[REM]]
118   %neg = sub i64 0, %arg
119   %x = and i64 %neg, %arg
120   %shl1 = shl i64 %x, 4
121   %shl2 = shl i64 %x, 3
122   %mask = add i64 %shl2, -2
123   %rem = and i64 %shl1, %mask
124   ret i64 %rem
127 ;; Make sure it doesn't work with a right shift
128 ;; Make sure it doesn't work if the subtract isn't one.
129 define i64 @rightshift(i64 %arg) {
130 ; CHECK-LABEL: define i64 @rightshift
131 ; CHECK-SAME: (i64 [[ARG:%.*]]) {
132 ; CHECK-NEXT:    [[NEG:%.*]] = sub i64 0, [[ARG]]
133 ; CHECK-NEXT:    [[X:%.*]] = and i64 [[NEG]], [[ARG]]
134 ; CHECK-NEXT:    [[SHL1:%.*]] = shl i64 [[X]], 4
135 ; CHECK-NEXT:    [[SHL2:%.*]] = lshr i64 [[X]], 3
136 ; CHECK-NEXT:    [[MASK:%.*]] = add i64 [[SHL2]], -1
137 ; CHECK-NEXT:    [[REM:%.*]] = and i64 [[SHL1]], [[MASK]]
138 ; CHECK-NEXT:    ret i64 [[REM]]
140   %neg = sub i64 0, %arg
141   %x = and i64 %neg, %arg
142   %shl1 = shl i64 %x, 4
143   %shl2 = lshr i64 %x, 3
144   %mask = add i64 %shl2, -1
145   %rem = and i64 %shl1, %mask
146   ret i64 %rem
149 declare i64 @llvm.vscale.i64()
151 attributes #0 = { vscale_range(1,16) }