1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4define i64 @test_lshr(i1 %c) { 5; CHECK-LABEL: @test_lshr( 6; CHECK-NEXT: entry: 7; CHECK-NEXT: br label [[LOOP:%.*]] 8; CHECK: loop: 9; CHECK-NEXT: br i1 [[C:%.*]], 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 %c, label %exit, label %loop 19exit: 20 %res = or i64 %iv.lshr, 1023 21 ret i64 %res 22} 23 24define i64 @test_add(i1 %c) { 25; CHECK-LABEL: @test_add( 26; CHECK-NEXT: entry: 27; CHECK-NEXT: br label [[LOOP:%.*]] 28; CHECK: loop: 29; CHECK-NEXT: br i1 [[C:%.*]], label [[EXIT:%.*]], label [[LOOP]] 30; CHECK: exit: 31; CHECK-NEXT: ret i64 0 32; 33entry: 34 br label %loop 35loop: 36 %iv = phi i64 [8, %entry], [%iv.next, %loop] 37 %iv.next = add nuw i64 %iv, 4 38 br i1 %c, label %exit, label %loop 39exit: 40 %res = and i64 %iv, 1 41 ret i64 %res 42} 43 44define i64 @test_sub(i1 %c) { 45; CHECK-LABEL: @test_sub( 46; CHECK-NEXT: entry: 47; CHECK-NEXT: br label [[LOOP:%.*]] 48; CHECK: loop: 49; CHECK-NEXT: br i1 [[C:%.*]], label [[EXIT:%.*]], label [[LOOP]] 50; CHECK: exit: 51; CHECK-NEXT: ret i64 0 52; 53entry: 54 br label %loop 55loop: 56 %iv = phi i64 [8, %entry], [%iv.next, %loop] 57 %iv.next = sub nuw i64 %iv, 4 58 br i1 %c, label %exit, label %loop 59exit: 60 %res = and i64 %iv, 1 61 ret i64 %res 62} 63 64define i64 @test_mul(i1 %c) { 65; CHECK-LABEL: @test_mul( 66; CHECK-NEXT: entry: 67; CHECK-NEXT: br label [[LOOP:%.*]] 68; CHECK: loop: 69; CHECK-NEXT: br i1 [[C:%.*]], label [[EXIT:%.*]], label [[LOOP]] 70; CHECK: exit: 71; CHECK-NEXT: ret i64 0 72; 73entry: 74 br label %loop 75loop: 76 %iv = phi i64 [8, %entry], [%iv.next, %loop] 77 %iv.next = mul i64 %iv, 2 78 br i1 %c, label %exit, label %loop 79exit: 80 %res = and i64 %iv, 2 81 ret i64 %res 82} 83 84define i64 @test_udiv(i1 %c) { 85; CHECK-LABEL: @test_udiv( 86; CHECK-NEXT: entry: 87; CHECK-NEXT: br label [[LOOP:%.*]] 88; CHECK: loop: 89; CHECK-NEXT: br i1 [[C:%.*]], label [[EXIT:%.*]], label [[LOOP]] 90; CHECK: exit: 91; CHECK-NEXT: ret i64 0 92; 93entry: 94 br label %loop 95loop: 96 %iv = phi i64 [9, %entry], [%iv.next, %loop] 97 %iv.next = udiv i64 %iv, 3 98 br i1 %c, label %exit, label %loop 99exit: 100 %res = and i64 %iv, 16 101 ret i64 %res 102} 103 104define i64 @test_udiv_neg(i1 %c) { 105; CHECK-LABEL: @test_udiv_neg( 106; CHECK-NEXT: entry: 107; CHECK-NEXT: br label [[LOOP:%.*]] 108; CHECK: loop: 109; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 2, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] 110; CHECK-NEXT: [[IV_NEXT]] = udiv i64 9, [[IV]] 111; CHECK-NEXT: br i1 [[C:%.*]], label [[EXIT:%.*]], label [[LOOP]] 112; CHECK: exit: 113; CHECK-NEXT: [[RES:%.*]] = and i64 [[IV]], 4 114; CHECK-NEXT: ret i64 [[RES]] 115; 116entry: 117 br label %loop 118loop: 119 %iv = phi i64 [2, %entry], [%iv.next, %loop] 120 %iv.next = udiv i64 9, %iv 121 br i1 %c, label %exit, label %loop 122exit: 123 %res = and i64 %iv, 4 124 ret i64 %res 125} 126 127define i64 @test_urem(i1 %c) { 128; CHECK-LABEL: @test_urem( 129; CHECK-NEXT: entry: 130; CHECK-NEXT: br label [[LOOP:%.*]] 131; CHECK: loop: 132; CHECK-NEXT: br i1 [[C:%.*]], label [[EXIT:%.*]], label [[LOOP]] 133; CHECK: exit: 134; CHECK-NEXT: ret i64 0 135; 136entry: 137 br label %loop 138loop: 139 %iv = phi i64 [3, %entry], [%iv.next, %loop] 140 %iv.next = urem i64 9, %iv 141 br i1 %c, label %exit, label %loop 142exit: 143 %res = and i64 %iv, 4 144 ret i64 %res 145} 146 147define i64 @test_and(i1 %c) { 148; CHECK-LABEL: @test_and( 149; CHECK-NEXT: entry: 150; CHECK-NEXT: br label [[LOOP:%.*]] 151; CHECK: loop: 152; CHECK-NEXT: br i1 [[C:%.*]], label [[EXIT:%.*]], label [[LOOP]] 153; CHECK: exit: 154; CHECK-NEXT: ret i64 2047 155; 156entry: 157 br label %loop 158loop: 159 %iv = phi i64 [1025, %entry], [%iv.next, %loop] 160 %iv.next = and i64 %iv, 1024 161 br i1 %c, label %exit, label %loop 162exit: 163 %res = or i64 %iv, 1023 164 ret i64 %res 165} 166 167define i64 @test_or(i1 %c) { 168; CHECK-LABEL: @test_or( 169; CHECK-NEXT: entry: 170; CHECK-NEXT: br label [[LOOP:%.*]] 171; CHECK: loop: 172; CHECK-NEXT: br i1 [[C:%.*]], label [[EXIT:%.*]], label [[LOOP]] 173; CHECK: exit: 174; CHECK-NEXT: ret i64 2047 175; 176entry: 177 br label %loop 178loop: 179 %iv = phi i64 [1025, %entry], [%iv.next, %loop] 180 %iv.next = or i64 %iv, 1024 181 br i1 %c, label %exit, label %loop 182exit: 183 %res = or i64 %iv, 1023 184 ret i64 %res 185} 186 187define i64 @test_ashr_zeros(i1 %c) { 188; CHECK-LABEL: @test_ashr_zeros( 189; CHECK-NEXT: entry: 190; CHECK-NEXT: br label [[LOOP:%.*]] 191; CHECK: loop: 192; CHECK-NEXT: br i1 [[C:%.*]], label [[EXIT:%.*]], label [[LOOP]] 193; CHECK: exit: 194; CHECK-NEXT: ret i64 1023 195; 196entry: 197 br label %loop 198loop: 199 %iv.ashr = phi i64 [1023, %entry], [%iv.ashr.next, %loop] 200 %iv.ashr.next = ashr i64 %iv.ashr, 1 201 br i1 %c, label %exit, label %loop 202exit: 203 %res = or i64 %iv.ashr, 1023 204 ret i64 %res 205} 206 207define i64 @test_ashr_ones(i1 %c) { 208; CHECK-LABEL: @test_ashr_ones( 209; CHECK-NEXT: entry: 210; CHECK-NEXT: br label [[LOOP:%.*]] 211; CHECK: loop: 212; CHECK-NEXT: br i1 [[C:%.*]], label [[EXIT:%.*]], label [[LOOP]] 213; CHECK: exit: 214; CHECK-NEXT: ret i64 -1 215; 216entry: 217 br label %loop 218loop: 219 %iv.ashr = phi i64 [-1023, %entry], [%iv.ashr.next, %loop] 220 %iv.ashr.next = ashr i64 %iv.ashr, 1 221 br i1 %c, label %exit, label %loop 222exit: 223 %res = or i64 %iv.ashr, 1023 224 ret i64 %res 225} 226 227; Same as previous, but swapped operands to phi 228define i64 @test_ashr_ones2(i1 %c) { 229; CHECK-LABEL: @test_ashr_ones2( 230; CHECK-NEXT: entry: 231; CHECK-NEXT: br label [[LOOP:%.*]] 232; CHECK: loop: 233; CHECK-NEXT: br i1 [[C:%.*]], label [[EXIT:%.*]], label [[LOOP]] 234; CHECK: exit: 235; CHECK-NEXT: ret i64 -1 236; 237entry: 238 br label %loop 239loop: 240 %iv.ashr = phi i64 [%iv.ashr.next, %loop], [-1023, %entry] 241 %iv.ashr.next = ashr i64 %iv.ashr, 1 242 br i1 %c, label %exit, label %loop 243exit: 244 %res = or i64 %iv.ashr, 1023 245 ret i64 %res 246} 247 248 249; negative case for when start is unknown 250define i64 @test_ashr_unknown(i1 %c, i64 %start) { 251; CHECK-LABEL: @test_ashr_unknown( 252; CHECK-NEXT: entry: 253; CHECK-NEXT: br label [[LOOP:%.*]] 254; CHECK: loop: 255; CHECK-NEXT: [[IV_ASHR:%.*]] = phi i64 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_ASHR_NEXT:%.*]], [[LOOP]] ] 256; CHECK-NEXT: [[IV_ASHR_NEXT]] = ashr i64 [[IV_ASHR]], 1 257; CHECK-NEXT: br i1 [[C:%.*]], label [[EXIT:%.*]], label [[LOOP]] 258; CHECK: exit: 259; CHECK-NEXT: [[RES:%.*]] = or i64 [[IV_ASHR]], 1023 260; CHECK-NEXT: ret i64 [[RES]] 261; 262entry: 263 br label %loop 264loop: 265 %iv.ashr = phi i64 [%start, %entry], [%iv.ashr.next, %loop] 266 %iv.ashr.next = ashr i64 %iv.ashr, 1 267 br i1 %c, label %exit, label %loop 268exit: 269 %res = or i64 %iv.ashr, 1023 270 ret i64 %res 271} 272 273; Negative case where we don't have a (shift) recurrence because the operands 274; of the ashr are swapped. (This does end up being a divide recurrence.) 275define i64 @test_ashr_wrong_op(i1 %c, i64 %start) { 276; CHECK-LABEL: @test_ashr_wrong_op( 277; CHECK-NEXT: entry: 278; CHECK-NEXT: br label [[LOOP:%.*]] 279; CHECK: loop: 280; CHECK-NEXT: [[IV_ASHR:%.*]] = phi i64 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_ASHR_NEXT:%.*]], [[LOOP]] ] 281; CHECK-NEXT: [[IV_ASHR_NEXT]] = lshr i64 1, [[IV_ASHR]] 282; CHECK-NEXT: br i1 [[C:%.*]], label [[EXIT:%.*]], label [[LOOP]] 283; CHECK: exit: 284; CHECK-NEXT: [[RES:%.*]] = or i64 [[IV_ASHR]], 1023 285; CHECK-NEXT: ret i64 [[RES]] 286; 287entry: 288 br label %loop 289loop: 290 %iv.ashr = phi i64 [%start, %entry], [%iv.ashr.next, %loop] 291 %iv.ashr.next = ashr i64 1, %iv.ashr 292 br i1 %c, label %exit, label %loop 293exit: 294 %res = or i64 %iv.ashr, 1023 295 ret i64 %res 296} 297 298 299define i64 @test_shl(i1 %c) { 300; CHECK-LABEL: @test_shl( 301; CHECK-NEXT: entry: 302; CHECK-NEXT: br label [[LOOP:%.*]] 303; CHECK: loop: 304; CHECK-NEXT: br i1 [[C:%.*]], label [[EXIT:%.*]], label [[LOOP]] 305; CHECK: exit: 306; CHECK-NEXT: ret i64 0 307; 308entry: 309 br label %loop 310loop: 311 %iv.shl = phi i64 [8, %entry], [%iv.shl.next, %loop] 312 %iv.shl.next = shl i64 %iv.shl, 1 313 br i1 %c, label %exit, label %loop 314exit: 315 %res = and i64 %iv.shl, 7 316 ret i64 %res 317} 318