1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=correlated-propagation -S | FileCheck %s 3 4declare void @llvm.assume(i1) 5declare i8 @llvm.umin(i8, i8) 6declare i8 @llvm.umax(i8, i8) 7declare i8 @llvm.smin(i8, i8) 8declare i8 @llvm.smax(i8, i8) 9 10; If we don't know anything about the arguments, we can't do anything. 11 12define i8 @test0(i8 %x, i8 %y) { 13; CHECK-LABEL: @test0( 14; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) 15; CHECK-NEXT: ret i8 [[R]] 16; 17 %r = call i8 @llvm.umin(i8 %x, i8 %y) 18 ret i8 %r 19} 20define i8 @test1(i8 %x, i8 %y) { 21; CHECK-LABEL: @test1( 22; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) 23; CHECK-NEXT: ret i8 [[R]] 24; 25 %r = call i8 @llvm.umax(i8 %x, i8 %y) 26 ret i8 %r 27} 28define i8 @test2(i8 %x, i8 %y) { 29; CHECK-LABEL: @test2( 30; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) 31; CHECK-NEXT: ret i8 [[R]] 32; 33 %r = call i8 @llvm.smin(i8 %x, i8 %y) 34 ret i8 %r 35} 36define i8 @test3(i8 %x, i8 %y) { 37; CHECK-LABEL: @test3( 38; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) 39; CHECK-NEXT: ret i8 [[R]] 40; 41 %r = call i8 @llvm.smax(i8 %x, i8 %y) 42 ret i8 %r 43} 44 45; However, if we do know the ranges of arguments, we sometimes can tell that either one is always picked. 46 47define i8 @test4(i8 %x) { 48; CHECK-LABEL: @test4( 49; CHECK-NEXT: [[LIM:%.*]] = icmp ule i8 [[X:%.*]], 43 50; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 51; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 42) 52; CHECK-NEXT: ret i8 [[R]] 53; 54 %lim = icmp ule i8 %x, 43 55 call void @llvm.assume(i1 %lim) 56 %r = call i8 @llvm.umin(i8 %x, i8 42) 57 ret i8 %r 58} 59define i8 @test5(i8 %x) { 60; CHECK-LABEL: @test5( 61; CHECK-NEXT: [[LIM:%.*]] = icmp ule i8 [[X:%.*]], 42 62; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 63; CHECK-NEXT: ret i8 [[X]] 64; 65 %lim = icmp ule i8 %x, 42 66 call void @llvm.assume(i1 %lim) 67 %r = call i8 @llvm.umin(i8 %x, i8 42) 68 ret i8 %r 69} 70define i8 @test6(i8 %x) { 71; CHECK-LABEL: @test6( 72; CHECK-NEXT: [[LIM:%.*]] = icmp uge i8 [[X:%.*]], 42 73; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 74; CHECK-NEXT: ret i8 42 75; 76 %lim = icmp uge i8 %x, 42 77 call void @llvm.assume(i1 %lim) 78 %r = call i8 @llvm.umin(i8 %x, i8 42) 79 ret i8 %r 80} 81define i8 @test7(i8 %x) { 82; CHECK-LABEL: @test7( 83; CHECK-NEXT: [[LIM:%.*]] = icmp uge i8 [[X:%.*]], 41 84; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 85; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 42) 86; CHECK-NEXT: ret i8 [[R]] 87; 88 %lim = icmp uge i8 %x, 41 89 call void @llvm.assume(i1 %lim) 90 %r = call i8 @llvm.umin(i8 %x, i8 42) 91 ret i8 %r 92} 93 94define i8 @test8(i8 %x) { 95; CHECK-LABEL: @test8( 96; CHECK-NEXT: [[LIM:%.*]] = icmp uge i8 [[X:%.*]], 41 97; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 98; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.umax.i8(i8 [[X]], i8 42) 99; CHECK-NEXT: ret i8 [[R]] 100; 101 %lim = icmp uge i8 %x, 41 102 call void @llvm.assume(i1 %lim) 103 %r = call i8 @llvm.umax(i8 %x, i8 42) 104 ret i8 %r 105} 106define i8 @test9(i8 %x) { 107; CHECK-LABEL: @test9( 108; CHECK-NEXT: [[LIM:%.*]] = icmp uge i8 [[X:%.*]], 42 109; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 110; CHECK-NEXT: ret i8 [[X]] 111; 112 %lim = icmp uge i8 %x, 42 113 call void @llvm.assume(i1 %lim) 114 %r = call i8 @llvm.umax(i8 %x, i8 42) 115 ret i8 %r 116} 117define i8 @test10(i8 %x) { 118; CHECK-LABEL: @test10( 119; CHECK-NEXT: [[LIM:%.*]] = icmp ule i8 [[X:%.*]], 42 120; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 121; CHECK-NEXT: ret i8 42 122; 123 %lim = icmp ule i8 %x, 42 124 call void @llvm.assume(i1 %lim) 125 %r = call i8 @llvm.umax(i8 %x, i8 42) 126 ret i8 %r 127} 128define i8 @test11(i8 %x) { 129; CHECK-LABEL: @test11( 130; CHECK-NEXT: [[LIM:%.*]] = icmp ule i8 [[X:%.*]], 43 131; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 132; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.umax.i8(i8 [[X]], i8 42) 133; CHECK-NEXT: ret i8 [[R]] 134; 135 %lim = icmp ule i8 %x, 43 136 call void @llvm.assume(i1 %lim) 137 %r = call i8 @llvm.umax(i8 %x, i8 42) 138 ret i8 %r 139} 140 141define i8 @test12(i8 %x) { 142; CHECK-LABEL: @test12( 143; CHECK-NEXT: [[LIM:%.*]] = icmp sle i8 [[X:%.*]], 43 144; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 145; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.smin.i8(i8 [[X]], i8 42) 146; CHECK-NEXT: ret i8 [[R]] 147; 148 %lim = icmp sle i8 %x, 43 149 call void @llvm.assume(i1 %lim) 150 %r = call i8 @llvm.smin(i8 %x, i8 42) 151 ret i8 %r 152} 153define i8 @test13(i8 %x) { 154; CHECK-LABEL: @test13( 155; CHECK-NEXT: [[LIM:%.*]] = icmp sle i8 [[X:%.*]], 42 156; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 157; CHECK-NEXT: ret i8 [[X]] 158; 159 %lim = icmp sle i8 %x, 42 160 call void @llvm.assume(i1 %lim) 161 %r = call i8 @llvm.smin(i8 %x, i8 42) 162 ret i8 %r 163} 164define i8 @test14(i8 %x) { 165; CHECK-LABEL: @test14( 166; CHECK-NEXT: [[LIM:%.*]] = icmp sge i8 [[X:%.*]], 42 167; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 168; CHECK-NEXT: ret i8 42 169; 170 %lim = icmp sge i8 %x, 42 171 call void @llvm.assume(i1 %lim) 172 %r = call i8 @llvm.smin(i8 %x, i8 42) 173 ret i8 %r 174} 175define i8 @test15(i8 %x) { 176; CHECK-LABEL: @test15( 177; CHECK-NEXT: [[LIM:%.*]] = icmp sge i8 [[X:%.*]], 41 178; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 179; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 42) 180; CHECK-NEXT: ret i8 [[TMP1]] 181; 182 %lim = icmp sge i8 %x, 41 183 call void @llvm.assume(i1 %lim) 184 %r = call i8 @llvm.smin(i8 %x, i8 42) 185 ret i8 %r 186} 187 188define i8 @test16(i8 %x) { 189; CHECK-LABEL: @test16( 190; CHECK-NEXT: [[LIM:%.*]] = icmp sge i8 [[X:%.*]], 41 191; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 192; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[X]], i8 42) 193; CHECK-NEXT: ret i8 [[TMP1]] 194; 195 %lim = icmp sge i8 %x, 41 196 call void @llvm.assume(i1 %lim) 197 %r = call i8 @llvm.smax(i8 %x, i8 42) 198 ret i8 %r 199} 200define i8 @test17(i8 %x) { 201; CHECK-LABEL: @test17( 202; CHECK-NEXT: [[LIM:%.*]] = icmp sge i8 [[X:%.*]], 42 203; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 204; CHECK-NEXT: ret i8 [[X]] 205; 206 %lim = icmp sge i8 %x, 42 207 call void @llvm.assume(i1 %lim) 208 %r = call i8 @llvm.smax(i8 %x, i8 42) 209 ret i8 %r 210} 211define i8 @test18(i8 %x) { 212; CHECK-LABEL: @test18( 213; CHECK-NEXT: [[LIM:%.*]] = icmp sle i8 [[X:%.*]], 42 214; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 215; CHECK-NEXT: ret i8 42 216; 217 %lim = icmp sle i8 %x, 42 218 call void @llvm.assume(i1 %lim) 219 %r = call i8 @llvm.smax(i8 %x, i8 42) 220 ret i8 %r 221} 222define i8 @test19(i8 %x) { 223; CHECK-LABEL: @test19( 224; CHECK-NEXT: [[LIM:%.*]] = icmp sle i8 [[X:%.*]], 43 225; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 226; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.smax.i8(i8 [[X]], i8 42) 227; CHECK-NEXT: ret i8 [[R]] 228; 229 %lim = icmp sle i8 %x, 43 230 call void @llvm.assume(i1 %lim) 231 %r = call i8 @llvm.smax(i8 %x, i8 42) 232 ret i8 %r 233} 234 235declare void @body(i32) 236 237define void @test_bidirectional() { 238; CHECK-LABEL: @test_bidirectional( 239; CHECK-NEXT: entry: 240; CHECK-NEXT: br label [[FOR_BODY:%.*]] 241; CHECK: for.body: 242; CHECK-NEXT: [[INDVAR:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ] 243; CHECK-NEXT: call void @body(i32 65535) 244; CHECK-NEXT: [[INC]] = add nsw i32 [[INDVAR]], 1 245; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[INDVAR]], 65535 246; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[EXIT:%.*]] 247; CHECK: exit: 248; CHECK-NEXT: ret void 249; 250entry: 251 br label %for.body 252 253for.body: 254 %indvar = phi i32 [ 0, %entry ], [ %inc, %for.body ] 255 %smax = call i32 @llvm.smax.i32(i32 %indvar, i32 65535) 256 call void @body(i32 %smax) 257 %inc = add nsw i32 %indvar, 1 258 %cmp = icmp slt i32 %indvar, 65535 259 br i1 %cmp, label %for.body, label %exit 260 261exit: 262 ret void 263} 264 265define i64 @test_at_use(i1 %cond, i64 %x) { 266; CHECK-LABEL: @test_at_use( 267; CHECK-NEXT: entry: 268; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[IF_END:%.*]] 269; CHECK: bb1: 270; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[X:%.*]], 0 271; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END]] 272; CHECK: if.then: 273; CHECK-NEXT: ret i64 0 274; CHECK: if.end: 275; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ [[X]], [[BB1]] ], [ 0, [[ENTRY:%.*]] ] 276; CHECK-NEXT: ret i64 [[PHI]] 277; 278entry: 279 br i1 %cond, label %bb1, label %if.end 280 281bb1: 282 %val = call i64 @llvm.smax.i64(i64 %x, i64 -1) 283 %cmp = icmp slt i64 %x, 0 284 br i1 %cmp, label %if.then, label %if.end 285 286if.then: 287 ret i64 0 288 289if.end: 290 %phi = phi i64 [%val, %bb1], [0, %entry] 291 ret i64 %phi 292} 293 294define i8 @test_smax_to_umax_nneg(i8 %a, i8 %b) { 295; CHECK-LABEL: @test_smax_to_umax_nneg( 296; CHECK-NEXT: [[NNEG_A:%.*]] = and i8 [[A:%.*]], 127 297; CHECK-NEXT: [[NNEG_B:%.*]] = and i8 [[B:%.*]], 127 298; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[NNEG_A]], i8 [[NNEG_B]]) 299; CHECK-NEXT: ret i8 [[TMP1]] 300; 301 %nneg_a = and i8 %a, 127 302 %nneg_b = and i8 %b, 127 303 %ret = call i8 @llvm.smax.i8(i8 %nneg_a, i8 %nneg_b) 304 ret i8 %ret 305} 306 307define i8 @test_smax_to_umax_neg(i8 %a, i8 %b) { 308; CHECK-LABEL: @test_smax_to_umax_neg( 309; CHECK-NEXT: [[NEG_A:%.*]] = or i8 [[A:%.*]], -128 310; CHECK-NEXT: [[NEG_B:%.*]] = or i8 [[B:%.*]], -128 311; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[NEG_A]], i8 [[NEG_B]]) 312; CHECK-NEXT: ret i8 [[TMP1]] 313; 314 %neg_a = or i8 %a, 128 315 %neg_b = or i8 %b, 128 316 %ret = call i8 @llvm.smax.i8(i8 %neg_a, i8 %neg_b) 317 ret i8 %ret 318} 319 320define i8 @test_smin_to_umin_nneg(i8 %a, i8 %b) { 321; CHECK-LABEL: @test_smin_to_umin_nneg( 322; CHECK-NEXT: [[NNEG_A:%.*]] = and i8 [[A:%.*]], 127 323; CHECK-NEXT: [[NNEG_B:%.*]] = and i8 [[B:%.*]], 127 324; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[NNEG_A]], i8 [[NNEG_B]]) 325; CHECK-NEXT: ret i8 [[TMP1]] 326; 327 %nneg_a = and i8 %a, 127 328 %nneg_b = and i8 %b, 127 329 %ret = call i8 @llvm.smin.i8(i8 %nneg_a, i8 %nneg_b) 330 ret i8 %ret 331} 332 333define i8 @test_smin_to_umin_neg(i8 %a, i8 %b) { 334; CHECK-LABEL: @test_smin_to_umin_neg( 335; CHECK-NEXT: [[NEG_A:%.*]] = or i8 [[A:%.*]], -128 336; CHECK-NEXT: [[NEG_B:%.*]] = or i8 [[B:%.*]], -128 337; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[NEG_A]], i8 [[NEG_B]]) 338; CHECK-NEXT: ret i8 [[TMP1]] 339; 340 %neg_a = or i8 %a, 128 341 %neg_b = or i8 %b, 128 342 %ret = call i8 @llvm.smin.i8(i8 %neg_a, i8 %neg_b) 343 ret i8 %ret 344} 345 346define i8 @test_umax_nneg(i8 %a, i8 %b) { 347; CHECK-LABEL: @test_umax_nneg( 348; CHECK-NEXT: [[NNEG_A:%.*]] = and i8 [[A:%.*]], 127 349; CHECK-NEXT: [[NNEG_B:%.*]] = and i8 [[B:%.*]], 127 350; CHECK-NEXT: [[RET:%.*]] = call i8 @llvm.umax.i8(i8 [[NNEG_A]], i8 [[NNEG_B]]) 351; CHECK-NEXT: ret i8 [[RET]] 352; 353 %nneg_a = and i8 %a, 127 354 %nneg_b = and i8 %b, 127 355 %ret = call i8 @llvm.umax.i8(i8 %nneg_a, i8 %nneg_b) 356 ret i8 %ret 357} 358