1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4declare void @use(i8 %value) 5 6define i1 @ucmp_eq_0(i32 %x, i32 %y) { 7; CHECK-LABEL: define i1 @ucmp_eq_0( 8; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 9; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[X]], [[Y]] 10; CHECK-NEXT: ret i1 [[TMP2]] 11; 12 %1 = call i8 @llvm.ucmp(i32 %x, i32 %y) 13 %2 = icmp eq i8 %1, 0 14 ret i1 %2 15} 16 17define i1 @ucmp_ne_0(i32 %x, i32 %y) { 18; CHECK-LABEL: define i1 @ucmp_ne_0( 19; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 20; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[X]], [[Y]] 21; CHECK-NEXT: ret i1 [[TMP2]] 22; 23 %1 = call i8 @llvm.ucmp(i32 %x, i32 %y) 24 %2 = icmp ne i8 %1, 0 25 ret i1 %2 26} 27 28define i1 @ucmp_eq_1(i32 %x, i32 %y) { 29; CHECK-LABEL: define i1 @ucmp_eq_1( 30; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 31; CHECK-NEXT: [[TMP2:%.*]] = icmp ugt i32 [[X]], [[Y]] 32; CHECK-NEXT: ret i1 [[TMP2]] 33; 34 %1 = call i8 @llvm.ucmp(i32 %x, i32 %y) 35 %2 = icmp eq i8 %1, 1 36 ret i1 %2 37} 38 39define i1 @ucmp_ne_1(i32 %x, i32 %y) { 40; CHECK-LABEL: define i1 @ucmp_ne_1( 41; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 42; CHECK-NEXT: [[TMP2:%.*]] = icmp ule i32 [[X]], [[Y]] 43; CHECK-NEXT: ret i1 [[TMP2]] 44; 45 %1 = call i8 @llvm.ucmp(i32 %x, i32 %y) 46 %2 = icmp ne i8 %1, 1 47 ret i1 %2 48} 49 50define i1 @ucmp_eq_negative_1(i32 %x, i32 %y) { 51; CHECK-LABEL: define i1 @ucmp_eq_negative_1( 52; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 53; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 [[X]], [[Y]] 54; CHECK-NEXT: ret i1 [[TMP2]] 55; 56 %1 = call i8 @llvm.ucmp(i32 %x, i32 %y) 57 %2 = icmp eq i8 %1, -1 58 ret i1 %2 59} 60 61define i1 @ucmp_ne_negative_1(i32 %x, i32 %y) { 62; CHECK-LABEL: define i1 @ucmp_ne_negative_1( 63; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 64; CHECK-NEXT: [[TMP2:%.*]] = icmp uge i32 [[X]], [[Y]] 65; CHECK-NEXT: ret i1 [[TMP2]] 66; 67 %1 = call i8 @llvm.ucmp(i32 %x, i32 %y) 68 %2 = icmp ne i8 %1, -1 69 ret i1 %2 70} 71 72define i1 @ucmp_sgt_0(i32 %x, i32 %y) { 73; CHECK-LABEL: define i1 @ucmp_sgt_0( 74; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 75; CHECK-NEXT: [[TMP2:%.*]] = icmp ugt i32 [[X]], [[Y]] 76; CHECK-NEXT: ret i1 [[TMP2]] 77; 78 %1 = call i8 @llvm.ucmp(i32 %x, i32 %y) 79 %2 = icmp sgt i8 %1, 0 80 ret i1 %2 81} 82 83define i1 @ucmp_sgt_neg_1(i32 %x, i32 %y) { 84; CHECK-LABEL: define i1 @ucmp_sgt_neg_1( 85; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 86; CHECK-NEXT: [[TMP2:%.*]] = icmp uge i32 [[X]], [[Y]] 87; CHECK-NEXT: ret i1 [[TMP2]] 88; 89 %1 = call i8 @llvm.ucmp(i32 %x, i32 %y) 90 %2 = icmp sgt i8 %1, -1 91 ret i1 %2 92} 93 94define i1 @ucmp_sge_0(i32 %x, i32 %y) { 95; CHECK-LABEL: define i1 @ucmp_sge_0( 96; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 97; CHECK-NEXT: [[TMP2:%.*]] = icmp uge i32 [[X]], [[Y]] 98; CHECK-NEXT: ret i1 [[TMP2]] 99; 100 %1 = call i8 @llvm.ucmp(i32 %x, i32 %y) 101 %2 = icmp sge i8 %1, 0 102 ret i1 %2 103} 104 105define i1 @ucmp_sge_1(i32 %x, i32 %y) { 106; CHECK-LABEL: define i1 @ucmp_sge_1( 107; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 108; CHECK-NEXT: [[TMP2:%.*]] = icmp ugt i32 [[X]], [[Y]] 109; CHECK-NEXT: ret i1 [[TMP2]] 110; 111 %1 = call i8 @llvm.ucmp(i32 %x, i32 %y) 112 %2 = icmp sge i8 %1, 1 113 ret i1 %2 114} 115 116define i1 @ucmp_slt_0(i32 %x, i32 %y) { 117; CHECK-LABEL: define i1 @ucmp_slt_0( 118; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 119; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 [[X]], [[Y]] 120; CHECK-NEXT: ret i1 [[TMP2]] 121; 122 %1 = call i8 @llvm.ucmp(i32 %x, i32 %y) 123 %2 = icmp slt i8 %1, 0 124 ret i1 %2 125} 126 127define i1 @ucmp_slt_1(i32 %x, i32 %y) { 128; CHECK-LABEL: define i1 @ucmp_slt_1( 129; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 130; CHECK-NEXT: [[TMP2:%.*]] = icmp ule i32 [[X]], [[Y]] 131; CHECK-NEXT: ret i1 [[TMP2]] 132; 133 %1 = call i8 @llvm.ucmp(i32 %x, i32 %y) 134 %2 = icmp slt i8 %1, 1 135 ret i1 %2 136} 137 138define i1 @ucmp_sle_0(i32 %x, i32 %y) { 139; CHECK-LABEL: define i1 @ucmp_sle_0( 140; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 141; CHECK-NEXT: [[TMP2:%.*]] = icmp ule i32 [[X]], [[Y]] 142; CHECK-NEXT: ret i1 [[TMP2]] 143; 144 %1 = call i8 @llvm.ucmp(i32 %x, i32 %y) 145 %2 = icmp sle i8 %1, 0 146 ret i1 %2 147} 148 149define i1 @ucmp_sle_neg_1(i32 %x, i32 %y) { 150; CHECK-LABEL: define i1 @ucmp_sle_neg_1( 151; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 152; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 [[X]], [[Y]] 153; CHECK-NEXT: ret i1 [[TMP2]] 154; 155 %1 = call i8 @llvm.ucmp(i32 %x, i32 %y) 156 %2 = icmp sle i8 %1, -1 157 ret i1 %2 158} 159 160; ucmp(x, y) u< C => x u>= y when C u> 1 and C != -1 161define i1 @ucmp_ult_positive_const_gt_than_1_lt_than_umax(i32 %x, i32 %y) { 162; CHECK-LABEL: define i1 @ucmp_ult_positive_const_gt_than_1_lt_than_umax( 163; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 164; CHECK-NEXT: [[TMP1:%.*]] = icmp uge i32 [[X]], [[Y]] 165; CHECK-NEXT: ret i1 [[TMP1]] 166; 167 %1 = call i8 @llvm.ucmp(i32 %x, i32 %y) 168 %2 = icmp ult i8 %1, 4 169 ret i1 %2 170} 171 172; ucmp(x, y) u> C => x u< y when C != 0 and C != -1 173define i1 @ucmp_ugt_const_not_0_or_neg1(i32 %x, i32 %y) { 174; CHECK-LABEL: define i1 @ucmp_ugt_const_not_0_or_neg1( 175; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 176; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 [[X]], [[Y]] 177; CHECK-NEXT: ret i1 [[TMP2]] 178; 179 %1 = call i8 @llvm.ucmp(i32 %x, i32 %y) 180 %2 = icmp ugt i8 %1, 12 181 ret i1 %2 182} 183 184; ========== Fold -ucmp(x, y) => ucmp(y, x) ========== 185define i8 @ucmp_negated(i32 %x, i32 %y) { 186; CHECK-LABEL: define i8 @ucmp_negated( 187; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 188; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[Y]], i32 [[X]]) 189; CHECK-NEXT: ret i8 [[TMP2]] 190; 191 %1 = call i8 @llvm.ucmp(i32 %x, i32 %y) 192 %2 = sub i8 0, %1 193 ret i8 %2 194} 195 196; Negative test: do not fold if the original ucmp result is already used 197define i8 @ucmp_negated_multiuse(i32 %x, i32 %y) { 198; CHECK-LABEL: define i8 @ucmp_negated_multiuse( 199; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 200; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]]) 201; CHECK-NEXT: call void @use(i8 [[TMP1]]) 202; CHECK-NEXT: [[TMP2:%.*]] = sub nsw i8 0, [[TMP1]] 203; CHECK-NEXT: ret i8 [[TMP2]] 204; 205 %1 = call i8 @llvm.ucmp(i32 %x, i32 %y) 206 call void @use(i8 %1) 207 %2 = sub i8 0, %1 208 ret i8 %2 209} 210 211; Fold ((x u< y) ? -1 : (x != y)) into ucmp(x, y) 212define i8 @ucmp_from_select_lt(i32 %x, i32 %y) { 213; CHECK-LABEL: define i8 @ucmp_from_select_lt( 214; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 215; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]]) 216; CHECK-NEXT: ret i8 [[R]] 217; 218 %ne_bool = icmp ne i32 %x, %y 219 %ne = zext i1 %ne_bool to i8 220 %lt = icmp ult i32 %x, %y 221 %r = select i1 %lt, i8 -1, i8 %ne 222 ret i8 %r 223} 224 225; Fold (x u< y) ? -1 : zext(x u> y) into ucmp(x, y) 226define i8 @ucmp_from_select_lt_and_gt(i32 %x, i32 %y) { 227; CHECK-LABEL: define i8 @ucmp_from_select_lt_and_gt( 228; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 229; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]]) 230; CHECK-NEXT: ret i8 [[R]] 231; 232 %gt_bool = icmp ugt i32 %x, %y 233 %gt = zext i1 %gt_bool to i8 234 %lt = icmp ult i32 %x, %y 235 %r = select i1 %lt, i8 -1, i8 %gt 236 ret i8 %r 237} 238 239; Vector version 240define <4 x i8> @ucmp_from_select_vec_lt(<4 x i32> %x, <4 x i32> %y) { 241; CHECK-LABEL: define <4 x i8> @ucmp_from_select_vec_lt( 242; CHECK-SAME: <4 x i32> [[X:%.*]], <4 x i32> [[Y:%.*]]) { 243; CHECK-NEXT: [[R:%.*]] = call <4 x i8> @llvm.ucmp.v4i8.v4i32(<4 x i32> [[X]], <4 x i32> [[Y]]) 244; CHECK-NEXT: ret <4 x i8> [[R]] 245; 246 %ne_bool = icmp ne <4 x i32> %x, %y 247 %ne = zext <4 x i1> %ne_bool to <4 x i8> 248 %lt = icmp ult <4 x i32> %x, %y 249 %r = select <4 x i1> %lt, <4 x i8> splat(i8 -1), <4 x i8> %ne 250 ret <4 x i8> %r 251} 252 253; Commuted operands 254define i8 @ucmp_from_select_lt_commuted_ops1(i32 %x, i32 %y) { 255; CHECK-LABEL: define i8 @ucmp_from_select_lt_commuted_ops1( 256; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 257; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]]) 258; CHECK-NEXT: ret i8 [[R]] 259; 260 %ne_bool = icmp ne i32 %y, %x 261 %ne = zext i1 %ne_bool to i8 262 %lt = icmp ult i32 %x, %y 263 %r = select i1 %lt, i8 -1, i8 %ne 264 ret i8 %r 265} 266 267define i8 @ucmp_from_select_lt_commuted_ops2(i32 %x, i32 %y) { 268; CHECK-LABEL: define i8 @ucmp_from_select_lt_commuted_ops2( 269; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 270; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]]) 271; CHECK-NEXT: ret i8 [[R]] 272; 273 %ne_bool = icmp ne i32 %x, %y 274 %ne = zext i1 %ne_bool to i8 275 %lt = icmp ugt i32 %y, %x 276 %r = select i1 %lt, i8 -1, i8 %ne 277 ret i8 %r 278} 279 280; Negative test: false value of the select is not `icmp ne x, y` 281define i8 @ucmp_from_select_lt_neg1(i32 %x, i32 %y) { 282; CHECK-LABEL: define i8 @ucmp_from_select_lt_neg1( 283; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 284; CHECK-NEXT: [[NE_BOOL:%.*]] = icmp eq i32 [[X]], [[Y]] 285; CHECK-NEXT: [[NE:%.*]] = zext i1 [[NE_BOOL]] to i8 286; CHECK-NEXT: [[LT:%.*]] = icmp ult i32 [[X]], [[Y]] 287; CHECK-NEXT: [[R:%.*]] = select i1 [[LT]], i8 -1, i8 [[NE]] 288; CHECK-NEXT: ret i8 [[R]] 289; 290 %ne_bool = icmp eq i32 %x, %y 291 %ne = zext i1 %ne_bool to i8 292 %lt = icmp ult i32 %x, %y 293 %r = select i1 %lt, i8 -1, i8 %ne 294 ret i8 %r 295} 296 297; Negative test: true value of select is not -1 298define i8 @ucmp_from_select_lt_neg2(i32 %x, i32 %y) { 299; CHECK-LABEL: define i8 @ucmp_from_select_lt_neg2( 300; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 301; CHECK-NEXT: [[NE_BOOL:%.*]] = icmp ne i32 [[X]], [[Y]] 302; CHECK-NEXT: [[NE:%.*]] = zext i1 [[NE_BOOL]] to i8 303; CHECK-NEXT: [[LT:%.*]] = icmp ult i32 [[X]], [[Y]] 304; CHECK-NEXT: [[R:%.*]] = select i1 [[LT]], i8 2, i8 [[NE]] 305; CHECK-NEXT: ret i8 [[R]] 306; 307 %ne_bool = icmp ne i32 %x, %y 308 %ne = zext i1 %ne_bool to i8 309 %lt = icmp ult i32 %x, %y 310 %r = select i1 %lt, i8 2, i8 %ne 311 ret i8 %r 312} 313 314; Negative test: false value of select is sign-extended instead of zero-extended 315define i8 @ucmp_from_select_lt_neg3(i32 %x, i32 %y) { 316; CHECK-LABEL: define i8 @ucmp_from_select_lt_neg3( 317; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 318; CHECK-NEXT: [[NE_BOOL:%.*]] = icmp ne i32 [[X]], [[Y]] 319; CHECK-NEXT: [[R:%.*]] = sext i1 [[NE_BOOL]] to i8 320; CHECK-NEXT: ret i8 [[R]] 321; 322 %ne_bool = icmp ne i32 %x, %y 323 %ne = sext i1 %ne_bool to i8 324 %lt = icmp ult i32 %x, %y 325 %r = select i1 %lt, i8 -1, i8 %ne 326 ret i8 %r 327} 328 329; Negative test: condition of select is not (x u< y) 330define i8 @ucmp_from_select_lt_neg4(i32 %x, i32 %y) { 331; CHECK-LABEL: define i8 @ucmp_from_select_lt_neg4( 332; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 333; CHECK-NEXT: [[NE_BOOL:%.*]] = icmp ne i32 [[X]], [[Y]] 334; CHECK-NEXT: [[NE:%.*]] = zext i1 [[NE_BOOL]] to i8 335; CHECK-NEXT: [[LT_NOT:%.*]] = icmp ugt i32 [[X]], [[Y]] 336; CHECK-NEXT: [[R:%.*]] = select i1 [[LT_NOT]], i8 [[NE]], i8 -1 337; CHECK-NEXT: ret i8 [[R]] 338; 339 %ne_bool = icmp ne i32 %x, %y 340 %ne = zext i1 %ne_bool to i8 341 %lt = icmp ule i32 %x, %y 342 %r = select i1 %lt, i8 -1, i8 %ne 343 ret i8 %r 344} 345 346; Fold (x u<= y) ? sext(x != y) : 1 into ucmp(x, y) 347define i8 @ucmp_from_select_le(i32 %x, i32 %y) { 348; CHECK-LABEL: define i8 @ucmp_from_select_le( 349; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 350; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]]) 351; CHECK-NEXT: ret i8 [[R]] 352; 353 %ne_bool = icmp ne i32 %x, %y 354 %ne = sext i1 %ne_bool to i8 355 %le = icmp ule i32 %x, %y 356 %r = select i1 %le, i8 %ne, i8 1 357 ret i8 %r 358} 359 360; Negative test: condition of select is not (x u<= y) 361define i8 @ucmp_from_select_le_neg1(i32 %x, i32 %y) { 362; CHECK-LABEL: define i8 @ucmp_from_select_le_neg1( 363; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 364; CHECK-NEXT: [[NE_BOOL:%.*]] = icmp ult i32 [[X]], [[Y]] 365; CHECK-NEXT: [[NE:%.*]] = sext i1 [[NE_BOOL]] to i8 366; CHECK-NEXT: [[LE_NOT:%.*]] = icmp ult i32 [[X]], [[Y]] 367; CHECK-NEXT: [[R:%.*]] = select i1 [[LE_NOT]], i8 1, i8 [[NE]] 368; CHECK-NEXT: ret i8 [[R]] 369; 370 %ne_bool = icmp ult i32 %x, %y 371 %ne = sext i1 %ne_bool to i8 372 %le = icmp uge i32 %x, %y 373 %r = select i1 %le, i8 %ne, i8 1 374 ret i8 %r 375} 376 377; Negative test: true value of select is zero-extended instead of sign-extended 378define i8 @ucmp_from_select_le_neg2(i32 %x, i32 %y) { 379; CHECK-LABEL: define i8 @ucmp_from_select_le_neg2( 380; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 381; CHECK-NEXT: [[NE_BOOL:%.*]] = icmp ne i32 [[X]], [[Y]] 382; CHECK-NEXT: [[R:%.*]] = zext i1 [[NE_BOOL]] to i8 383; CHECK-NEXT: ret i8 [[R]] 384; 385 %ne_bool = icmp ne i32 %x, %y 386 %ne = zext i1 %ne_bool to i8 387 %le = icmp ule i32 %x, %y 388 %r = select i1 %le, i8 %ne, i8 1 389 ret i8 %r 390} 391 392; Negative test: true value is not x != y 393define i8 @ucmp_from_select_le_neg3(i32 %x, i32 %y) { 394; CHECK-LABEL: define i8 @ucmp_from_select_le_neg3( 395; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 396; CHECK-NEXT: [[NE_BOOL:%.*]] = icmp sgt i32 [[X]], [[Y]] 397; CHECK-NEXT: [[NE:%.*]] = sext i1 [[NE_BOOL]] to i8 398; CHECK-NEXT: [[LE_NOT:%.*]] = icmp ugt i32 [[X]], [[Y]] 399; CHECK-NEXT: [[R:%.*]] = select i1 [[LE_NOT]], i8 1, i8 [[NE]] 400; CHECK-NEXT: ret i8 [[R]] 401; 402 %ne_bool = icmp sgt i32 %x, %y 403 %ne = sext i1 %ne_bool to i8 404 %le = icmp ule i32 %x, %y 405 %r = select i1 %le, i8 %ne, i8 1 406 ret i8 %r 407} 408 409; Negative test: false value is not 1 410define i8 @ucmp_from_select_le_neg4(i32 %x, i32 %y) { 411; CHECK-LABEL: define i8 @ucmp_from_select_le_neg4( 412; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 413; CHECK-NEXT: [[NE_BOOL:%.*]] = icmp ne i32 [[X]], [[Y]] 414; CHECK-NEXT: [[R:%.*]] = sext i1 [[NE_BOOL]] to i8 415; CHECK-NEXT: ret i8 [[R]] 416; 417 %ne_bool = icmp ne i32 %x, %y 418 %ne = sext i1 %ne_bool to i8 419 %le = icmp ule i32 %x, %y 420 %r = select i1 %le, i8 %ne, i8 -1 421 ret i8 %r 422} 423 424; Fold (x u>= y) ? zext(x != y) : -1 into ucmp(x, y) 425define i8 @ucmp_from_select_ge(i32 %x, i32 %y) { 426; CHECK-LABEL: define i8 @ucmp_from_select_ge( 427; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 428; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]]) 429; CHECK-NEXT: ret i8 [[R]] 430; 431 %ne_bool = icmp ne i32 %x, %y 432 %ne = zext i1 %ne_bool to i8 433 %ge = icmp uge i32 %x, %y 434 %r = select i1 %ge, i8 %ne, i8 -1 435 ret i8 %r 436} 437 438; Commuted operands 439define i8 @ucmp_from_select_ge_commuted_ops1(i32 %x, i32 %y) { 440; CHECK-LABEL: define i8 @ucmp_from_select_ge_commuted_ops1( 441; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 442; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]]) 443; CHECK-NEXT: ret i8 [[R]] 444; 445 %ne_bool = icmp ne i32 %y, %x 446 %ne = zext i1 %ne_bool to i8 447 %ge = icmp uge i32 %x, %y 448 %r = select i1 %ge, i8 %ne, i8 -1 449 ret i8 %r 450} 451 452define i8 @ucmp_from_select_ge_commuted_ops2(i32 %x, i32 %y) { 453; CHECK-LABEL: define i8 @ucmp_from_select_ge_commuted_ops2( 454; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 455; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]]) 456; CHECK-NEXT: ret i8 [[R]] 457; 458 %ne_bool = icmp ne i32 %x, %y 459 %ne = zext i1 %ne_bool to i8 460 %ge = icmp ule i32 %y, %x 461 %r = select i1 %ge, i8 %ne, i8 -1 462 ret i8 %r 463} 464 465; Negative test: condition is not x u>= y 466define i8 @ucmp_from_select_ge_neg1(i32 %x, i32 %y) { 467; CHECK-LABEL: define i8 @ucmp_from_select_ge_neg1( 468; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 469; CHECK-NEXT: [[NE_BOOL:%.*]] = icmp ne i32 [[X]], [[Y]] 470; CHECK-NEXT: [[NE:%.*]] = zext i1 [[NE_BOOL]] to i8 471; CHECK-NEXT: [[GE:%.*]] = icmp ult i32 [[X]], [[Y]] 472; CHECK-NEXT: [[R:%.*]] = select i1 [[GE]], i8 [[NE]], i8 -1 473; CHECK-NEXT: ret i8 [[R]] 474; 475 %ne_bool = icmp ne i32 %x, %y 476 %ne = zext i1 %ne_bool to i8 477 %ge = icmp ult i32 %x, %y 478 %r = select i1 %ge, i8 %ne, i8 -1 479 ret i8 %r 480} 481 482; Negative test: true value is sign-extended instead of zero-extended 483define i8 @ucmp_from_select_ge_neg2(i32 %x, i32 %y) { 484; CHECK-LABEL: define i8 @ucmp_from_select_ge_neg2( 485; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 486; CHECK-NEXT: [[NE_BOOL:%.*]] = icmp ne i32 [[X]], [[Y]] 487; CHECK-NEXT: [[R:%.*]] = sext i1 [[NE_BOOL]] to i8 488; CHECK-NEXT: ret i8 [[R]] 489; 490 %ne_bool = icmp ne i32 %x, %y 491 %ne = sext i1 %ne_bool to i8 492 %ge = icmp uge i32 %x, %y 493 %r = select i1 %ge, i8 %ne, i8 -1 494 ret i8 %r 495} 496 497; Negative test: true value is not x != y 498define i8 @ucmp_from_select_ge_neg3(i32 %x, i32 %y) { 499; CHECK-LABEL: define i8 @ucmp_from_select_ge_neg3( 500; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 501; CHECK-NEXT: [[NE_BOOL:%.*]] = icmp sgt i32 [[X]], [[Y]] 502; CHECK-NEXT: [[NE:%.*]] = zext i1 [[NE_BOOL]] to i8 503; CHECK-NEXT: [[GE_NOT:%.*]] = icmp ult i32 [[X]], [[Y]] 504; CHECK-NEXT: [[R:%.*]] = select i1 [[GE_NOT]], i8 -1, i8 [[NE]] 505; CHECK-NEXT: ret i8 [[R]] 506; 507 %ne_bool = icmp sgt i32 %x, %y 508 %ne = zext i1 %ne_bool to i8 509 %ge = icmp uge i32 %x, %y 510 %r = select i1 %ge, i8 %ne, i8 -1 511 ret i8 %r 512} 513 514; Negative test: false value is not -1 515define i8 @ucmp_from_select_ge_neg4(i32 %x, i32 %y) { 516; CHECK-LABEL: define i8 @ucmp_from_select_ge_neg4( 517; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 518; CHECK-NEXT: [[NE_BOOL:%.*]] = icmp ne i32 [[X]], [[Y]] 519; CHECK-NEXT: [[NE:%.*]] = zext i1 [[NE_BOOL]] to i8 520; CHECK-NEXT: [[GE_NOT:%.*]] = icmp ult i32 [[X]], [[Y]] 521; CHECK-NEXT: [[R:%.*]] = select i1 [[GE_NOT]], i8 3, i8 [[NE]] 522; CHECK-NEXT: ret i8 [[R]] 523; 524 %ne_bool = icmp ne i32 %x, %y 525 %ne = zext i1 %ne_bool to i8 526 %ge = icmp uge i32 %x, %y 527 %r = select i1 %ge, i8 %ne, i8 3 528 ret i8 %r 529} 530 531; Fold (x > y) ? 1 : sext(x < y) 532define i8 @ucmp_from_select_gt_and_lt(i32 %x, i32 %y) { 533; CHECK-LABEL: define i8 @ucmp_from_select_gt_and_lt( 534; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 535; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]]) 536; CHECK-NEXT: ret i8 [[R]] 537; 538 %lt_bool = icmp ult i32 %x, %y 539 %lt = sext i1 %lt_bool to i8 540 %gt = icmp ugt i32 %x, %y 541 %r = select i1 %gt, i8 1, i8 %lt 542 ret i8 %r 543} 544 545; (x == y) ? 0 : (x u> y ? 1 : -1) into ucmp(x, y) 546define i8 @scmp_from_select_eq_and_gt(i32 %x, i32 %y) { 547; CHECK-LABEL: define i8 @scmp_from_select_eq_and_gt( 548; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 549; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]]) 550; CHECK-NEXT: ret i8 [[R]] 551; 552 %eq = icmp eq i32 %x, %y 553 %gt = icmp ugt i32 %x, %y 554 %sel1 = select i1 %gt, i8 1, i8 -1 555 %r = select i1 %eq, i8 0, i8 %sel1 556 ret i8 %r 557} 558