diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index ed68b4e994c..75d3de94059 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -4011,9 +4011,11 @@ def PKHTB : APKHI<0b01101000, 1, (outs GPRnopc:$Rd), // Alternate cases for PKHTB where identities eliminate some nodes. Note that // a shift amount of 0 is *not legal* here, it is PKHBT instead. +// We also can not replace a srl (17..31) by an arithmetic shift we would use in +// pkhtb src1, src2, asr (17..31). def : ARMV6Pat<(or (and GPRnopc:$src1, 0xFFFF0000), - (srl GPRnopc:$src2, imm16_31:$sh)), - (PKHTB GPRnopc:$src1, GPRnopc:$src2, imm16_31:$sh)>; + (srl GPRnopc:$src2, imm16:$sh)), + (PKHTB GPRnopc:$src1, GPRnopc:$src2, imm16:$sh)>; def : ARMV6Pat<(or (and GPRnopc:$src1, 0xFFFF0000), (and (srl GPRnopc:$src2, imm1_15:$sh), 0xFFFF)), (PKHTB GPRnopc:$src1, GPRnopc:$src2, imm1_15:$sh)>; diff --git a/test/CodeGen/ARM/pack.ll b/test/CodeGen/ARM/pack.ll index 90151767b91..b94414328ca 100644 --- a/test/CodeGen/ARM/pack.ll +++ b/test/CodeGen/ARM/pack.ll @@ -78,11 +78,24 @@ define i32 @test7(i32 %X, i32 %Y) { ret i32 %tmp57 } +; Arithmetic and logic right shift does not have the same semantics if shifting +; by more than 16 in this context. + ; CHECK: test8 -; CHECK: pkhtb r0, r0, r1, asr #22 +; CHECK-NOT: pkhtb r0, r0, r1, asr #22 define i32 @test8(i32 %X, i32 %Y) { %tmp1 = and i32 %X, -65536 %tmp3 = lshr i32 %Y, 22 %tmp57 = or i32 %tmp3, %tmp1 ret i32 %tmp57 } + +; CHECK: test9: +; CHECK: pkhtb r0, r0, r1, asr #16 +define i32 @test9(i32 %src1, i32 %src2) { +entry: + %tmp = and i32 %src1, -65536 + %tmp2 = lshr i32 %src2, 16 + %tmp3 = or i32 %tmp, %tmp2 + ret i32 %tmp3 +}