From: Guozhi Wei Date: Thu, 2 Mar 2017 21:07:59 +0000 (+0000) Subject: [PPC] Fix code generation for bswap(int32) followed by store16 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e225b39cd4cdf3b62d5395ab3a6753a8503dbff7;p=llvm [PPC] Fix code generation for bswap(int32) followed by store16 This patch fixes pr32063. Current code in PPCTargetLowering::PerformDAGCombine can transform bswap store into a single PPCISD::STBRX instruction. but it doesn't consider the case that the operand size of bswap may be larger than store size. When it occurs, we need 2 modifications, 1 For the last operand of PPCISD::STBRX, we should not use DAG.getValueType(N->getOperand(1).getValueType()), instead we should use cast(N)->getMemoryVT(). 2 Before PPCISD::STBRX, we need to shift the original operand of bswap to the right side. Differential Revision: https://reviews.llvm.org/D30362 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@296811 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index 07f4d839620..f532d48a701 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -11391,9 +11391,17 @@ SDValue PPCTargetLowering::PerformDAGCombine(SDNode *N, if (BSwapOp.getValueType() == MVT::i16) BSwapOp = DAG.getNode(ISD::ANY_EXTEND, dl, MVT::i32, BSwapOp); + // If the type of BSWAP operand is wider than stored memory width + // it need to be shifted to the right side before STBRX. + EVT mVT = cast(N)->getMemoryVT(); + if (Op1VT.bitsGT(mVT)) { + int shift = Op1VT.getSizeInBits() - mVT.getSizeInBits(); + BSwapOp = DAG.getNode(ISD::SRL, dl, Op1VT, BSwapOp, + DAG.getConstant(shift, dl, MVT::i32)); + } + SDValue Ops[] = { - N->getOperand(0), BSwapOp, N->getOperand(2), - DAG.getValueType(N->getOperand(1).getValueType()) + N->getOperand(0), BSwapOp, N->getOperand(2), DAG.getValueType(mVT) }; return DAG.getMemIntrinsicNode(PPCISD::STBRX, dl, DAG.getVTList(MVT::Other), diff --git a/test/CodeGen/PowerPC/pr32063.ll b/test/CodeGen/PowerPC/pr32063.ll new file mode 100644 index 00000000000..f031ec83c55 --- /dev/null +++ b/test/CodeGen/PowerPC/pr32063.ll @@ -0,0 +1,16 @@ +; RUN: llc -O2 < %s | FileCheck %s +target triple = "powerpc64le-linux-gnu" + +define void @foo(i32 %v, i16* %p) { + %1 = and i32 %v, -65536 + %2 = tail call i32 @llvm.bswap.i32(i32 %1) + %conv = trunc i32 %2 to i16 + store i16 %conv, i16* %p + ret void + +; CHECK: srwi +; CHECK: sthbrx +; CHECK-NOT: stwbrx +} + +declare i32 @llvm.bswap.i32(i32)