mirror of
https://src.fedoraproject.org/rpms/llvm.git
synced 2024-11-24 17:34:47 +00:00
78 lines
2.9 KiB
Diff
78 lines
2.9 KiB
Diff
|
From 66e43b0a8e5616a4762eedee9bd030a49b9d6545 Mon Sep 17 00:00:00 2001
|
||
|
From: Guozhi Wei <carrot@google.com>
|
||
|
Date: Thu, 2 Mar 2017 21:07:59 +0000
|
||
|
Subject: [PATCH 1/3] [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<StoreSDNode>(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
|
||
|
---
|
||
|
lib/Target/PowerPC/PPCISelLowering.cpp | 12 ++++++++++--
|
||
|
test/CodeGen/PowerPC/pr32063.ll | 16 ++++++++++++++++
|
||
|
2 files changed, 26 insertions(+), 2 deletions(-)
|
||
|
create mode 100644 test/CodeGen/PowerPC/pr32063.ll
|
||
|
|
||
|
diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp
|
||
|
index 6313082..c8eb6f1 100644
|
||
|
--- a/lib/Target/PowerPC/PPCISelLowering.cpp
|
||
|
+++ b/lib/Target/PowerPC/PPCISelLowering.cpp
|
||
|
@@ -11226,9 +11226,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<StoreSDNode>(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 0000000..f031ec8
|
||
|
--- /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)
|
||
|
--
|
||
|
1.8.3.1
|
||
|
|