1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4; Tests for foldAndOrOfICmpEqConstantAndICmp 5; https://github.com/llvm/llvm-project/issues/63749 6 7; ============================================================================== 8; (icmp eq X, C) | (icmp ult Other, (X - C)) -> (icmp ule Other, (X - (C + 1))) 9; (icmp ne X, C) & (icmp uge Other, (X - C)) -> (icmp ugt Other, (X - (C + 1))) 10; ============================================================================== 11 12; ============================================================================== 13; Basic tests 14; ============================================================================== 15define i1 @eq_basic(i8 %x, i8 %y) { 16; CHECK-LABEL: define i1 @eq_basic( 17; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { 18; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[X]], -1 19; CHECK-NEXT: [[OR:%.*]] = icmp uge i8 [[TMP1]], [[Y]] 20; CHECK-NEXT: ret i1 [[OR]] 21; 22 %c1 = icmp eq i8 %x, 0 23 %c2 = icmp ugt i8 %x, %y 24 %or = or i1 %c1, %c2 25 ret i1 %or 26} 27 28define i1 @ne_basic_equal_5(i8 %x, i8 %y) { 29; CHECK-LABEL: define i1 @ne_basic_equal_5( 30; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { 31; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[X]], -6 32; CHECK-NEXT: [[AND:%.*]] = icmp ult i8 [[TMP1]], [[Y]] 33; CHECK-NEXT: ret i1 [[AND]] 34; 35 %sub = add i8 %x, -5 36 %c1 = icmp ne i8 %x, 5 37 %c2 = icmp ule i8 %sub, %y 38 %and = and i1 %c1, %c2 39 ret i1 %and 40} 41 42define i1 @eq_basic_equal_minus_1(i8 %x, i8 %y) { 43; CHECK-LABEL: define i1 @eq_basic_equal_minus_1( 44; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { 45; CHECK-NEXT: [[OR:%.*]] = icmp uge i8 [[X]], [[Y]] 46; CHECK-NEXT: ret i1 [[OR]] 47; 48 %add = add i8 %x, 1 49 %c1 = icmp eq i8 %x, -1 50 %c2 = icmp ugt i8 %add, %y 51 %or = or i1 %c1, %c2 52 ret i1 %or 53} 54 55define i1 @ne_basic_equal_minus_7(i8 %x, i8 %y) { 56; CHECK-LABEL: define i1 @ne_basic_equal_minus_7( 57; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { 58; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[X]], 6 59; CHECK-NEXT: [[AND:%.*]] = icmp ult i8 [[TMP1]], [[Y]] 60; CHECK-NEXT: ret i1 [[AND]] 61; 62 %add = add i8 %x, 7 63 %c1 = icmp ne i8 %x, -7 64 %c2 = icmp ule i8 %add, %y 65 %and = and i1 %c1, %c2 66 ret i1 %and 67} 68 69define i1 @eq_basic_unequal(i8 %x, i8 %y) { 70; CHECK-LABEL: define i1 @eq_basic_unequal( 71; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { 72; CHECK-NEXT: [[SUB:%.*]] = add i8 [[X]], -5 73; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[X]], 6 74; CHECK-NEXT: [[C2:%.*]] = icmp ugt i8 [[SUB]], [[Y]] 75; CHECK-NEXT: [[OR:%.*]] = or i1 [[C1]], [[C2]] 76; CHECK-NEXT: ret i1 [[OR]] 77; 78 %sub = add i8 %x, -5 79 %c1 = icmp eq i8 %x, 6 80 %c2 = icmp ugt i8 %sub, %y 81 %or = or i1 %c1, %c2 82 ret i1 %or 83} 84 85define i1 @ne_basic_unequal(i8 %x, i8 %y) { 86; CHECK-LABEL: define i1 @ne_basic_unequal( 87; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { 88; CHECK-NEXT: [[ADD:%.*]] = add i8 [[X]], 7 89; CHECK-NEXT: [[C1:%.*]] = icmp ne i8 [[X]], -4 90; CHECK-NEXT: [[C2:%.*]] = icmp ule i8 [[ADD]], [[Y]] 91; CHECK-NEXT: [[AND:%.*]] = and i1 [[C1]], [[C2]] 92; CHECK-NEXT: ret i1 [[AND]] 93; 94 %add = add i8 %x, 7 95 %c1 = icmp ne i8 %x, -4 96 %c2 = icmp ule i8 %add, %y 97 %and = and i1 %c1, %c2 98 ret i1 %and 99} 100 101; ============================================================================== 102; Tests with multiple uses 103; ============================================================================== 104define i1 @eq_multi_c1(i8 %x, i8 %y) { 105; CHECK-LABEL: define i1 @eq_multi_c1( 106; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { 107; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[X]], 0 108; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[X]], -1 109; CHECK-NEXT: [[OR:%.*]] = icmp uge i8 [[TMP1]], [[Y]] 110; CHECK-NEXT: call void @use(i1 [[C1]]) 111; CHECK-NEXT: ret i1 [[OR]] 112; 113 %c1 = icmp eq i8 %x, 0 114 %c2 = icmp ugt i8 %x, %y 115 %or = or i1 %c1, %c2 116 call void @use(i1 %c1) 117 ret i1 %or 118} 119 120define i1 @ne_multi_c2(i8 %x, i8 %y) { 121; CHECK-LABEL: define i1 @ne_multi_c2( 122; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { 123; CHECK-NEXT: [[C2:%.*]] = icmp ule i8 [[X]], [[Y]] 124; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[X]], -1 125; CHECK-NEXT: [[AND:%.*]] = icmp ult i8 [[TMP1]], [[Y]] 126; CHECK-NEXT: call void @use(i1 [[C2]]) 127; CHECK-NEXT: ret i1 [[AND]] 128; 129 %c1 = icmp ne i8 %x, 0 130 %c2 = icmp ule i8 %x, %y 131 %and = and i1 %c1, %c2 132 call void @use(i1 %c2) 133 ret i1 %and 134} 135 136; ============================================================================== 137; Tests with vector types 138; ============================================================================== 139define <2 x i1> @eq_vector(<2 x i8> %x, <2 x i8> %y) { 140; CHECK-LABEL: define <2 x i1> @eq_vector( 141; CHECK-SAME: <2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]]) { 142; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i8> [[X]], splat (i8 -1) 143; CHECK-NEXT: [[OR:%.*]] = icmp uge <2 x i8> [[TMP1]], [[Y]] 144; CHECK-NEXT: ret <2 x i1> [[OR]] 145; 146 %c1 = icmp eq <2 x i8> %x, <i8 0, i8 0> 147 %c2 = icmp ugt <2 x i8> %x, %y 148 %or = or <2 x i1> %c1, %c2 149 ret <2 x i1> %or 150} 151 152define <2 x i1> @ne_vector_equal_5(<2 x i8> %x, <2 x i8> %y) { 153; CHECK-LABEL: define <2 x i1> @ne_vector_equal_5( 154; CHECK-SAME: <2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]]) { 155; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i8> [[X]], splat (i8 -6) 156; CHECK-NEXT: [[AND:%.*]] = icmp ult <2 x i8> [[TMP1]], [[Y]] 157; CHECK-NEXT: ret <2 x i1> [[AND]] 158; 159 %sub = add <2 x i8> %x, <i8 -5, i8 -5> 160 %c1 = icmp ne <2 x i8> %x, <i8 5, i8 5> 161 %c2 = icmp ule <2 x i8> %sub, %y 162 %and = and <2 x i1> %c1, %c2 163 ret <2 x i1> %and 164} 165 166define <2 x i1> @eq_vector_equal_minus_1(<2 x i8> %x, <2 x i8> %y) { 167; CHECK-LABEL: define <2 x i1> @eq_vector_equal_minus_1( 168; CHECK-SAME: <2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]]) { 169; CHECK-NEXT: [[OR:%.*]] = icmp uge <2 x i8> [[X]], [[Y]] 170; CHECK-NEXT: ret <2 x i1> [[OR]] 171; 172 %add = add <2 x i8> %x, <i8 1, i8 1> 173 %c1 = icmp eq <2 x i8> %x, <i8 -1, i8 -1> 174 %c2 = icmp ugt <2 x i8> %add, %y 175 %or = or <2 x i1> %c1, %c2 176 ret <2 x i1> %or 177} 178 179define <2 x i1> @ne_vector_equal_minus_7(<2 x i8> %x, <2 x i8> %y) { 180; CHECK-LABEL: define <2 x i1> @ne_vector_equal_minus_7( 181; CHECK-SAME: <2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]]) { 182; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i8> [[X]], splat (i8 6) 183; CHECK-NEXT: [[AND:%.*]] = icmp ult <2 x i8> [[TMP1]], [[Y]] 184; CHECK-NEXT: ret <2 x i1> [[AND]] 185; 186 %add = add <2 x i8> %x, <i8 7, i8 7> 187 %c1 = icmp ne <2 x i8> %x, <i8 -7, i8 -7> 188 %c2 = icmp ule <2 x i8> %add, %y 189 %and = and <2 x i1> %c1, %c2 190 ret <2 x i1> %and 191} 192 193define <2 x i1> @eq_vector_unequal1(<2 x i8> %x, <2 x i8> %y) { 194; CHECK-LABEL: define <2 x i1> @eq_vector_unequal1( 195; CHECK-SAME: <2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]]) { 196; CHECK-NEXT: [[SUB:%.*]] = add <2 x i8> [[X]], splat (i8 -5) 197; CHECK-NEXT: [[C1:%.*]] = icmp eq <2 x i8> [[X]], splat (i8 2) 198; CHECK-NEXT: [[C2:%.*]] = icmp ugt <2 x i8> [[SUB]], [[Y]] 199; CHECK-NEXT: [[OR:%.*]] = or <2 x i1> [[C1]], [[C2]] 200; CHECK-NEXT: ret <2 x i1> [[OR]] 201; 202 %sub = add <2 x i8> %x, <i8 -5, i8 -5> 203 %c1 = icmp eq <2 x i8> %x, <i8 2, i8 2> 204 %c2 = icmp ugt <2 x i8> %sub, %y 205 %or = or <2 x i1> %c1, %c2 206 ret <2 x i1> %or 207} 208 209define <2 x i1> @ne_vector_unequal2(<2 x i8> %x, <2 x i8> %y) { 210; CHECK-LABEL: define <2 x i1> @ne_vector_unequal2( 211; CHECK-SAME: <2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]]) { 212; CHECK-NEXT: [[ADD:%.*]] = add <2 x i8> [[X]], splat (i8 7) 213; CHECK-NEXT: [[C1:%.*]] = icmp ne <2 x i8> [[X]], splat (i8 -3) 214; CHECK-NEXT: [[C2:%.*]] = icmp ule <2 x i8> [[ADD]], [[Y]] 215; CHECK-NEXT: [[AND:%.*]] = and <2 x i1> [[C1]], [[C2]] 216; CHECK-NEXT: ret <2 x i1> [[AND]] 217; 218 %add = add <2 x i8> %x, <i8 7, i8 7> 219 %c1 = icmp ne <2 x i8> %x, <i8 -3, i8 -3> 220 %c2 = icmp ule <2 x i8> %add, %y 221 %and = and <2 x i1> %c1, %c2 222 ret <2 x i1> %and 223} 224 225; ============================================================================== 226; Tests with poison 227; ============================================================================== 228define <2 x i1> @eq_vector_poison_icmp(<2 x i8> %x, <2 x i8> %y) { 229; CHECK-LABEL: define <2 x i1> @eq_vector_poison_icmp( 230; CHECK-SAME: <2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]]) { 231; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i8> [[X]], splat (i8 -6) 232; CHECK-NEXT: [[OR:%.*]] = icmp uge <2 x i8> [[TMP1]], [[Y]] 233; CHECK-NEXT: ret <2 x i1> [[OR]] 234; 235 %sub = add <2 x i8> %x, <i8 -5, i8 -5> 236 %c1 = icmp eq <2 x i8> %x, <i8 5, i8 poison> 237 %c2 = icmp ugt <2 x i8> %sub, %y 238 %or = or <2 x i1> %c1, %c2 239 ret <2 x i1> %or 240} 241 242define <2 x i1> @eq_vector_poison_add(<2 x i8> %x, <2 x i8> %y) { 243; CHECK-LABEL: define <2 x i1> @eq_vector_poison_add( 244; CHECK-SAME: <2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]]) { 245; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i8> [[X]], splat (i8 -6) 246; CHECK-NEXT: [[OR:%.*]] = icmp uge <2 x i8> [[TMP1]], [[Y]] 247; CHECK-NEXT: ret <2 x i1> [[OR]] 248; 249 %sub = add <2 x i8> %x, <i8 -5, i8 poison> 250 %c1 = icmp eq <2 x i8> %x, <i8 5, i8 5> 251 %c2 = icmp ugt <2 x i8> %sub, %y 252 %or = or <2 x i1> %c1, %c2 253 ret <2 x i1> %or 254} 255 256; ============================================================================== 257; Tests with values commuted 258; ============================================================================== 259define i1 @eq_commuted(i8 %x, i8 %py) { 260; CHECK-LABEL: define i1 @eq_commuted( 261; CHECK-SAME: i8 [[X:%.*]], i8 [[PY:%.*]]) { 262; CHECK-NEXT: [[Y:%.*]] = sdiv i8 43, [[PY]] 263; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[X]], -1 264; CHECK-NEXT: [[OR:%.*]] = icmp uge i8 [[TMP1]], [[Y]] 265; CHECK-NEXT: ret i1 [[OR]] 266; 267 %y = sdiv i8 43, %py ; thwart complexity-based canonicalization 268 %c1 = icmp eq i8 %x, 0 269 %c2 = icmp ult i8 %y, %x 270 %or = or i1 %c1, %c2 271 ret i1 %or 272} 273 274define i1 @ne_commuted_equal_minus_1(i8 %x, i8 %py) { 275; CHECK-LABEL: define i1 @ne_commuted_equal_minus_1( 276; CHECK-SAME: i8 [[X:%.*]], i8 [[PY:%.*]]) { 277; CHECK-NEXT: [[Y:%.*]] = sdiv i8 42, [[PY]] 278; CHECK-NEXT: [[AND:%.*]] = icmp ult i8 [[X]], [[Y]] 279; CHECK-NEXT: ret i1 [[AND]] 280; 281 %y = sdiv i8 42, %py ; thwart complexity-based canonicalization 282 %add = add i8 %x, 1 283 %c1 = icmp ne i8 %x, -1 284 %c2 = icmp uge i8 %y, %add 285 %and = and i1 %c1, %c2 286 ret i1 %and 287} 288 289declare void @use(i1) 290