1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s 3 4; Vary the operand sizes for extra coverage, but the transform should be identical in all cases. 5 6; (X == 0) ? 0 : -1 --> (X == 0) - 1 7 8define i8 @i8_select_0_or_neg1(i8 %x) { 9; CHECK-LABEL: i8_select_0_or_neg1: 10; CHECK: # %bb.0: 11; CHECK-NEXT: xorl %eax, %eax 12; CHECK-NEXT: negb %dil 13; CHECK-NEXT: sbbl %eax, %eax 14; CHECK-NEXT: # kill: def $al killed $al killed $eax 15; CHECK-NEXT: retq 16 %cmp = icmp eq i8 %x, 0 17 %sel = select i1 %cmp, i8 0, i8 -1 18 ret i8 %sel 19} 20 21; (X == 0) ? 0 : -1 --> (X == 0) - 1 22 23define i16 @i16_select_0_or_neg1_as_math(i16 %x) { 24; CHECK-LABEL: i16_select_0_or_neg1_as_math: 25; CHECK: # %bb.0: 26; CHECK-NEXT: xorl %eax, %eax 27; CHECK-NEXT: negw %di 28; CHECK-NEXT: sbbl %eax, %eax 29; CHECK-NEXT: # kill: def $ax killed $ax killed $eax 30; CHECK-NEXT: retq 31 %cmp = icmp eq i16 %x, 0 32 %ext = zext i1 %cmp to i16 33 %add = add i16 %ext, -1 34 ret i16 %add 35} 36 37; (X != 0) ? -1 : 0 --> 0 - (X != 0) 38 39define i32 @i32_select_0_or_neg1_commuted(i32 %x) { 40; CHECK-LABEL: i32_select_0_or_neg1_commuted: 41; CHECK: # %bb.0: 42; CHECK-NEXT: xorl %eax, %eax 43; CHECK-NEXT: negl %edi 44; CHECK-NEXT: sbbl %eax, %eax 45; CHECK-NEXT: retq 46 %cmp = icmp ne i32 %x, 0 47 %sel = select i1 %cmp, i32 -1, i32 0 48 ret i32 %sel 49} 50 51; (X != 0) ? -1 : 0 --> 0 - (X != 0) 52 53define i64 @i64_select_0_or_neg1_commuted_as_math(i64 %x) { 54; CHECK-LABEL: i64_select_0_or_neg1_commuted_as_math: 55; CHECK: # %bb.0: 56; CHECK-NEXT: xorl %eax, %eax 57; CHECK-NEXT: negq %rdi 58; CHECK-NEXT: sbbq %rax, %rax 59; CHECK-NEXT: retq 60 %cmp = icmp ne i64 %x, 0 61 %ext = zext i1 %cmp to i64 62 %sub = sub i64 0, %ext 63 ret i64 %sub 64} 65 66; (X == 0) ? -1 : 0 --> 0 - (X == 0) 67 68define i64 @i64_select_neg1_or_0(i64 %x) { 69; CHECK-LABEL: i64_select_neg1_or_0: 70; CHECK: # %bb.0: 71; CHECK-NEXT: xorl %eax, %eax 72; CHECK-NEXT: cmpq $1, %rdi 73; CHECK-NEXT: sbbq %rax, %rax 74; CHECK-NEXT: retq 75 %cmp = icmp eq i64 %x, 0 76 %sel = select i1 %cmp, i64 -1, i64 0 77 ret i64 %sel 78} 79 80; (X == 0) ? -1 : 0 --> 0 - (X == 0) 81 82define i32 @i32_select_neg1_or_0_as_math(i32 %x) { 83; CHECK-LABEL: i32_select_neg1_or_0_as_math: 84; CHECK: # %bb.0: 85; CHECK-NEXT: xorl %eax, %eax 86; CHECK-NEXT: cmpl $1, %edi 87; CHECK-NEXT: sbbl %eax, %eax 88; CHECK-NEXT: retq 89 %cmp = icmp eq i32 %x, 0 90 %ext = zext i1 %cmp to i32 91 %sub = sub i32 0, %ext 92 ret i32 %sub 93} 94 95; (X != 0) ? 0 : -1 --> (X != 0) - 1 96 97define i16 @i16_select_neg1_or_0_commuted(i16 %x) { 98; CHECK-LABEL: i16_select_neg1_or_0_commuted: 99; CHECK: # %bb.0: 100; CHECK-NEXT: xorl %eax, %eax 101; CHECK-NEXT: cmpw $1, %di 102; CHECK-NEXT: sbbl %eax, %eax 103; CHECK-NEXT: # kill: def $ax killed $ax killed $eax 104; CHECK-NEXT: retq 105 %cmp = icmp ne i16 %x, 0 106 %sel = select i1 %cmp, i16 0, i16 -1 107 ret i16 %sel 108} 109 110; (X != 0) ? 0 : -1 --> (X != 0) - 1 111 112define i8 @i8_select_neg1_or_0_commuted_as_math(i8 %x) { 113; CHECK-LABEL: i8_select_neg1_or_0_commuted_as_math: 114; CHECK: # %bb.0: 115; CHECK-NEXT: xorl %eax, %eax 116; CHECK-NEXT: cmpb $1, %dil 117; CHECK-NEXT: sbbl %eax, %eax 118; CHECK-NEXT: # kill: def $al killed $al killed $eax 119; CHECK-NEXT: retq 120 %cmp = icmp ne i8 %x, 0 121 %ext = zext i1 %cmp to i8 122 %add = add i8 %ext, -1 123 ret i8 %add 124} 125 126; (X <u Y) ? -1 : 0 --> cmp, sbb 127 128define i32 @ult_select_neg1_or_0(i32 %x, i32 %y) nounwind { 129; CHECK-LABEL: ult_select_neg1_or_0: 130; CHECK: # %bb.0: 131; CHECK-NEXT: xorl %eax, %eax 132; CHECK-NEXT: cmpl %esi, %edi 133; CHECK-NEXT: sbbl %eax, %eax 134; CHECK-NEXT: retq 135 %cmp = icmp ult i32 %x, %y 136 %ext = sext i1 %cmp to i32 137 ret i32 %ext 138} 139 140; Swap the predicate and compare operands: 141; (Y >u X) ? -1 : 0 --> cmp, sbb 142 143define i32 @ugt_select_neg1_or_0(i32 %x, i32 %y) nounwind { 144; CHECK-LABEL: ugt_select_neg1_or_0: 145; CHECK: # %bb.0: 146; CHECK-NEXT: xorl %eax, %eax 147; CHECK-NEXT: cmpl %esi, %edi 148; CHECK-NEXT: sbbl %eax, %eax 149; CHECK-NEXT: retq 150 %cmp = icmp ugt i32 %y, %x 151 %ext = sext i1 %cmp to i32 152 ret i32 %ext 153} 154 155; Invert the predicate and effectively swap the select operands: 156; (X >=u Y) ? 0 : -1 --> (X <u Y) ? -1 : 0 --> cmp, sbb 157 158define i32 @uge_select_0_or_neg1(i32 %x, i32 %y) nounwind { 159; CHECK-LABEL: uge_select_0_or_neg1: 160; CHECK: # %bb.0: 161; CHECK-NEXT: xorl %eax, %eax 162; CHECK-NEXT: cmpl %esi, %edi 163; CHECK-NEXT: sbbl %eax, %eax 164; CHECK-NEXT: retq 165 %cmp = icmp uge i32 %x, %y 166 %ext = zext i1 %cmp to i32 167 %add = add i32 %ext, -1 168 ret i32 %add 169} 170 171; Swap the predicate and compare operands: 172; (Y <=u X) ? 0 : -1 --> (X <u Y) ? -1 : 0 --> cmp, sbb 173 174define i32 @ule_select_0_or_neg1(i32 %x, i32 %y) nounwind { 175; CHECK-LABEL: ule_select_0_or_neg1: 176; CHECK: # %bb.0: 177; CHECK-NEXT: xorl %eax, %eax 178; CHECK-NEXT: cmpl %esi, %edi 179; CHECK-NEXT: sbbl %eax, %eax 180; CHECK-NEXT: retq 181 %cmp = icmp ule i32 %y, %x 182 %ext = zext i1 %cmp to i32 183 %add = add i32 %ext, -1 184 ret i32 %add 185} 186 187; Verify that subtract with constant is the same thing. 188; (X >=u Y) ? 0 : -1 --> (X <u Y) ? -1 : 0 --> cmp, sbb 189 190define i32 @uge_select_0_or_neg1_sub(i32 %x, i32 %y) nounwind { 191; CHECK-LABEL: uge_select_0_or_neg1_sub: 192; CHECK: # %bb.0: 193; CHECK-NEXT: xorl %eax, %eax 194; CHECK-NEXT: cmpl %esi, %edi 195; CHECK-NEXT: sbbl %eax, %eax 196; CHECK-NEXT: retq 197 %cmp = icmp uge i32 %x, %y 198 %ext = zext i1 %cmp to i32 199 %sub = sub i32 %ext, 1 200 ret i32 %sub 201} 202 203; Check more sub-from-zero patterns. 204; (X >u Y) ? -1 : 0 --> cmp, sbb 205 206define i64 @ugt_select_neg1_or_0_sub(i64 %x, i64 %y) nounwind { 207; CHECK-LABEL: ugt_select_neg1_or_0_sub: 208; CHECK: # %bb.0: 209; CHECK-NEXT: xorl %eax, %eax 210; CHECK-NEXT: cmpq %rdi, %rsi 211; CHECK-NEXT: sbbq %rax, %rax 212; CHECK-NEXT: retq 213 %cmp = icmp ugt i64 %x, %y 214 %zext = zext i1 %cmp to i64 215 %sub = sub i64 0, %zext 216 ret i64 %sub 217} 218 219; Swap the predicate and compare operands: 220; (Y <u X) ? -1 : 0 --> cmp, sbb 221 222define i16 @ult_select_neg1_or_0_sub(i16 %x, i16 %y) nounwind { 223; CHECK-LABEL: ult_select_neg1_or_0_sub: 224; CHECK: # %bb.0: 225; CHECK-NEXT: xorl %eax, %eax 226; CHECK-NEXT: cmpw %di, %si 227; CHECK-NEXT: sbbl %eax, %eax 228; CHECK-NEXT: # kill: def $ax killed $ax killed $eax 229; CHECK-NEXT: retq 230 %cmp = icmp ult i16 %y, %x 231 %zext = zext i1 %cmp to i16 232 %sub = sub i16 0, %zext 233 ret i16 %sub 234} 235 236 237 238; Make sure we're creating nodes with the right value types. This would crash. 239; https://bugs.llvm.org/show_bug.cgi?id=33560 240 241define void @PR33560(i8 %x, i64 %y) { 242; CHECK-LABEL: PR33560: 243; CHECK: # %bb.0: # %entry 244; CHECK-NEXT: xorl %eax, %eax 245; CHECK-NEXT: negb %dil 246; CHECK-NEXT: sbbq %rax, %rax 247; CHECK-NEXT: cmpq %rsi, %rax 248; CHECK-NEXT: retq 249entry: 250 %cmp1 = icmp eq i8 %x, 0 251 %ext = zext i1 %cmp1 to i64 252 %add = add i64 %ext, -1 253 %cmp2 = icmp eq i64 %add, %y 254 br i1 %cmp2, label %end, label %else 255 256else: 257 %tmp7 = zext i1 %cmp1 to i8 258 br label %end 259 260end: 261 ret void 262} 263 264; Cases for PR45700 265define i32 @ult_zext_add(i32 %0, i32 %1, i32 %2) { 266; CHECK-LABEL: ult_zext_add: 267; CHECK: # %bb.0: 268; CHECK-NEXT: movl %edi, %eax 269; CHECK-NEXT: cmpl %edx, %esi 270; CHECK-NEXT: adcl $0, %eax 271; CHECK-NEXT: retq 272 %4 = icmp ult i32 %1, %2 273 %5 = zext i1 %4 to i32 274 %6 = add nsw i32 %5, %0 275 ret i32 %6 276} 277 278define i32 @ule_zext_add(i32 %0, i32 %1, i32 %2) { 279; CHECK-LABEL: ule_zext_add: 280; CHECK: # %bb.0: 281; CHECK-NEXT: movl %edi, %eax 282; CHECK-NEXT: cmpl %esi, %edx 283; CHECK-NEXT: sbbl $-1, %eax 284; CHECK-NEXT: retq 285 %4 = icmp ule i32 %1, %2 286 %5 = zext i1 %4 to i32 287 %6 = add nsw i32 %5, %0 288 ret i32 %6 289} 290 291define i32 @ugt_zext_add(i32 %0, i32 %1, i32 %2) { 292; CHECK-LABEL: ugt_zext_add: 293; CHECK: # %bb.0: 294; CHECK-NEXT: movl %edi, %eax 295; CHECK-NEXT: cmpl %esi, %edx 296; CHECK-NEXT: adcl $0, %eax 297; CHECK-NEXT: retq 298 %4 = icmp ugt i32 %1, %2 299 %5 = zext i1 %4 to i32 300 %6 = add nsw i32 %5, %0 301 ret i32 %6 302} 303 304define i32 @uge_zext_add(i32 %0, i32 %1, i32 %2) { 305; CHECK-LABEL: uge_zext_add: 306; CHECK: # %bb.0: 307; CHECK-NEXT: movl %edi, %eax 308; CHECK-NEXT: cmpl %edx, %esi 309; CHECK-NEXT: sbbl $-1, %eax 310; CHECK-NEXT: retq 311 %4 = icmp uge i32 %1, %2 312 %5 = zext i1 %4 to i32 313 %6 = add nsw i32 %5, %0 314 ret i32 %6 315} 316 317define i32 @ult_sext_add(i32 %0, i32 %1, i32 %2) { 318; CHECK-LABEL: ult_sext_add: 319; CHECK: # %bb.0: 320; CHECK-NEXT: movl %edi, %eax 321; CHECK-NEXT: cmpl %edx, %esi 322; CHECK-NEXT: sbbl $0, %eax 323; CHECK-NEXT: retq 324 %4 = icmp ult i32 %1, %2 325 %5 = sext i1 %4 to i32 326 %6 = add nsw i32 %5, %0 327 ret i32 %6 328} 329 330define i32 @ule_sext_add(i32 %0, i32 %1, i32 %2) { 331; CHECK-LABEL: ule_sext_add: 332; CHECK: # %bb.0: 333; CHECK-NEXT: movl %edi, %eax 334; CHECK-NEXT: cmpl %esi, %edx 335; CHECK-NEXT: adcl $-1, %eax 336; CHECK-NEXT: retq 337 %4 = icmp ule i32 %1, %2 338 %5 = sext i1 %4 to i32 339 %6 = add nsw i32 %5, %0 340 ret i32 %6 341} 342 343define i32 @ugt_sext_add(i32 %0, i32 %1, i32 %2) { 344; CHECK-LABEL: ugt_sext_add: 345; CHECK: # %bb.0: 346; CHECK-NEXT: movl %edi, %eax 347; CHECK-NEXT: cmpl %esi, %edx 348; CHECK-NEXT: sbbl $0, %eax 349; CHECK-NEXT: retq 350 %4 = icmp ugt i32 %1, %2 351 %5 = sext i1 %4 to i32 352 %6 = add nsw i32 %5, %0 353 ret i32 %6 354} 355 356define i32 @uge_sext_add(i32 %0, i32 %1, i32 %2) { 357; CHECK-LABEL: uge_sext_add: 358; CHECK: # %bb.0: 359; CHECK-NEXT: movl %edi, %eax 360; CHECK-NEXT: cmpl %edx, %esi 361; CHECK-NEXT: adcl $-1, %eax 362; CHECK-NEXT: retq 363 %4 = icmp uge i32 %1, %2 364 %5 = sext i1 %4 to i32 365 %6 = add nsw i32 %5, %0 366 ret i32 %6 367} 368