1*9880d681SAndroid Build Coastguard Worker; bswap should be constant folded when it is passed a constant argument 2*9880d681SAndroid Build Coastguard Worker 3*9880d681SAndroid Build Coastguard Worker; RUN: llc < %s -march=x86 -mcpu=i686 | FileCheck %s 4*9880d681SAndroid Build Coastguard Worker; RUN: llc < %s -march=x86-64 | FileCheck %s --check-prefix=CHECK64 5*9880d681SAndroid Build Coastguard Worker 6*9880d681SAndroid Build Coastguard Workerdeclare i16 @llvm.bswap.i16(i16) 7*9880d681SAndroid Build Coastguard Worker 8*9880d681SAndroid Build Coastguard Workerdeclare i32 @llvm.bswap.i32(i32) 9*9880d681SAndroid Build Coastguard Worker 10*9880d681SAndroid Build Coastguard Workerdeclare i64 @llvm.bswap.i64(i64) 11*9880d681SAndroid Build Coastguard Worker 12*9880d681SAndroid Build Coastguard Workerdefine i16 @W(i16 %A) { 13*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: W: 14*9880d681SAndroid Build Coastguard Worker; CHECK: rolw $8, %ax 15*9880d681SAndroid Build Coastguard Worker 16*9880d681SAndroid Build Coastguard Worker; CHECK64-LABEL: W: 17*9880d681SAndroid Build Coastguard Worker; CHECK64: rolw $8, % 18*9880d681SAndroid Build Coastguard Worker %Z = call i16 @llvm.bswap.i16( i16 %A ) ; <i16> [#uses=1] 19*9880d681SAndroid Build Coastguard Worker ret i16 %Z 20*9880d681SAndroid Build Coastguard Worker} 21*9880d681SAndroid Build Coastguard Worker 22*9880d681SAndroid Build Coastguard Workerdefine i32 @X(i32 %A) { 23*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: X: 24*9880d681SAndroid Build Coastguard Worker; CHECK: bswapl %eax 25*9880d681SAndroid Build Coastguard Worker 26*9880d681SAndroid Build Coastguard Worker; CHECK64-LABEL: X: 27*9880d681SAndroid Build Coastguard Worker; CHECK64: bswapl % 28*9880d681SAndroid Build Coastguard Worker %Z = call i32 @llvm.bswap.i32( i32 %A ) ; <i32> [#uses=1] 29*9880d681SAndroid Build Coastguard Worker ret i32 %Z 30*9880d681SAndroid Build Coastguard Worker} 31*9880d681SAndroid Build Coastguard Worker 32*9880d681SAndroid Build Coastguard Workerdefine i64 @Y(i64 %A) { 33*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: Y: 34*9880d681SAndroid Build Coastguard Worker; CHECK: bswapl %eax 35*9880d681SAndroid Build Coastguard Worker; CHECK: bswapl %edx 36*9880d681SAndroid Build Coastguard Worker 37*9880d681SAndroid Build Coastguard Worker; CHECK64-LABEL: Y: 38*9880d681SAndroid Build Coastguard Worker; CHECK64: bswapq % 39*9880d681SAndroid Build Coastguard Worker %Z = call i64 @llvm.bswap.i64( i64 %A ) ; <i64> [#uses=1] 40*9880d681SAndroid Build Coastguard Worker ret i64 %Z 41*9880d681SAndroid Build Coastguard Worker} 42*9880d681SAndroid Build Coastguard Worker 43*9880d681SAndroid Build Coastguard Worker; rdar://9164521 44*9880d681SAndroid Build Coastguard Workerdefine i32 @test1(i32 %a) nounwind readnone { 45*9880d681SAndroid Build Coastguard Workerentry: 46*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: test1: 47*9880d681SAndroid Build Coastguard Worker; CHECK: bswapl [[REG:%.*]] 48*9880d681SAndroid Build Coastguard Worker; CHECK: shrl $16, [[REG]] 49*9880d681SAndroid Build Coastguard Worker 50*9880d681SAndroid Build Coastguard Worker; CHECK64-LABEL: test1: 51*9880d681SAndroid Build Coastguard Worker; CHECK64: bswapl [[REG:%.*]] 52*9880d681SAndroid Build Coastguard Worker; CHECK64: shrl $16, [[REG]] 53*9880d681SAndroid Build Coastguard Worker %and = lshr i32 %a, 8 54*9880d681SAndroid Build Coastguard Worker %shr3 = and i32 %and, 255 55*9880d681SAndroid Build Coastguard Worker %and2 = shl i32 %a, 8 56*9880d681SAndroid Build Coastguard Worker %shl = and i32 %and2, 65280 57*9880d681SAndroid Build Coastguard Worker %or = or i32 %shr3, %shl 58*9880d681SAndroid Build Coastguard Worker ret i32 %or 59*9880d681SAndroid Build Coastguard Worker} 60*9880d681SAndroid Build Coastguard Worker 61*9880d681SAndroid Build Coastguard Workerdefine i32 @test2(i32 %a) nounwind readnone { 62*9880d681SAndroid Build Coastguard Workerentry: 63*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: test2: 64*9880d681SAndroid Build Coastguard Worker; CHECK: bswapl [[REG:%.*]] 65*9880d681SAndroid Build Coastguard Worker; CHECK: sarl $16, [[REG]] 66*9880d681SAndroid Build Coastguard Worker 67*9880d681SAndroid Build Coastguard Worker; CHECK64-LABEL: test2: 68*9880d681SAndroid Build Coastguard Worker; CHECK64: bswapl [[REG:%.*]] 69*9880d681SAndroid Build Coastguard Worker; CHECK64: sarl $16, [[REG]] 70*9880d681SAndroid Build Coastguard Worker %and = lshr i32 %a, 8 71*9880d681SAndroid Build Coastguard Worker %shr4 = and i32 %and, 255 72*9880d681SAndroid Build Coastguard Worker %and2 = shl i32 %a, 8 73*9880d681SAndroid Build Coastguard Worker %or = or i32 %shr4, %and2 74*9880d681SAndroid Build Coastguard Worker %sext = shl i32 %or, 16 75*9880d681SAndroid Build Coastguard Worker %conv3 = ashr exact i32 %sext, 16 76*9880d681SAndroid Build Coastguard Worker ret i32 %conv3 77*9880d681SAndroid Build Coastguard Worker} 78*9880d681SAndroid Build Coastguard Worker 79*9880d681SAndroid Build Coastguard Worker@var8 = global i8 0 80*9880d681SAndroid Build Coastguard Worker@var16 = global i16 0 81*9880d681SAndroid Build Coastguard Worker 82*9880d681SAndroid Build Coastguard Worker; The "shl" below can move bits into the high parts of the value, so the 83*9880d681SAndroid Build Coastguard Worker; operation is not a "bswap, shr" pair. 84*9880d681SAndroid Build Coastguard Worker 85*9880d681SAndroid Build Coastguard Worker; rdar://problem/14814049 86*9880d681SAndroid Build Coastguard Workerdefine i64 @not_bswap() { 87*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: not_bswap: 88*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: bswapl 89*9880d681SAndroid Build Coastguard Worker; CHECK: ret 90*9880d681SAndroid Build Coastguard Worker 91*9880d681SAndroid Build Coastguard Worker; CHECK64-LABEL: not_bswap: 92*9880d681SAndroid Build Coastguard Worker; CHECK64-NOT: bswapq 93*9880d681SAndroid Build Coastguard Worker; CHECK64: ret 94*9880d681SAndroid Build Coastguard Worker %init = load i16, i16* @var16 95*9880d681SAndroid Build Coastguard Worker %big = zext i16 %init to i64 96*9880d681SAndroid Build Coastguard Worker 97*9880d681SAndroid Build Coastguard Worker %hishifted = lshr i64 %big, 8 98*9880d681SAndroid Build Coastguard Worker %loshifted = shl i64 %big, 8 99*9880d681SAndroid Build Coastguard Worker 100*9880d681SAndroid Build Coastguard Worker %notswapped = or i64 %hishifted, %loshifted 101*9880d681SAndroid Build Coastguard Worker 102*9880d681SAndroid Build Coastguard Worker ret i64 %notswapped 103*9880d681SAndroid Build Coastguard Worker} 104*9880d681SAndroid Build Coastguard Worker 105*9880d681SAndroid Build Coastguard Worker; This time, the lshr (and subsequent or) is completely useless. While it's 106*9880d681SAndroid Build Coastguard Worker; technically correct to convert this into a "bswap, shr", it's suboptimal. A 107*9880d681SAndroid Build Coastguard Worker; simple shl works better. 108*9880d681SAndroid Build Coastguard Worker 109*9880d681SAndroid Build Coastguard Workerdefine i64 @not_useful_bswap() { 110*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: not_useful_bswap: 111*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: bswapl 112*9880d681SAndroid Build Coastguard Worker; CHECK: ret 113*9880d681SAndroid Build Coastguard Worker 114*9880d681SAndroid Build Coastguard Worker; CHECK64-LABEL: not_useful_bswap: 115*9880d681SAndroid Build Coastguard Worker; CHECK64-NOT: bswapq 116*9880d681SAndroid Build Coastguard Worker; CHECK64: ret 117*9880d681SAndroid Build Coastguard Worker 118*9880d681SAndroid Build Coastguard Worker %init = load i8, i8* @var8 119*9880d681SAndroid Build Coastguard Worker %big = zext i8 %init to i64 120*9880d681SAndroid Build Coastguard Worker 121*9880d681SAndroid Build Coastguard Worker %hishifted = lshr i64 %big, 8 122*9880d681SAndroid Build Coastguard Worker %loshifted = shl i64 %big, 8 123*9880d681SAndroid Build Coastguard Worker 124*9880d681SAndroid Build Coastguard Worker %notswapped = or i64 %hishifted, %loshifted 125*9880d681SAndroid Build Coastguard Worker 126*9880d681SAndroid Build Coastguard Worker ret i64 %notswapped 127*9880d681SAndroid Build Coastguard Worker} 128*9880d681SAndroid Build Coastguard Worker 129*9880d681SAndroid Build Coastguard Worker; Finally, it *is* OK to just mask off the shl if we know that the value is zero 130*9880d681SAndroid Build Coastguard Worker; beyond 16 bits anyway. This is a legitimate bswap. 131*9880d681SAndroid Build Coastguard Worker 132*9880d681SAndroid Build Coastguard Workerdefine i64 @finally_useful_bswap() { 133*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: finally_useful_bswap: 134*9880d681SAndroid Build Coastguard Worker; CHECK: bswapl [[REG:%.*]] 135*9880d681SAndroid Build Coastguard Worker; CHECK: shrl $16, [[REG]] 136*9880d681SAndroid Build Coastguard Worker; CHECK: ret 137*9880d681SAndroid Build Coastguard Worker 138*9880d681SAndroid Build Coastguard Worker; CHECK64-LABEL: finally_useful_bswap: 139*9880d681SAndroid Build Coastguard Worker; CHECK64: bswapq [[REG:%.*]] 140*9880d681SAndroid Build Coastguard Worker; CHECK64: shrq $48, [[REG]] 141*9880d681SAndroid Build Coastguard Worker; CHECK64: ret 142*9880d681SAndroid Build Coastguard Worker 143*9880d681SAndroid Build Coastguard Worker %init = load i16, i16* @var16 144*9880d681SAndroid Build Coastguard Worker %big = zext i16 %init to i64 145*9880d681SAndroid Build Coastguard Worker 146*9880d681SAndroid Build Coastguard Worker %hishifted = lshr i64 %big, 8 147*9880d681SAndroid Build Coastguard Worker %lomasked = and i64 %big, 255 148*9880d681SAndroid Build Coastguard Worker %loshifted = shl i64 %lomasked, 8 149*9880d681SAndroid Build Coastguard Worker 150*9880d681SAndroid Build Coastguard Worker %swapped = or i64 %hishifted, %loshifted 151*9880d681SAndroid Build Coastguard Worker 152*9880d681SAndroid Build Coastguard Worker ret i64 %swapped 153*9880d681SAndroid Build Coastguard Worker} 154*9880d681SAndroid Build Coastguard Worker 155