420 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; bswap should be constant folded when it is passed a constant argument3 4; RUN: llc < %s -mtriple=i686-- -mcpu=i686 | FileCheck %s5; RUN: llc < %s -mtriple=x86_64-- | FileCheck %s --check-prefix=CHECK646 7declare i16 @llvm.bswap.i16(i16)8declare i32 @llvm.bswap.i32(i32)9declare i64 @llvm.bswap.i64(i64)10 11define i16 @W(i16 %A) {12; CHECK-LABEL: W:13; CHECK: # %bb.0:14; CHECK-NEXT: movzwl {{[0-9]+}}(%esp), %eax15; CHECK-NEXT: rolw $8, %ax16; CHECK-NEXT: retl17;18; CHECK64-LABEL: W:19; CHECK64: # %bb.0:20; CHECK64-NEXT: movl %edi, %eax21; CHECK64-NEXT: rolw $8, %ax22; CHECK64-NEXT: # kill: def $ax killed $ax killed $eax23; CHECK64-NEXT: retq24 %Z = call i16 @llvm.bswap.i16( i16 %A ) ; <i16> [#uses=1]25 ret i16 %Z26}27 28define dso_local i32 @X(i32 %A) {29; CHECK-LABEL: X:30; CHECK: # %bb.0:31; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax32; CHECK-NEXT: bswapl %eax33; CHECK-NEXT: retl34;35; CHECK64-LABEL: X:36; CHECK64: # %bb.0:37; CHECK64-NEXT: movl %edi, %eax38; CHECK64-NEXT: bswapl %eax39; CHECK64-NEXT: retq40 %Z = call i32 @llvm.bswap.i32( i32 %A ) ; <i32> [#uses=1]41 ret i32 %Z42}43 44define i64 @Y(i64 %A) {45; CHECK-LABEL: Y:46; CHECK: # %bb.0:47; CHECK-NEXT: movl {{[0-9]+}}(%esp), %edx48; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax49; CHECK-NEXT: bswapl %eax50; CHECK-NEXT: bswapl %edx51; CHECK-NEXT: retl52;53; CHECK64-LABEL: Y:54; CHECK64: # %bb.0:55; CHECK64-NEXT: movq %rdi, %rax56; CHECK64-NEXT: bswapq %rax57; CHECK64-NEXT: retq58 %Z = call i64 @llvm.bswap.i64( i64 %A ) ; <i64> [#uses=1]59 ret i64 %Z60}61 62; This isn't really a bswap test, but the potential probem is63; easier to see with bswap vs. other ops. The transform in64; question starts with a bitwise logic op and tries to hoist65; those ahead of other ops. But that's not generally profitable66; when the other ops have other uses (and it might not be safe67; either due to unconstrained instruction count growth).68 69define dso_local i32 @bswap_multiuse(i32 %x, i32 %y, ptr %p1, ptr %p2) nounwind {70; CHECK-LABEL: bswap_multiuse:71; CHECK: # %bb.0:72; CHECK-NEXT: pushl %esi73; CHECK-NEXT: movl {{[0-9]+}}(%esp), %ecx74; CHECK-NEXT: movl {{[0-9]+}}(%esp), %edx75; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax76; CHECK-NEXT: movl {{[0-9]+}}(%esp), %esi77; CHECK-NEXT: bswapl %esi78; CHECK-NEXT: bswapl %eax79; CHECK-NEXT: movl %esi, (%edx)80; CHECK-NEXT: movl %eax, (%ecx)81; CHECK-NEXT: orl %esi, %eax82; CHECK-NEXT: popl %esi83; CHECK-NEXT: retl84;85; CHECK64-LABEL: bswap_multiuse:86; CHECK64: # %bb.0:87; CHECK64-NEXT: movl %esi, %eax88; CHECK64-NEXT: bswapl %edi89; CHECK64-NEXT: bswapl %eax90; CHECK64-NEXT: movl %edi, (%rdx)91; CHECK64-NEXT: movl %eax, (%rcx)92; CHECK64-NEXT: orl %edi, %eax93; CHECK64-NEXT: retq94 %xt = call i32 @llvm.bswap.i32(i32 %x)95 %yt = call i32 @llvm.bswap.i32(i32 %y)96 store i32 %xt, ptr %p197 store i32 %yt, ptr %p298 %r = or i32 %xt, %yt99 ret i32 %r100}101 102; rdar://9164521103define dso_local i32 @test1(i32 %a) nounwind readnone {104; CHECK-LABEL: test1:105; CHECK: # %bb.0:106; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax107; CHECK-NEXT: bswapl %eax108; CHECK-NEXT: shrl $16, %eax109; CHECK-NEXT: retl110;111; CHECK64-LABEL: test1:112; CHECK64: # %bb.0:113; CHECK64-NEXT: movl %edi, %eax114; CHECK64-NEXT: bswapl %eax115; CHECK64-NEXT: shrl $16, %eax116; CHECK64-NEXT: retq117 %and = lshr i32 %a, 8118 %shr3 = and i32 %and, 255119 %and2 = shl i32 %a, 8120 %shl = and i32 %and2, 65280121 %or = or i32 %shr3, %shl122 ret i32 %or123}124 125define dso_local i32 @test2(i32 %a) nounwind readnone {126; CHECK-LABEL: test2:127; CHECK: # %bb.0:128; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax129; CHECK-NEXT: bswapl %eax130; CHECK-NEXT: sarl $16, %eax131; CHECK-NEXT: retl132;133; CHECK64-LABEL: test2:134; CHECK64: # %bb.0:135; CHECK64-NEXT: movl %edi, %eax136; CHECK64-NEXT: bswapl %eax137; CHECK64-NEXT: sarl $16, %eax138; CHECK64-NEXT: retq139 %and = lshr i32 %a, 8140 %shr4 = and i32 %and, 255141 %and2 = shl i32 %a, 8142 %or = or i32 %shr4, %and2143 %sext = shl i32 %or, 16144 %conv3 = ashr exact i32 %sext, 16145 ret i32 %conv3146}147 148@var8 = dso_local global i8 0149@var16 = dso_local global i16 0150 151; The "shl" below can move bits into the high parts of the value, so the152; operation is not a "bswap, shr" pair.153 154; rdar://problem/14814049155define i64 @not_bswap() {156; CHECK-LABEL: not_bswap:157; CHECK: # %bb.0:158; CHECK-NEXT: movzwl var16, %eax159; CHECK-NEXT: movl %eax, %ecx160; CHECK-NEXT: shrl $8, %ecx161; CHECK-NEXT: shll $8, %eax162; CHECK-NEXT: orl %ecx, %eax163; CHECK-NEXT: xorl %edx, %edx164; CHECK-NEXT: retl165;166; CHECK64-LABEL: not_bswap:167; CHECK64: # %bb.0:168; CHECK64-NEXT: movzwl var16(%rip), %eax169; CHECK64-NEXT: movl %eax, %ecx170; CHECK64-NEXT: shrl $8, %ecx171; CHECK64-NEXT: shll $8, %eax172; CHECK64-NEXT: orl %ecx, %eax173; CHECK64-NEXT: retq174 %init = load i16, ptr @var16175 %big = zext i16 %init to i64176 177 %hishifted = lshr i64 %big, 8178 %loshifted = shl i64 %big, 8179 180 %notswapped = or i64 %hishifted, %loshifted181 182 ret i64 %notswapped183}184 185; This time, the lshr (and subsequent or) is completely useless. While it's186; technically correct to convert this into a "bswap, shr", it's suboptimal. A187; simple shl works better.188 189define i64 @not_useful_bswap() {190; CHECK-LABEL: not_useful_bswap:191; CHECK: # %bb.0:192; CHECK-NEXT: movzbl var8, %eax193; CHECK-NEXT: shll $8, %eax194; CHECK-NEXT: xorl %edx, %edx195; CHECK-NEXT: retl196;197; CHECK64-LABEL: not_useful_bswap:198; CHECK64: # %bb.0:199; CHECK64-NEXT: movzbl var8(%rip), %eax200; CHECK64-NEXT: shll $8, %eax201; CHECK64-NEXT: retq202 %init = load i8, ptr @var8203 %big = zext i8 %init to i64204 205 %hishifted = lshr i64 %big, 8206 %loshifted = shl i64 %big, 8207 208 %notswapped = or i64 %hishifted, %loshifted209 210 ret i64 %notswapped211}212 213; Finally, it *is* OK to just mask off the shl if we know that the value is zero214; beyond 16 bits anyway. This is a legitimate bswap.215 216define i64 @finally_useful_bswap() {217; CHECK-LABEL: finally_useful_bswap:218; CHECK: # %bb.0:219; CHECK-NEXT: movzwl var16, %eax220; CHECK-NEXT: bswapl %eax221; CHECK-NEXT: shrl $16, %eax222; CHECK-NEXT: xorl %edx, %edx223; CHECK-NEXT: retl224;225; CHECK64-LABEL: finally_useful_bswap:226; CHECK64: # %bb.0:227; CHECK64-NEXT: movzwl var16(%rip), %eax228; CHECK64-NEXT: bswapl %eax229; CHECK64-NEXT: shrl $16, %eax230; CHECK64-NEXT: retq231 %init = load i16, ptr @var16232 %big = zext i16 %init to i64233 234 %hishifted = lshr i64 %big, 8235 %lomasked = and i64 %big, 255236 %loshifted = shl i64 %lomasked, 8237 238 %swapped = or i64 %hishifted, %loshifted239 240 ret i64 %swapped241}242 243; Make sure we don't assert during type legalization promoting a large244; bswap due to the need for a large shift that won't fit in the i8 returned245; from getShiftAmountTy.246define i528 @large_promotion(i528 %A) nounwind {247; CHECK-LABEL: large_promotion:248; CHECK: # %bb.0:249; CHECK-NEXT: pushl %ebp250; CHECK-NEXT: pushl %ebx251; CHECK-NEXT: pushl %edi252; CHECK-NEXT: pushl %esi253; CHECK-NEXT: subl $44, %esp254; CHECK-NEXT: movl {{[0-9]+}}(%esp), %ebp255; CHECK-NEXT: movl {{[0-9]+}}(%esp), %ebx256; CHECK-NEXT: movl {{[0-9]+}}(%esp), %edi257; CHECK-NEXT: movl {{[0-9]+}}(%esp), %esi258; CHECK-NEXT: movl {{[0-9]+}}(%esp), %edx259; CHECK-NEXT: movl {{[0-9]+}}(%esp), %ecx260; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax261; CHECK-NEXT: bswapl %eax262; CHECK-NEXT: bswapl %ecx263; CHECK-NEXT: shrdl $16, %ecx, %eax264; CHECK-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill265; CHECK-NEXT: bswapl %edx266; CHECK-NEXT: shrdl $16, %edx, %ecx267; CHECK-NEXT: movl %ecx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill268; CHECK-NEXT: bswapl %esi269; CHECK-NEXT: shrdl $16, %esi, %edx270; CHECK-NEXT: movl %edx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill271; CHECK-NEXT: bswapl %edi272; CHECK-NEXT: shrdl $16, %edi, %esi273; CHECK-NEXT: movl %esi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill274; CHECK-NEXT: bswapl %ebx275; CHECK-NEXT: shrdl $16, %ebx, %edi276; CHECK-NEXT: movl %edi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill277; CHECK-NEXT: bswapl %ebp278; CHECK-NEXT: shrdl $16, %ebp, %ebx279; CHECK-NEXT: movl %ebx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill280; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax281; CHECK-NEXT: bswapl %eax282; CHECK-NEXT: shrdl $16, %eax, %ebp283; CHECK-NEXT: movl %ebp, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill284; CHECK-NEXT: movl {{[0-9]+}}(%esp), %ecx285; CHECK-NEXT: bswapl %ecx286; CHECK-NEXT: shrdl $16, %ecx, %eax287; CHECK-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill288; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax289; CHECK-NEXT: bswapl %eax290; CHECK-NEXT: shrdl $16, %eax, %ecx291; CHECK-NEXT: movl %ecx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill292; CHECK-NEXT: movl {{[0-9]+}}(%esp), %ecx293; CHECK-NEXT: bswapl %ecx294; CHECK-NEXT: shrdl $16, %ecx, %eax295; CHECK-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill296; CHECK-NEXT: movl {{[0-9]+}}(%esp), %ebp297; CHECK-NEXT: bswapl %ebp298; CHECK-NEXT: shrdl $16, %ebp, %ecx299; CHECK-NEXT: movl %ecx, (%esp) # 4-byte Spill300; CHECK-NEXT: movl {{[0-9]+}}(%esp), %ebx301; CHECK-NEXT: bswapl %ebx302; CHECK-NEXT: shrdl $16, %ebx, %ebp303; CHECK-NEXT: movl {{[0-9]+}}(%esp), %esi304; CHECK-NEXT: bswapl %esi305; CHECK-NEXT: shrdl $16, %esi, %ebx306; CHECK-NEXT: movl {{[0-9]+}}(%esp), %edx307; CHECK-NEXT: bswapl %edx308; CHECK-NEXT: shrdl $16, %edx, %esi309; CHECK-NEXT: movl {{[0-9]+}}(%esp), %ecx310; CHECK-NEXT: bswapl %ecx311; CHECK-NEXT: shrdl $16, %ecx, %edx312; CHECK-NEXT: movl {{[0-9]+}}(%esp), %edi313; CHECK-NEXT: bswapl %edi314; CHECK-NEXT: shrdl $16, %edi, %ecx315; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax316; CHECK-NEXT: movl %ecx, 60(%eax)317; CHECK-NEXT: movl %edx, 56(%eax)318; CHECK-NEXT: movl %esi, 52(%eax)319; CHECK-NEXT: movl %ebx, 48(%eax)320; CHECK-NEXT: movl %ebp, 44(%eax)321; CHECK-NEXT: movl (%esp), %ecx # 4-byte Reload322; CHECK-NEXT: movl %ecx, 40(%eax)323; CHECK-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Reload324; CHECK-NEXT: movl %ecx, 36(%eax)325; CHECK-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Reload326; CHECK-NEXT: movl %ecx, 32(%eax)327; CHECK-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Reload328; CHECK-NEXT: movl %ecx, 28(%eax)329; CHECK-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Reload330; CHECK-NEXT: movl %ecx, 24(%eax)331; CHECK-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Reload332; CHECK-NEXT: movl %ecx, 20(%eax)333; CHECK-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Reload334; CHECK-NEXT: movl %ecx, 16(%eax)335; CHECK-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Reload336; CHECK-NEXT: movl %ecx, 12(%eax)337; CHECK-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Reload338; CHECK-NEXT: movl %ecx, 8(%eax)339; CHECK-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Reload340; CHECK-NEXT: movl %ecx, 4(%eax)341; CHECK-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Reload342; CHECK-NEXT: movl %ecx, (%eax)343; CHECK-NEXT: shrl $16, %edi344; CHECK-NEXT: movw %di, 64(%eax)345; CHECK-NEXT: addl $44, %esp346; CHECK-NEXT: popl %esi347; CHECK-NEXT: popl %edi348; CHECK-NEXT: popl %ebx349; CHECK-NEXT: popl %ebp350; CHECK-NEXT: retl $4351;352; CHECK64-LABEL: large_promotion:353; CHECK64: # %bb.0:354; CHECK64-NEXT: pushq %rbx355; CHECK64-NEXT: movq %rdi, %rax356; CHECK64-NEXT: movq {{[0-9]+}}(%rsp), %rbx357; CHECK64-NEXT: movq {{[0-9]+}}(%rsp), %r11358; CHECK64-NEXT: movq {{[0-9]+}}(%rsp), %r10359; CHECK64-NEXT: movq {{[0-9]+}}(%rsp), %rdi360; CHECK64-NEXT: bswapq %rdi361; CHECK64-NEXT: bswapq %r10362; CHECK64-NEXT: shrdq $48, %r10, %rdi363; CHECK64-NEXT: bswapq %r11364; CHECK64-NEXT: shrdq $48, %r11, %r10365; CHECK64-NEXT: bswapq %rbx366; CHECK64-NEXT: shrdq $48, %rbx, %r11367; CHECK64-NEXT: bswapq %r9368; CHECK64-NEXT: shrdq $48, %r9, %rbx369; CHECK64-NEXT: bswapq %r8370; CHECK64-NEXT: shrdq $48, %r8, %r9371; CHECK64-NEXT: bswapq %rcx372; CHECK64-NEXT: shrdq $48, %rcx, %r8373; CHECK64-NEXT: bswapq %rdx374; CHECK64-NEXT: shrdq $48, %rdx, %rcx375; CHECK64-NEXT: bswapq %rsi376; CHECK64-NEXT: shrdq $48, %rsi, %rdx377; CHECK64-NEXT: shrq $48, %rsi378; CHECK64-NEXT: movq %rdx, 56(%rax)379; CHECK64-NEXT: movq %rcx, 48(%rax)380; CHECK64-NEXT: movq %r8, 40(%rax)381; CHECK64-NEXT: movq %r9, 32(%rax)382; CHECK64-NEXT: movq %rbx, 24(%rax)383; CHECK64-NEXT: movq %r11, 16(%rax)384; CHECK64-NEXT: movq %r10, 8(%rax)385; CHECK64-NEXT: movq %rdi, (%rax)386; CHECK64-NEXT: movw %si, 64(%rax)387; CHECK64-NEXT: popq %rbx388; CHECK64-NEXT: retq389 %Z = call i528 @llvm.bswap.i528(i528 %A)390 ret i528 %Z391}392declare i528 @llvm.bswap.i528(i528)393 394define i32 @pr55484(i32 %0) {395; CHECK-LABEL: pr55484:396; CHECK: # %bb.0:397; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax398; CHECK-NEXT: movl %eax, %ecx399; CHECK-NEXT: shrl $8, %ecx400; CHECK-NEXT: shll $8, %eax401; CHECK-NEXT: orl %ecx, %eax402; CHECK-NEXT: cwtl403; CHECK-NEXT: retl404;405; CHECK64-LABEL: pr55484:406; CHECK64: # %bb.0:407; CHECK64-NEXT: movl %edi, %eax408; CHECK64-NEXT: shrl $8, %eax409; CHECK64-NEXT: shll $8, %edi410; CHECK64-NEXT: orl %eax, %edi411; CHECK64-NEXT: movswl %di, %eax412; CHECK64-NEXT: retq413 %2 = lshr i32 %0, 8414 %3 = shl i32 %0, 8415 %4 = or i32 %2, %3416 %5 = trunc i32 %4 to i16417 %6 = sext i16 %5 to i32418 ret i32 %6419}420