397 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s3 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) - 17 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, %eax12; CHECK-NEXT: negb %dil13; CHECK-NEXT: sbbl %eax, %eax14; CHECK-NEXT: # kill: def $al killed $al killed $eax15; CHECK-NEXT: retq16 %cmp = icmp eq i8 %x, 017 %sel = select i1 %cmp, i8 0, i8 -118 ret i8 %sel19}20 21; (X == 0) ? 0 : -1 --> (X == 0) - 122 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, %eax27; CHECK-NEXT: negw %di28; CHECK-NEXT: sbbl %eax, %eax29; CHECK-NEXT: # kill: def $ax killed $ax killed $eax30; CHECK-NEXT: retq31 %cmp = icmp eq i16 %x, 032 %ext = zext i1 %cmp to i1633 %add = add i16 %ext, -134 ret i16 %add35}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, %eax43; CHECK-NEXT: negl %edi44; CHECK-NEXT: sbbl %eax, %eax45; CHECK-NEXT: retq46 %cmp = icmp ne i32 %x, 047 %sel = select i1 %cmp, i32 -1, i32 048 ret i32 %sel49}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, %eax57; CHECK-NEXT: negq %rdi58; CHECK-NEXT: sbbq %rax, %rax59; CHECK-NEXT: retq60 %cmp = icmp ne i64 %x, 061 %ext = zext i1 %cmp to i6462 %sub = sub i64 0, %ext63 ret i64 %sub64}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, %eax72; CHECK-NEXT: cmpq $1, %rdi73; CHECK-NEXT: sbbq %rax, %rax74; CHECK-NEXT: retq75 %cmp = icmp eq i64 %x, 076 %sel = select i1 %cmp, i64 -1, i64 077 ret i64 %sel78}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, %eax86; CHECK-NEXT: cmpl $1, %edi87; CHECK-NEXT: sbbl %eax, %eax88; CHECK-NEXT: retq89 %cmp = icmp eq i32 %x, 090 %ext = zext i1 %cmp to i3291 %sub = sub i32 0, %ext92 ret i32 %sub93}94 95; (X != 0) ? 0 : -1 --> (X != 0) - 196 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, %eax101; CHECK-NEXT: cmpw $1, %di102; CHECK-NEXT: sbbl %eax, %eax103; CHECK-NEXT: # kill: def $ax killed $ax killed $eax104; CHECK-NEXT: retq105 %cmp = icmp ne i16 %x, 0106 %sel = select i1 %cmp, i16 0, i16 -1107 ret i16 %sel108}109 110; (X != 0) ? 0 : -1 --> (X != 0) - 1111 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, %eax116; CHECK-NEXT: cmpb $1, %dil117; CHECK-NEXT: sbbl %eax, %eax118; CHECK-NEXT: # kill: def $al killed $al killed $eax119; CHECK-NEXT: retq120 %cmp = icmp ne i8 %x, 0121 %ext = zext i1 %cmp to i8122 %add = add i8 %ext, -1123 ret i8 %add124}125 126; (X <u Y) ? -1 : 0 --> cmp, sbb127 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, %eax132; CHECK-NEXT: cmpl %esi, %edi133; CHECK-NEXT: sbbl %eax, %eax134; CHECK-NEXT: retq135 %cmp = icmp ult i32 %x, %y136 %ext = sext i1 %cmp to i32137 ret i32 %ext138}139 140; Swap the predicate and compare operands:141; (Y >u X) ? -1 : 0 --> cmp, sbb142 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, %eax147; CHECK-NEXT: cmpl %esi, %edi148; CHECK-NEXT: sbbl %eax, %eax149; CHECK-NEXT: retq150 %cmp = icmp ugt i32 %y, %x151 %ext = sext i1 %cmp to i32152 ret i32 %ext153}154 155; Invert the predicate and effectively swap the select operands:156; (X >=u Y) ? 0 : -1 --> (X <u Y) ? -1 : 0 --> cmp, sbb157 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, %eax162; CHECK-NEXT: cmpl %esi, %edi163; CHECK-NEXT: sbbl %eax, %eax164; CHECK-NEXT: retq165 %cmp = icmp uge i32 %x, %y166 %ext = zext i1 %cmp to i32167 %add = add i32 %ext, -1168 ret i32 %add169}170 171; Swap the predicate and compare operands:172; (Y <=u X) ? 0 : -1 --> (X <u Y) ? -1 : 0 --> cmp, sbb173 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, %eax178; CHECK-NEXT: cmpl %esi, %edi179; CHECK-NEXT: sbbl %eax, %eax180; CHECK-NEXT: retq181 %cmp = icmp ule i32 %y, %x182 %ext = zext i1 %cmp to i32183 %add = add i32 %ext, -1184 ret i32 %add185}186 187; Verify that subtract with constant is the same thing.188; (X >=u Y) ? 0 : -1 --> (X <u Y) ? -1 : 0 --> cmp, sbb189 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, %eax194; CHECK-NEXT: cmpl %esi, %edi195; CHECK-NEXT: sbbl %eax, %eax196; CHECK-NEXT: retq197 %cmp = icmp uge i32 %x, %y198 %ext = zext i1 %cmp to i32199 %sub = sub i32 %ext, 1200 ret i32 %sub201}202 203; Check more sub-from-zero patterns.204; (X >u Y) ? -1 : 0 --> cmp, sbb205 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, %eax210; CHECK-NEXT: cmpq %rdi, %rsi211; CHECK-NEXT: sbbq %rax, %rax212; CHECK-NEXT: retq213 %cmp = icmp ugt i64 %x, %y214 %zext = zext i1 %cmp to i64215 %sub = sub i64 0, %zext216 ret i64 %sub217}218 219; Swap the predicate and compare operands:220; (Y <u X) ? -1 : 0 --> cmp, sbb221 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, %eax226; CHECK-NEXT: cmpw %di, %si227; CHECK-NEXT: sbbl %eax, %eax228; CHECK-NEXT: # kill: def $ax killed $ax killed $eax229; CHECK-NEXT: retq230 %cmp = icmp ult i16 %y, %x231 %zext = zext i1 %cmp to i16232 %sub = sub i16 0, %zext233 ret i16 %sub234}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=33560240 241define void @PR33560(i8 %x, i64 %y) {242; CHECK-LABEL: PR33560:243; CHECK: # %bb.0: # %entry244; CHECK-NEXT: xorl %eax, %eax245; CHECK-NEXT: negb %dil246; CHECK-NEXT: sbbq %rax, %rax247; CHECK-NEXT: cmpq %rsi, %rax248; CHECK-NEXT: retq249entry:250 %cmp1 = icmp eq i8 %x, 0251 %ext = zext i1 %cmp1 to i64252 %add = add i64 %ext, -1253 %cmp2 = icmp eq i64 %add, %y254 br i1 %cmp2, label %end, label %else255 256else:257 %tmp7 = zext i1 %cmp1 to i8258 br label %end259 260end:261 ret void262}263 264; Cases for PR45700265define 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, %eax269; CHECK-NEXT: cmpl %edx, %esi270; CHECK-NEXT: adcl $0, %eax271; CHECK-NEXT: retq272 %4 = icmp ult i32 %1, %2273 %5 = zext i1 %4 to i32274 %6 = add nsw i32 %5, %0275 ret i32 %6276}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, %eax282; CHECK-NEXT: cmpl %esi, %edx283; CHECK-NEXT: sbbl $-1, %eax284; CHECK-NEXT: retq285 %4 = icmp ule i32 %1, %2286 %5 = zext i1 %4 to i32287 %6 = add nsw i32 %5, %0288 ret i32 %6289}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, %eax295; CHECK-NEXT: cmpl %esi, %edx296; CHECK-NEXT: adcl $0, %eax297; CHECK-NEXT: retq298 %4 = icmp ugt i32 %1, %2299 %5 = zext i1 %4 to i32300 %6 = add nsw i32 %5, %0301 ret i32 %6302}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, %eax308; CHECK-NEXT: cmpl %edx, %esi309; CHECK-NEXT: sbbl $-1, %eax310; CHECK-NEXT: retq311 %4 = icmp uge i32 %1, %2312 %5 = zext i1 %4 to i32313 %6 = add nsw i32 %5, %0314 ret i32 %6315}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, %eax321; CHECK-NEXT: cmpl %edx, %esi322; CHECK-NEXT: sbbl $0, %eax323; CHECK-NEXT: retq324 %4 = icmp ult i32 %1, %2325 %5 = sext i1 %4 to i32326 %6 = add nsw i32 %5, %0327 ret i32 %6328}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, %eax334; CHECK-NEXT: cmpl %esi, %edx335; CHECK-NEXT: adcl $-1, %eax336; CHECK-NEXT: retq337 %4 = icmp ule i32 %1, %2338 %5 = sext i1 %4 to i32339 %6 = add nsw i32 %5, %0340 ret i32 %6341}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, %eax347; CHECK-NEXT: cmpl %esi, %edx348; CHECK-NEXT: sbbl $0, %eax349; CHECK-NEXT: retq350 %4 = icmp ugt i32 %1, %2351 %5 = sext i1 %4 to i32352 %6 = add nsw i32 %5, %0353 ret i32 %6354}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, %eax360; CHECK-NEXT: cmpl %edx, %esi361; CHECK-NEXT: adcl $-1, %eax362; CHECK-NEXT: retq363 %4 = icmp uge i32 %1, %2364 %5 = sext i1 %4 to i32365 %6 = add nsw i32 %5, %0366 ret i32 %6367}368 369define i32 @sub_sub_ugt(i32 %a, i32 %b) {370; CHECK-LABEL: sub_sub_ugt:371; CHECK: # %bb.0:372; CHECK-NEXT: movl %edi, %eax373; CHECK-NEXT: cmpl %edi, %esi374; CHECK-NEXT: sbbl %esi, %eax375; CHECK-NEXT: retq376 %cmp = icmp ugt i32 %a, %b377 %conv = zext i1 %cmp to i32378 %sub = sub i32 %a, %b379 %res = sub i32 %sub, %conv380 ret i32 %res381}382 383define i32 @sub_sub_ult(i32 %a, i32 %b) {384; CHECK-LABEL: sub_sub_ult:385; CHECK: # %bb.0:386; CHECK-NEXT: movl %edi, %eax387; CHECK-NEXT: cmpl %edi, %esi388; CHECK-NEXT: sbbl %esi, %eax389; CHECK-NEXT: retq390 %cmp = icmp ult i32 %b, %a391 %conv = zext i1 %cmp to i32392 %sub = sub i32 %a, %b393 %res = sub i32 %sub, %conv394 ret i32 %res395}396 397