From b3f19ed18bf7e9edae49b04313d463ce46a8ba0a Mon Sep 17 00:00:00 2001 From: Tom Stellard Date: Mon, 19 Mar 2018 23:55:28 +0000 Subject: [PATCH] Backport r296811, r297001, and r327651 from trunk. rhbz#1554349 --- ...eration-for-bswap-int32-followed-by-.patch | 77 +++++++++++++ ...ure-with-STBRX-when-store-is-narrowe.patch | 107 ++++++++++++++++++ ...non-simple-MVT-in-STBRX-optimization.patch | 69 +++++++++++ llvm.spec | 8 +- 4 files changed, 260 insertions(+), 1 deletion(-) create mode 100644 0001-PPC-Fix-code-generation-for-bswap-int32-followed-by-.patch create mode 100644 0002-PowerPC-Fix-failure-with-STBRX-when-store-is-narrowe.patch create mode 100644 0003-PPC-Avoid-non-simple-MVT-in-STBRX-optimization.patch diff --git a/0001-PPC-Fix-code-generation-for-bswap-int32-followed-by-.patch b/0001-PPC-Fix-code-generation-for-bswap-int32-followed-by-.patch new file mode 100644 index 0000000..ac5fbf9 --- /dev/null +++ b/0001-PPC-Fix-code-generation-for-bswap-int32-followed-by-.patch @@ -0,0 +1,77 @@ +From 66e43b0a8e5616a4762eedee9bd030a49b9d6545 Mon Sep 17 00:00:00 2001 +From: Guozhi Wei +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(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(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 + diff --git a/0002-PowerPC-Fix-failure-with-STBRX-when-store-is-narrowe.patch b/0002-PowerPC-Fix-failure-with-STBRX-when-store-is-narrowe.patch new file mode 100644 index 0000000..f5bc6e3 --- /dev/null +++ b/0002-PowerPC-Fix-failure-with-STBRX-when-store-is-narrowe.patch @@ -0,0 +1,107 @@ +From 88e57f376eabc375cd9f374369cf9e8e4dcb90af Mon Sep 17 00:00:00 2001 +From: Nemanja Ivanovic +Date: Mon, 6 Mar 2017 07:32:13 +0000 +Subject: [PATCH 2/3] [PowerPC] Fix failure with STBRX when store is narrower + than the bswap + +Fixes a crash caused by r296811 by truncating the input of the STBRX node +when the bswap is wider than i32. + +Fixes https://bugs.llvm.org/show_bug.cgi?id=32140 + +Differential Revision: https://reviews.llvm.org/D30615 + +git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@297001 91177308-0d34-0410-b5e6-96231b3b80d8 +--- + lib/Target/PowerPC/PPCISelLowering.cpp | 7 ++-- + test/CodeGen/PowerPC/pr32140.ll | 59 ++++++++++++++++++++++++++++++++++ + 2 files changed, 64 insertions(+), 2 deletions(-) + create mode 100644 test/CodeGen/PowerPC/pr32140.ll + +diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp +index c8eb6f1..521bb32 100644 +--- a/lib/Target/PowerPC/PPCISelLowering.cpp ++++ b/lib/Target/PowerPC/PPCISelLowering.cpp +@@ -11230,9 +11230,12 @@ SDValue PPCTargetLowering::PerformDAGCombine(SDNode *N, + // 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(); ++ int Shift = Op1VT.getSizeInBits() - mVT.getSizeInBits(); + BSwapOp = DAG.getNode(ISD::SRL, dl, Op1VT, BSwapOp, +- DAG.getConstant(shift, dl, MVT::i32)); ++ DAG.getConstant(Shift, dl, MVT::i32)); ++ // Need to truncate if this is a bswap of i64 stored as i32/i16. ++ if (Op1VT == MVT::i64) ++ BSwapOp = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, BSwapOp); + } + + SDValue Ops[] = { +diff --git a/test/CodeGen/PowerPC/pr32140.ll b/test/CodeGen/PowerPC/pr32140.ll +new file mode 100644 +index 0000000..827a904 +--- /dev/null ++++ b/test/CodeGen/PowerPC/pr32140.ll +@@ -0,0 +1,59 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -mtriple=powerpc64le-linux-gnu -mcpu=pwr8 < %s | FileCheck %s ++; RUN: llc -mtriple=powerpc64-linux-gnu -mcpu=pwr8 < %s | FileCheck %s ++ ++@as = common local_unnamed_addr global i16 0, align 2 ++@bs = common local_unnamed_addr global i16 0, align 2 ++@ai = common local_unnamed_addr global i32 0, align 4 ++@bi = common local_unnamed_addr global i32 0, align 4 ++ ++define void @bswapStorei64Toi32() { ++; CHECK-LABEL: bswapStorei64Toi32: ++; CHECK: # BB#0: # %entry ++; CHECK: lwa 3, 0(3) ++; CHECK-NEXT: rldicl 3, 3, 32, 32 ++; CHECK-NEXT: stwbrx 3, 0, 4 ++; CHECK-NEXT: blr ++entry: ++ %0 = load i32, i32* @ai, align 4 ++ %conv.i = sext i32 %0 to i64 ++ %or26.i = tail call i64 @llvm.bswap.i64(i64 %conv.i) ++ %conv = trunc i64 %or26.i to i32 ++ store i32 %conv, i32* @bi, align 4 ++ ret void ++} ++ ++define void @bswapStorei32Toi16() { ++; CHECK-LABEL: bswapStorei32Toi16: ++; CHECK: # BB#0: # %entry ++; CHECK: lha 3, 0(3) ++; CHECK-NEXT: srwi 3, 3, 16 ++; CHECK-NEXT: sthbrx 3, 0, 4 ++; CHECK-NEXT: blr ++entry: ++ %0 = load i16, i16* @as, align 2 ++ %conv.i = sext i16 %0 to i32 ++ %or26.i = tail call i32 @llvm.bswap.i32(i32 %conv.i) ++ %conv = trunc i32 %or26.i to i16 ++ store i16 %conv, i16* @bs, align 2 ++ ret void ++} ++ ++define void @bswapStorei64Toi16() { ++; CHECK-LABEL: bswapStorei64Toi16: ++; CHECK: # BB#0: # %entry ++; CHECK: lha 3, 0(3) ++; CHECK-NEXT: rldicl 3, 3, 16, 48 ++; CHECK-NEXT: sthbrx 3, 0, 4 ++; CHECK-NEXT: blr ++entry: ++ %0 = load i16, i16* @as, align 2 ++ %conv.i = sext i16 %0 to i64 ++ %or26.i = tail call i64 @llvm.bswap.i64(i64 %conv.i) ++ %conv = trunc i64 %or26.i to i16 ++ store i16 %conv, i16* @bs, align 2 ++ ret void ++} ++ ++declare i32 @llvm.bswap.i32(i32) ++declare i64 @llvm.bswap.i64(i64) +-- +1.8.3.1 + diff --git a/0003-PPC-Avoid-non-simple-MVT-in-STBRX-optimization.patch b/0003-PPC-Avoid-non-simple-MVT-in-STBRX-optimization.patch new file mode 100644 index 0000000..f9662bb --- /dev/null +++ b/0003-PPC-Avoid-non-simple-MVT-in-STBRX-optimization.patch @@ -0,0 +1,69 @@ +From 8578ad1fb9aa7ebc7e6da266371b8fd58e67633f Mon Sep 17 00:00:00 2001 +From: Guozhi Wei +Date: Thu, 15 Mar 2018 17:49:12 +0000 +Subject: [PATCH 3/3] [PPC] Avoid non-simple MVT in STBRX optimization + +PR35402 triggered this case. It bswap and stores a 48bit value, current STBRX optimization transforms it into STBRX. Unfortunately 48bit is not a simple MVT, there is no PPC instruction to support it, and it can't be automatically expanded by llvm, so caused a crash. + +This patch detects the non-simple MVT and returns early. + +Differential Revision: https://reviews.llvm.org/D44500 + +git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@327651 91177308-0d34-0410-b5e6-96231b3b80d8 +--- + lib/Target/PowerPC/PPCISelLowering.cpp | 6 +++++- + test/CodeGen/PowerPC/pr35402.ll | 18 ++++++++++++++++++ + 2 files changed, 23 insertions(+), 1 deletion(-) + create mode 100644 test/CodeGen/PowerPC/pr35402.ll + +diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp +index 521bb32..3c37306 100644 +--- a/lib/Target/PowerPC/PPCISelLowering.cpp ++++ b/lib/Target/PowerPC/PPCISelLowering.cpp +@@ -11221,6 +11221,11 @@ SDValue PPCTargetLowering::PerformDAGCombine(SDNode *N, + N->getOperand(1).getValueType() == MVT::i16 || + (Subtarget.hasLDBRX() && Subtarget.isPPC64() && + N->getOperand(1).getValueType() == MVT::i64))) { ++ // STBRX can only handle simple types. ++ EVT mVT = cast(N)->getMemoryVT(); ++ if (mVT.isExtended()) ++ break; ++ + SDValue BSwapOp = N->getOperand(1).getOperand(0); + // Do an any-extend to 32-bits if this is a half-word input. + if (BSwapOp.getValueType() == MVT::i16) +@@ -11228,7 +11233,6 @@ SDValue PPCTargetLowering::PerformDAGCombine(SDNode *N, + + // 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, +diff --git a/test/CodeGen/PowerPC/pr35402.ll b/test/CodeGen/PowerPC/pr35402.ll +new file mode 100644 +index 0000000..06e6d96 +--- /dev/null ++++ b/test/CodeGen/PowerPC/pr35402.ll +@@ -0,0 +1,18 @@ ++; RUN: llc -O2 < %s | FileCheck %s ++target triple = "powerpc64le-linux-gnu" ++ ++define void @test(i8* %p, i64 %data) { ++entry: ++ %0 = tail call i64 @llvm.bswap.i64(i64 %data) ++ %ptr = bitcast i8* %p to i48* ++ %val = trunc i64 %0 to i48 ++ store i48 %val, i48* %ptr, align 1 ++ ret void ++ ++; CHECK: sth ++; CHECK: stw ++; CHECK-NOT: stdbrx ++ ++} ++ ++declare i64 @llvm.bswap.i64(i64) +-- +1.8.3.1 + diff --git a/llvm.spec b/llvm.spec index df8b4ff..085a93d 100644 --- a/llvm.spec +++ b/llvm.spec @@ -9,7 +9,7 @@ Name: llvm Version: 4.0.1 -Release: 2%{?dist} +Release: 3%{?dist} Summary: The Low Level Virtual Machine License: NCSA @@ -24,6 +24,9 @@ Patch4: 0001-Revert-Revert-CMake-Move-sphinx-detection-into-AddSp.patch Patch5: 0001-CMake-Fix-docs-llvm-man-target-when-clang-llvm-is-in.patch Patch6: 0001-CMake-Add-LLVM_UTILS_INSTALL_DIR-option.patch Patch7: 0001-DebugInfo-Fix-potential-CU-mismatch-for-SubprogramSc.patch +Patch8: 0001-PPC-Fix-code-generation-for-bswap-int32-followed-by-.patch +Patch9: 0002-PowerPC-Fix-failure-with-STBRX-when-store-is-narrowe.patch +Patch10: 0003-PPC-Avoid-non-simple-MVT-in-STBRX-optimization.patch BuildRequires: cmake BuildRequires: zlib-devel @@ -205,6 +208,9 @@ fi %{_libdir}/cmake/llvm/LLVMStaticExports.cmake %changelog +* Mon Mar 19 2018 Tom Stellard - 4.0.1-3 +- Backport r296811, r297001, and r327651 from trunk. rhbz#1554349 + * Tue Nov 21 2017 Tom Stellard - 4.0.1-2 - Backport r318289 to fix a debuginfo issue with rust.