1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -instcombine -S | FileCheck %s
3
4define i64 @test_lshr() {
5; CHECK-LABEL: @test_lshr(
6; CHECK-NEXT:  entry:
7; CHECK-NEXT:    br label [[LOOP:%.*]]
8; CHECK:       loop:
9; CHECK-NEXT:    br i1 undef, label [[EXIT:%.*]], label [[LOOP]]
10; CHECK:       exit:
11; CHECK-NEXT:    ret i64 1023
12;
13entry:
14  br label %loop
15loop:
16  %iv.lshr = phi i64 [1023, %entry], [%iv.lshr.next, %loop]
17  %iv.lshr.next = lshr i64 %iv.lshr, 1
18  br i1 undef, label %exit, label %loop
19exit:
20  %res = or i64 %iv.lshr, 1023
21  ret i64 %res
22}
23
24define i64 @test_ashr_zeros() {
25; CHECK-LABEL: @test_ashr_zeros(
26; CHECK-NEXT:  entry:
27; CHECK-NEXT:    br label [[LOOP:%.*]]
28; CHECK:       loop:
29; CHECK-NEXT:    br i1 undef, label [[EXIT:%.*]], label [[LOOP]]
30; CHECK:       exit:
31; CHECK-NEXT:    ret i64 1023
32;
33entry:
34  br label %loop
35loop:
36  %iv.ashr = phi i64 [1023, %entry], [%iv.ashr.next, %loop]
37  %iv.ashr.next = ashr i64 %iv.ashr, 1
38  br i1 undef, label %exit, label %loop
39exit:
40  %res = or i64 %iv.ashr, 1023
41  ret i64 %res
42}
43
44define i64 @test_ashr_ones() {
45; CHECK-LABEL: @test_ashr_ones(
46; CHECK-NEXT:  entry:
47; CHECK-NEXT:    br label [[LOOP:%.*]]
48; CHECK:       loop:
49; CHECK-NEXT:    br i1 undef, label [[EXIT:%.*]], label [[LOOP]]
50; CHECK:       exit:
51; CHECK-NEXT:    ret i64 -1
52;
53entry:
54  br label %loop
55loop:
56  %iv.ashr = phi i64 [-1023, %entry], [%iv.ashr.next, %loop]
57  %iv.ashr.next = ashr i64 %iv.ashr, 1
58  br i1 undef, label %exit, label %loop
59exit:
60  %res = or i64 %iv.ashr, 1023
61  ret i64 %res
62}
63
64; Same as previous, but swapped operands to phi
65define i64 @test_ashr_ones2() {
66; CHECK-LABEL: @test_ashr_ones2(
67; CHECK-NEXT:  entry:
68; CHECK-NEXT:    br label [[LOOP:%.*]]
69; CHECK:       loop:
70; CHECK-NEXT:    br i1 undef, label [[EXIT:%.*]], label [[LOOP]]
71; CHECK:       exit:
72; CHECK-NEXT:    ret i64 -1
73;
74entry:
75  br label %loop
76loop:
77  %iv.ashr = phi i64 [%iv.ashr.next, %loop], [-1023, %entry]
78  %iv.ashr.next = ashr i64 %iv.ashr, 1
79  br i1 undef, label %exit, label %loop
80exit:
81  %res = or i64 %iv.ashr, 1023
82  ret i64 %res
83}
84
85
86; negative case for when start is unknown
87define i64 @test_ashr_unknown(i64 %start) {
88; CHECK-LABEL: @test_ashr_unknown(
89; CHECK-NEXT:  entry:
90; CHECK-NEXT:    br label [[LOOP:%.*]]
91; CHECK:       loop:
92; CHECK-NEXT:    [[IV_ASHR:%.*]] = phi i64 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_ASHR_NEXT:%.*]], [[LOOP]] ]
93; CHECK-NEXT:    [[IV_ASHR_NEXT]] = ashr i64 [[IV_ASHR]], 1
94; CHECK-NEXT:    br i1 undef, label [[EXIT:%.*]], label [[LOOP]]
95; CHECK:       exit:
96; CHECK-NEXT:    [[RES:%.*]] = or i64 [[IV_ASHR]], 1023
97; CHECK-NEXT:    ret i64 [[RES]]
98;
99entry:
100  br label %loop
101loop:
102  %iv.ashr = phi i64 [%start, %entry], [%iv.ashr.next, %loop]
103  %iv.ashr.next = ashr i64 %iv.ashr, 1
104  br i1 undef, label %exit, label %loop
105exit:
106  %res = or i64 %iv.ashr, 1023
107  ret i64 %res
108}
109
110; Negative case where we don't have a (shift) recurrence because the operands
111; of the ashr are swapped.  (This does end up being a divide recurrence.)
112define i64 @test_ashr_wrong_op(i64 %start) {
113; CHECK-LABEL: @test_ashr_wrong_op(
114; CHECK-NEXT:  entry:
115; CHECK-NEXT:    br label [[LOOP:%.*]]
116; CHECK:       loop:
117; CHECK-NEXT:    [[IV_ASHR:%.*]] = phi i64 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_ASHR_NEXT:%.*]], [[LOOP]] ]
118; CHECK-NEXT:    [[IV_ASHR_NEXT]] = lshr i64 1, [[IV_ASHR]]
119; CHECK-NEXT:    br i1 undef, label [[EXIT:%.*]], label [[LOOP]]
120; CHECK:       exit:
121; CHECK-NEXT:    [[RES:%.*]] = or i64 [[IV_ASHR]], 1023
122; CHECK-NEXT:    ret i64 [[RES]]
123;
124entry:
125  br label %loop
126loop:
127  %iv.ashr = phi i64 [%start, %entry], [%iv.ashr.next, %loop]
128  %iv.ashr.next = ashr i64 1, %iv.ashr
129  br i1 undef, label %exit, label %loop
130exit:
131  %res = or i64 %iv.ashr, 1023
132  ret i64 %res
133}
134
135
136define i64 @test_shl() {
137; CHECK-LABEL: @test_shl(
138; CHECK-NEXT:  entry:
139; CHECK-NEXT:    br label [[LOOP:%.*]]
140; CHECK:       loop:
141; CHECK-NEXT:    br i1 undef, label [[EXIT:%.*]], label [[LOOP]]
142; CHECK:       exit:
143; CHECK-NEXT:    ret i64 0
144;
145entry:
146  br label %loop
147loop:
148  %iv.shl = phi i64 [8, %entry], [%iv.shl.next, %loop]
149  %iv.shl.next = shl i64 %iv.shl, 1
150  br i1 undef, label %exit, label %loop
151exit:
152  %res = and i64 %iv.shl, 7
153  ret i64 %res
154}
155