1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -instcombine -S | FileCheck %s 3 4; Should fold 5; (%x + %y) u< %x 6; or 7; (%x + %y) u< %y 8; to 9; @llvm.uadd.with.overflow(%x, %y) + extractvalue 10; 11; All tests here have extra uses, to ensure that the pattern isn't perturbed. 12 13declare void @use8(i8) 14declare void @use2x8(<2 x i8>) 15 16define i1 @t0_basic(i8 %x, i8 %y) { 17; CHECK-LABEL: @t0_basic( 18; CHECK-NEXT: [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]] 19; CHECK-NEXT: call void @use8(i8 [[T0]]) 20; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[T0]], [[Y]] 21; CHECK-NEXT: ret i1 [[R]] 22; 23 %t0 = add i8 %x, %y 24 call void @use8(i8 %t0) 25 %r = icmp ult i8 %t0, %y 26 ret i1 %r 27} 28 29define <2 x i1> @t1_vec(<2 x i8> %x, <2 x i8> %y) { 30; CHECK-LABEL: @t1_vec( 31; CHECK-NEXT: [[T0:%.*]] = add <2 x i8> [[X:%.*]], [[Y:%.*]] 32; CHECK-NEXT: call void @use2x8(<2 x i8> [[T0]]) 33; CHECK-NEXT: [[R:%.*]] = icmp ult <2 x i8> [[T0]], [[Y]] 34; CHECK-NEXT: ret <2 x i1> [[R]] 35; 36 %t0 = add <2 x i8> %x, %y 37 call void @use2x8(<2 x i8> %t0) 38 %r = icmp ult <2 x i8> %t0, %y 39 ret <2 x i1> %r 40} 41 42; Commutativity 43 44define i1 @t2_symmetry(i8 %x, i8 %y) { 45; CHECK-LABEL: @t2_symmetry( 46; CHECK-NEXT: [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]] 47; CHECK-NEXT: call void @use8(i8 [[T0]]) 48; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[T0]], [[X]] 49; CHECK-NEXT: ret i1 [[R]] 50; 51 %t0 = add i8 %x, %y 52 call void @use8(i8 %t0) 53 %r = icmp ult i8 %t0, %x ; can check against either of `add` arguments 54 ret i1 %r 55} 56 57declare i8 @gen8() 58 59define i1 @t3_commutative(i8 %x) { 60; CHECK-LABEL: @t3_commutative( 61; CHECK-NEXT: [[Y:%.*]] = call i8 @gen8() 62; CHECK-NEXT: [[T0:%.*]] = add i8 [[Y]], [[X:%.*]] 63; CHECK-NEXT: call void @use8(i8 [[T0]]) 64; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[T0]], [[Y]] 65; CHECK-NEXT: ret i1 [[R]] 66; 67 %y = call i8 @gen8() 68 %t0 = add i8 %y, %x ; swapped 69 call void @use8(i8 %t0) 70 %r = icmp ult i8 %t0, %y 71 ret i1 %r 72} 73 74define i1 @t4_commutative(i8 %x, i8 %y) { 75; CHECK-LABEL: @t4_commutative( 76; CHECK-NEXT: [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]] 77; CHECK-NEXT: call void @use8(i8 [[T0]]) 78; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[T0]], [[Y]] 79; CHECK-NEXT: ret i1 [[R]] 80; 81 %t0 = add i8 %x, %y 82 call void @use8(i8 %t0) 83 %r = icmp ugt i8 %y, %t0 ; swapped 84 ret i1 %r 85} 86 87define i1 @t5_commutative(i8 %x) { 88; CHECK-LABEL: @t5_commutative( 89; CHECK-NEXT: [[Y:%.*]] = call i8 @gen8() 90; CHECK-NEXT: [[T0:%.*]] = add i8 [[Y]], [[X:%.*]] 91; CHECK-NEXT: call void @use8(i8 [[T0]]) 92; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[Y]], [[T0]] 93; CHECK-NEXT: ret i1 [[R]] 94; 95 %y = call i8 @gen8() 96 %t0 = add i8 %y, %x ; swapped 97 call void @use8(i8 %t0) 98 %r = icmp ugt i8 %y, %t0 ; swapped 99 ret i1 %r 100} 101 102; Extra-use tests 103 104define i1 @t6_no_extrause(i8 %x, i8 %y) { 105; CHECK-LABEL: @t6_no_extrause( 106; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[Y:%.*]], -1 107; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[TMP1]], [[X:%.*]] 108; CHECK-NEXT: ret i1 [[R]] 109; 110 %t0 = add i8 %x, %y 111 %r = icmp ult i8 %t0, %y 112 ret i1 %r 113} 114 115; Negative tests 116 117define i1 @n7_different_y(i8 %x, i8 %y0, i8 %y1) { 118; CHECK-LABEL: @n7_different_y( 119; CHECK-NEXT: [[T0:%.*]] = add i8 [[X:%.*]], [[Y0:%.*]] 120; CHECK-NEXT: call void @use8(i8 [[T0]]) 121; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[T0]], [[Y1:%.*]] 122; CHECK-NEXT: ret i1 [[R]] 123; 124 %t0 = add i8 %x, %y0 125 call void @use8(i8 %t0) 126 %r = icmp ult i8 %t0, %y1 127 ret i1 %r 128} 129 130define i1 @n8_wrong_pred0(i8 %x, i8 %y) { 131; CHECK-LABEL: @n8_wrong_pred0( 132; CHECK-NEXT: [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]] 133; CHECK-NEXT: call void @use8(i8 [[T0]]) 134; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[T0]], [[Y]] 135; CHECK-NEXT: ret i1 [[R]] 136; 137 %t0 = add i8 %x, %y 138 call void @use8(i8 %t0) 139 %r = icmp ule i8 %t0, %y 140 ret i1 %r 141} 142 143define i1 @n9_wrong_pred1(i8 %x, i8 %y) { 144; CHECK-LABEL: @n9_wrong_pred1( 145; CHECK-NEXT: [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]] 146; CHECK-NEXT: call void @use8(i8 [[T0]]) 147; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[T0]], [[Y]] 148; CHECK-NEXT: ret i1 [[R]] 149; 150 %t0 = add i8 %x, %y 151 call void @use8(i8 %t0) 152 %r = icmp ugt i8 %t0, %y 153 ret i1 %r 154} 155 156define i1 @n10_wrong_pred2(i8 %x, i8 %y) { 157; CHECK-LABEL: @n10_wrong_pred2( 158; CHECK-NEXT: [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]] 159; CHECK-NEXT: call void @use8(i8 [[T0]]) 160; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[X]], 0 161; CHECK-NEXT: ret i1 [[R]] 162; 163 %t0 = add i8 %x, %y 164 call void @use8(i8 %t0) 165 %r = icmp eq i8 %t0, %y 166 ret i1 %r 167} 168 169define i1 @n11_wrong_pred3(i8 %x, i8 %y) { 170; CHECK-LABEL: @n11_wrong_pred3( 171; CHECK-NEXT: [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]] 172; CHECK-NEXT: call void @use8(i8 [[T0]]) 173; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[X]], 0 174; CHECK-NEXT: ret i1 [[R]] 175; 176 %t0 = add i8 %x, %y 177 call void @use8(i8 %t0) 178 %r = icmp ne i8 %t0, %y 179 ret i1 %r 180} 181 182define i1 @n12_wrong_pred4(i8 %x, i8 %y) { 183; CHECK-LABEL: @n12_wrong_pred4( 184; CHECK-NEXT: [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]] 185; CHECK-NEXT: call void @use8(i8 [[T0]]) 186; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[T0]], [[Y]] 187; CHECK-NEXT: ret i1 [[R]] 188; 189 %t0 = add i8 %x, %y 190 call void @use8(i8 %t0) 191 %r = icmp slt i8 %t0, %y 192 ret i1 %r 193} 194 195define i1 @n13_wrong_pred5(i8 %x, i8 %y) { 196; CHECK-LABEL: @n13_wrong_pred5( 197; CHECK-NEXT: [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]] 198; CHECK-NEXT: call void @use8(i8 [[T0]]) 199; CHECK-NEXT: [[R:%.*]] = icmp sle i8 [[T0]], [[Y]] 200; CHECK-NEXT: ret i1 [[R]] 201; 202 %t0 = add i8 %x, %y 203 call void @use8(i8 %t0) 204 %r = icmp sle i8 %t0, %y 205 ret i1 %r 206} 207 208define i1 @n14_wrong_pred6(i8 %x, i8 %y) { 209; CHECK-LABEL: @n14_wrong_pred6( 210; CHECK-NEXT: [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]] 211; CHECK-NEXT: call void @use8(i8 [[T0]]) 212; CHECK-NEXT: [[R:%.*]] = icmp sgt i8 [[T0]], [[Y]] 213; CHECK-NEXT: ret i1 [[R]] 214; 215 %t0 = add i8 %x, %y 216 call void @use8(i8 %t0) 217 %r = icmp sgt i8 %t0, %y 218 ret i1 %r 219} 220 221define i1 @n15_wrong_pred7(i8 %x, i8 %y) { 222; CHECK-LABEL: @n15_wrong_pred7( 223; CHECK-NEXT: [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]] 224; CHECK-NEXT: call void @use8(i8 [[T0]]) 225; CHECK-NEXT: [[R:%.*]] = icmp sge i8 [[T0]], [[Y]] 226; CHECK-NEXT: ret i1 [[R]] 227; 228 %t0 = add i8 %x, %y 229 call void @use8(i8 %t0) 230 %r = icmp sge i8 %t0, %y 231 ret i1 %r 232} 233