From ffd3bb8f0d875f4aae3097660f973b1e7512ee05 Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Fri, 5 Jul 2013 18:28:39 +0000 Subject: [PATCH] ARM: Fix incorrect pack pattern A "pkhtb x, x, y asr #num" uses the lower 16 bits of "y asr #num" and packs them in the bottom half of "x". An arithmetic and logic shift are only equivalent in this context if the shift amount is 16. We would be shifting in ones into the bottom 16bits instead of zeros if "y" is negative. radar://14338767 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@185712 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMInstrInfo.td | 6 ++++-- test/CodeGen/ARM/pack.ll | 15 ++++++++++++++- 2 files changed, 18 insertions(+), 3 deletions(-) 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 +}