diff options
author | Simon Pilgrim <llvm-dev@redking.me.uk> | 2018-08-20 13:05:48 +0000 |
---|---|---|
committer | Simon Pilgrim <llvm-dev@redking.me.uk> | 2018-08-20 13:05:48 +0000 |
commit | 5b78c9d58d9043db6a9c4ca489a40486375776d8 (patch) | |
tree | 8fd9a0d0f7a48d5c270bcd17000f12cc09ee9988 /llvm/lib/CodeGen | |
parent | d882a497420c68d0795f7e18edccf5cef0bf2b64 (diff) | |
download | bcm5719-llvm-5b78c9d58d9043db6a9c4ca489a40486375776d8.tar.gz bcm5719-llvm-5b78c9d58d9043db6a9c4ca489a40486375776d8.zip |
[SelectionDAG] Add partial sign-bit support to ComputeNumSignBits for BITCAST nodes
Only adds support to the existing 'large element' scalar/vector to 'small element' vector bitcasts.
Handle the case where the sign bit extends to only part of the small elements.
llvm-svn: 340169
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 7b28a06d953..c40fda3a20b 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -3240,9 +3240,9 @@ unsigned SelectionDAG::ComputeNumSignBits(SDValue Op, const APInt &DemandedElts, if (VTBits == SrcBits) return ComputeNumSignBits(N0, DemandedElts, Depth + 1); + bool IsLE = getDataLayout().isLittleEndian(); + // Bitcast 'large element' scalar/vector to 'small element' vector. - // TODO: Handle cases other than 'sign splat' when we have a use case. - // Requires handling of DemandedElts and Endianness. if ((SrcBits % VTBits) == 0) { assert(Op.getValueType().isVector() && "Expected bitcast to vector"); @@ -3252,9 +3252,23 @@ unsigned SelectionDAG::ComputeNumSignBits(SDValue Op, const APInt &DemandedElts, if (DemandedElts[i]) SrcDemandedElts.setBit(i / Scale); + // Fast case - sign splat can be simply split across the small elements. Tmp = ComputeNumSignBits(N0, SrcDemandedElts, Depth + 1); if (Tmp == SrcBits) return VTBits; + + // Slow case - determine how far the sign extends into each sub-element. + Tmp2 = VTBits; + for (unsigned i = 0; i != NumElts; ++i) + if (DemandedElts[i]) { + unsigned SubOffset = i % Scale; + SubOffset = (IsLE ? ((Scale - 1) - SubOffset) : SubOffset); + SubOffset = SubOffset * VTBits; + if (Tmp <= SubOffset) + return 1; + Tmp2 = std::min(Tmp2, Tmp - SubOffset); + } + return Tmp2; } break; } |