diff options
author | Artur Pilipenko <apilipenko@azulsystems.com> | 2017-02-09 12:06:01 +0000 |
---|---|---|
committer | Artur Pilipenko <apilipenko@azulsystems.com> | 2017-02-09 12:06:01 +0000 |
commit | 4a64031954b61e2f8a68f762bb3854d983dc5bb3 (patch) | |
tree | 5c9da5e287bc552a44f41e5b475e2e81eb16af6f /llvm/lib/CodeGen | |
parent | 563e23e66e5fd383147f5e0d9b4fa67f265a422a (diff) | |
download | bcm5719-llvm-4a64031954b61e2f8a68f762bb3854d983dc5bb3.tar.gz bcm5719-llvm-4a64031954b61e2f8a68f762bb3854d983dc5bb3.zip |
[DAGCombiner] Support non-zero offset in load combine
Enable folding patterns which load the value from non-zero offset:
i8 *a = ...
i32 val = a[4] | (a[5] << 8) | (a[6] << 16) | (a[7] << 24)
=>
i32 val = *((i32*)(a+4))
Reviewed By: RKSimon
Differential Revision: https://reviews.llvm.org/D29394
llvm-svn: 294582
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 11 |
1 files changed, 8 insertions, 3 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index e3c15b77a26..3a71a5ddb0e 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -4533,6 +4533,7 @@ SDValue DAGCombiner::MatchLoadCombine(SDNode *N) { SmallSet<LoadSDNode *, 8> Loads; LoadSDNode *FirstLoad = nullptr; + int64_t FirstOffset = INT64_MAX; bool IsBigEndianTarget = DAG.getDataLayout().isBigEndian(); auto ByteAt = IsBigEndianTarget ? BigEndianByteAt : LittleEndianByteAt; @@ -4575,21 +4576,25 @@ SDValue DAGCombiner::MatchLoadCombine(SDNode *N) { ByteOffsets[i] = ByteOffsetFromBase; // Remember the first byte load - if (ByteOffsetFromBase == 0) + if (ByteOffsetFromBase < FirstOffset) { FirstLoad = L; + FirstOffset = ByteOffsetFromBase; + } Loads.insert(L); } assert(Loads.size() > 0 && "All the bytes of the value must be loaded from " "memory, so there must be at least one load which produces the value"); assert(Base && "Base address of the accessed memory location must be set"); + assert(FirstOffset != INT64_MAX && "First byte offset must be set"); // Check if the bytes of the OR we are looking at match with either big or // little endian value load bool BigEndian = true, LittleEndian = true; for (unsigned i = 0; i < ByteWidth; i++) { - LittleEndian &= ByteOffsets[i] == LittleEndianByteAt(ByteWidth, i); - BigEndian &= ByteOffsets[i] == BigEndianByteAt(ByteWidth, i); + int64_t CurrentByteOffset = ByteOffsets[i] - FirstOffset; + LittleEndian &= CurrentByteOffset == LittleEndianByteAt(ByteWidth, i); + BigEndian &= CurrentByteOffset == BigEndianByteAt(ByteWidth, i); if (!BigEndian && !LittleEndian) return SDValue(); } |