383 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc < %s -mtriple=i686-unknown-unknown | FileCheck %s --check-prefixes=X863; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s --check-prefixes=X644; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+bmi | FileCheck %s --check-prefixes=X645 6; PR522677; InstCombine transforms an 'add' with min-signed-value into an 'xor'.8; LEA instruction selection should be able to see through that9; transform and reduce add/shift/xor instruction counts and moves.10 11;12; XOR(X,MIN_SIGNED_VALUE)13;14 15define i8 @xor_sminval_i8(i8 %x) {16; X86-LABEL: xor_sminval_i8:17; X86: # %bb.0:18; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax19; X86-NEXT: addb $-128, %al20; X86-NEXT: retl21;22; X64-LABEL: xor_sminval_i8:23; X64: # %bb.0:24; X64-NEXT: # kill: def $edi killed $edi def $rdi25; X64-NEXT: leal -128(%rdi), %eax26; X64-NEXT: # kill: def $al killed $al killed $eax27; X64-NEXT: retq28 %r = xor i8 %x, 12829 ret i8 %r30}31 32; negative test33define i8 @xor_notsminval_i8(i8 %x) {34; X86-LABEL: xor_notsminval_i8:35; X86: # %bb.0:36; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax37; X86-NEXT: xorb $127, %al38; X86-NEXT: retl39;40; X64-LABEL: xor_notsminval_i8:41; X64: # %bb.0:42; X64-NEXT: movl %edi, %eax43; X64-NEXT: xorb $127, %al44; X64-NEXT: # kill: def $al killed $al killed $eax45; X64-NEXT: retq46 %r = xor i8 %x, 12747 ret i8 %r48}49 50define i16 @xor_sminval_i16(i16 %x) {51; X86-LABEL: xor_sminval_i16:52; X86: # %bb.0:53; X86-NEXT: movl $32768, %eax # imm = 0x800054; X86-NEXT: xorl {{[0-9]+}}(%esp), %eax55; X86-NEXT: # kill: def $ax killed $ax killed $eax56; X86-NEXT: retl57;58; X64-LABEL: xor_sminval_i16:59; X64: # %bb.0:60; X64-NEXT: movl %edi, %eax61; X64-NEXT: xorl $32768, %eax # imm = 0x800062; X64-NEXT: # kill: def $ax killed $ax killed $eax63; X64-NEXT: retq64 %r = xor i16 %x, 3276865 ret i16 %r66}67 68define i32 @xor_sminval_i32(i32 %x) {69; X86-LABEL: xor_sminval_i32:70; X86: # %bb.0:71; X86-NEXT: movl $-2147483648, %eax # imm = 0x8000000072; X86-NEXT: xorl {{[0-9]+}}(%esp), %eax73; X86-NEXT: retl74;75; X64-LABEL: xor_sminval_i32:76; X64: # %bb.0:77; X64-NEXT: # kill: def $edi killed $edi def $rdi78; X64-NEXT: leal -2147483648(%rdi), %eax79; X64-NEXT: retq80 %r = xor i32 %x, 214748364881 ret i32 %r82}83 84; negative test85define i32 @xor_notsminval_i32(i32 %x) {86; X86-LABEL: xor_notsminval_i32:87; X86: # %bb.0:88; X86-NEXT: movl $32768, %eax # imm = 0x800089; X86-NEXT: xorl {{[0-9]+}}(%esp), %eax90; X86-NEXT: retl91;92; X64-LABEL: xor_notsminval_i32:93; X64: # %bb.0:94; X64-NEXT: movl %edi, %eax95; X64-NEXT: xorl $32768, %eax # imm = 0x800096; X64-NEXT: retq97 %r = xor i32 %x, 3276898 ret i32 %r99}100 101define i64 @xor_sminval_i64(i64 %x) {102; X86-LABEL: xor_sminval_i64:103; X86: # %bb.0:104; X86-NEXT: movl {{[0-9]+}}(%esp), %eax105; X86-NEXT: movl $-2147483648, %edx # imm = 0x80000000106; X86-NEXT: xorl {{[0-9]+}}(%esp), %edx107; X86-NEXT: retl108;109; X64-LABEL: xor_sminval_i64:110; X64: # %bb.0:111; X64-NEXT: movabsq $-9223372036854775808, %rax # imm = 0x8000000000000000112; X64-NEXT: xorq %rdi, %rax113; X64-NEXT: retq114 %r = xor i64 %x, -9223372036854775808115 ret i64 %r116}117 118;119; XOR(ADD/SUB(X,C),MIN_SIGNED_VALUE)120;121 122define i8 @xor_add_sminval_i8(i8 %x, i8 %y) {123; X86-LABEL: xor_add_sminval_i8:124; X86: # %bb.0:125; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax126; X86-NEXT: addb {{[0-9]+}}(%esp), %al127; X86-NEXT: addb $-128, %al128; X86-NEXT: retl129;130; X64-LABEL: xor_add_sminval_i8:131; X64: # %bb.0:132; X64-NEXT: # kill: def $esi killed $esi def $rsi133; X64-NEXT: # kill: def $edi killed $edi def $rdi134; X64-NEXT: leal (%rdi,%rsi), %eax135; X64-NEXT: addb $-128, %al136; X64-NEXT: # kill: def $al killed $al killed $eax137; X64-NEXT: retq138 %s = add i8 %x, %y139 %r = xor i8 %s, 128140 ret i8 %r141}142 143define i16 @xor_sub_sminval_i16(i16 %x) {144; X86-LABEL: xor_sub_sminval_i16:145; X86: # %bb.0:146; X86-NEXT: movl $32766, %eax # imm = 0x7FFE147; X86-NEXT: addl {{[0-9]+}}(%esp), %eax148; X86-NEXT: # kill: def $ax killed $ax killed $eax149; X86-NEXT: retl150;151; X64-LABEL: xor_sub_sminval_i16:152; X64: # %bb.0:153; X64-NEXT: # kill: def $edi killed $edi def $rdi154; X64-NEXT: leal 32766(%rdi), %eax155; X64-NEXT: # kill: def $ax killed $ax killed $eax156; X64-NEXT: retq157 %s = sub i16 %x, 2158 %r = xor i16 %s, 32768159 ret i16 %r160}161 162define i32 @xor_add_sminval_i32(i32 %x) {163; X86-LABEL: xor_add_sminval_i32:164; X86: # %bb.0:165; X86-NEXT: movl $-2147483136, %eax # imm = 0x80000200166; X86-NEXT: addl {{[0-9]+}}(%esp), %eax167; X86-NEXT: retl168;169; X64-LABEL: xor_add_sminval_i32:170; X64: # %bb.0:171; X64-NEXT: # kill: def $edi killed $edi def $rdi172; X64-NEXT: leal -2147483136(%rdi), %eax173; X64-NEXT: retq174 %s = add i32 %x, 512175 %r = xor i32 %s, 2147483648176 ret i32 %r177}178 179define i64 @xor_add_sminval_i64(i64 %x, i64 %y) {180; X86-LABEL: xor_add_sminval_i64:181; X86: # %bb.0:182; X86-NEXT: movl {{[0-9]+}}(%esp), %eax183; X86-NEXT: movl {{[0-9]+}}(%esp), %edx184; X86-NEXT: addl {{[0-9]+}}(%esp), %eax185; X86-NEXT: adcl {{[0-9]+}}(%esp), %edx186; X86-NEXT: addl $-2147483648, %edx # imm = 0x80000000187; X86-NEXT: retl188;189; X64-LABEL: xor_add_sminval_i64:190; X64: # %bb.0:191; X64-NEXT: leaq (%rdi,%rsi), %rcx192; X64-NEXT: movabsq $-9223372036854775808, %rax # imm = 0x8000000000000000193; X64-NEXT: xorq %rcx, %rax194; X64-NEXT: retq195 %s = add i64 %x, %y196 %r = xor i64 %s, -9223372036854775808197 ret i64 %r198}199 200;201; ADD/SUB(XOR(X,MIN_SIGNED_VALUE),C)202;203 204define i8 @sub_xor_sminval_i8(i8 %x, i8 %y) {205; X86-LABEL: sub_xor_sminval_i8:206; X86: # %bb.0:207; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax208; X86-NEXT: addb $-128, %al209; X86-NEXT: subb {{[0-9]+}}(%esp), %al210; X86-NEXT: retl211;212; X64-LABEL: sub_xor_sminval_i8:213; X64: # %bb.0:214; X64-NEXT: # kill: def $edi killed $edi def $rdi215; X64-NEXT: leal -128(%rdi), %eax216; X64-NEXT: subb %sil, %al217; X64-NEXT: # kill: def $al killed $al killed $eax218; X64-NEXT: retq219 %r = xor i8 %x, 128220 %s = sub i8 %r, %y221 ret i8 %s222}223 224define i16 @add_xor_sminval_i16(i16 %x) {225; X86-LABEL: add_xor_sminval_i16:226; X86: # %bb.0:227; X86-NEXT: movl $-32766, %eax # imm = 0x8002228; X86-NEXT: addl {{[0-9]+}}(%esp), %eax229; X86-NEXT: # kill: def $ax killed $ax killed $eax230; X86-NEXT: retl231;232; X64-LABEL: add_xor_sminval_i16:233; X64: # %bb.0:234; X64-NEXT: # kill: def $edi killed $edi def $rdi235; X64-NEXT: leal -32766(%rdi), %eax236; X64-NEXT: # kill: def $ax killed $ax killed $eax237; X64-NEXT: retq238 %r = xor i16 %x, 32768239 %s = add i16 %r, 2240 ret i16 %s241}242 243define i32 @sub_xor_sminval_i32(i32 %x) {244; X86-LABEL: sub_xor_sminval_i32:245; X86: # %bb.0:246; X86-NEXT: movl $2147483136, %eax # imm = 0x7FFFFE00247; X86-NEXT: addl {{[0-9]+}}(%esp), %eax248; X86-NEXT: retl249;250; X64-LABEL: sub_xor_sminval_i32:251; X64: # %bb.0:252; X64-NEXT: # kill: def $edi killed $edi def $rdi253; X64-NEXT: leal 2147483136(%rdi), %eax254; X64-NEXT: retq255 %r = xor i32 %x, 2147483648256 %s = sub i32 %r, 512257 ret i32 %s258}259 260define i64 @add_xor_sminval_i64(i64 %x, i64 %y) {261; X86-LABEL: add_xor_sminval_i64:262; X86: # %bb.0:263; X86-NEXT: movl {{[0-9]+}}(%esp), %eax264; X86-NEXT: movl {{[0-9]+}}(%esp), %edx265; X86-NEXT: addl {{[0-9]+}}(%esp), %eax266; X86-NEXT: adcl {{[0-9]+}}(%esp), %edx267; X86-NEXT: addl $-2147483648, %edx # imm = 0x80000000268; X86-NEXT: retl269;270; X64-LABEL: add_xor_sminval_i64:271; X64: # %bb.0:272; X64-NEXT: movabsq $-9223372036854775808, %rax # imm = 0x8000000000000000273; X64-NEXT: addq %rdi, %rax274; X64-NEXT: addq %rsi, %rax275; X64-NEXT: retq276 %r = xor i64 %x, -9223372036854775808277 %s = add i64 %y, %r278 ret i64 %s279}280 281;282; XOR(SHL(X,C),MIN_SIGNED_VALUE)283;284 285define i8 @xor_shl_sminval_i8(i8 %x) {286; X86-LABEL: xor_shl_sminval_i8:287; X86: # %bb.0:288; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax289; X86-NEXT: addb %al, %al290; X86-NEXT: addb $-128, %al291; X86-NEXT: retl292;293; X64-LABEL: xor_shl_sminval_i8:294; X64: # %bb.0:295; X64-NEXT: # kill: def $edi killed $edi def $rdi296; X64-NEXT: leal (%rdi,%rdi), %eax297; X64-NEXT: addb $-128, %al298; X64-NEXT: # kill: def $al killed $al killed $eax299; X64-NEXT: retq300 %s = shl i8 %x, 1301 %r = xor i8 %s, 128302 ret i8 %r303}304 305define i16 @xor_shl_sminval_i16(i16 %x) {306; X86-LABEL: xor_shl_sminval_i16:307; X86: # %bb.0:308; X86-NEXT: movl {{[0-9]+}}(%esp), %eax309; X86-NEXT: shll $2, %eax310; X86-NEXT: xorl $32768, %eax # imm = 0x8000311; X86-NEXT: # kill: def $ax killed $ax killed $eax312; X86-NEXT: retl313;314; X64-LABEL: xor_shl_sminval_i16:315; X64: # %bb.0:316; X64-NEXT: # kill: def $edi killed $edi def $rdi317; X64-NEXT: leal (,%rdi,4), %eax318; X64-NEXT: xorl $32768, %eax # imm = 0x8000319; X64-NEXT: # kill: def $ax killed $ax killed $eax320; X64-NEXT: retq321 %s = shl i16 %x, 2322 %r = xor i16 %s, 32768323 ret i16 %r324}325 326define i32 @xor_shl_sminval_i32(i32 %x) {327; X86-LABEL: xor_shl_sminval_i32:328; X86: # %bb.0:329; X86-NEXT: movl {{[0-9]+}}(%esp), %eax330; X86-NEXT: movl $-2147483648, %ecx # imm = 0x80000000331; X86-NEXT: leal (%ecx,%eax,8), %eax332; X86-NEXT: retl333;334; X64-LABEL: xor_shl_sminval_i32:335; X64: # %bb.0:336; X64-NEXT: # kill: def $edi killed $edi def $rdi337; X64-NEXT: leal -2147483648(,%rdi,8), %eax338; X64-NEXT: retq339 %s = shl i32 %x, 3340 %r = xor i32 %s, 2147483648341 ret i32 %r342}343 344; negative test345define i32 @xor_bigshl_sminval_i32(i32 %x) {346; X86-LABEL: xor_bigshl_sminval_i32:347; X86: # %bb.0:348; X86-NEXT: movl {{[0-9]+}}(%esp), %eax349; X86-NEXT: shll $8, %eax350; X86-NEXT: addl $-2147483648, %eax # imm = 0x80000000351; X86-NEXT: retl352;353; X64-LABEL: xor_bigshl_sminval_i32:354; X64: # %bb.0:355; X64-NEXT: # kill: def $edi killed $edi def $rdi356; X64-NEXT: shll $8, %edi357; X64-NEXT: leal -2147483648(%rdi), %eax358; X64-NEXT: retq359 %s = shl i32 %x, 8360 %r = xor i32 %s, 2147483648361 ret i32 %r362}363 364define i64 @xor_shl_sminval_i64(i64 %x) {365; X86-LABEL: xor_shl_sminval_i64:366; X86: # %bb.0:367; X86-NEXT: movl {{[0-9]+}}(%esp), %eax368; X86-NEXT: movl {{[0-9]+}}(%esp), %edx369; X86-NEXT: shldl $2, %eax, %edx370; X86-NEXT: shll $2, %eax371; X86-NEXT: addl $-2147483648, %edx # imm = 0x80000000372; X86-NEXT: retl373;374; X64-LABEL: xor_shl_sminval_i64:375; X64: # %bb.0:376; X64-NEXT: movabsq $-9223372036854775808, %rax # imm = 0x8000000000000000377; X64-NEXT: leaq (%rax,%rdi,4), %rax378; X64-NEXT: retq379 %s = shl i64 %x, 2380 %r = xor i64 %s, -9223372036854775808381 ret i64 %r382}383