Skip to content

Commit

Permalink
[NFC] Add a static function to do the endian check
Browse files Browse the repository at this point in the history
Add a new function to do the endian check, as I will commit another patch later, which will also need the endian check. 

Differential Revision: https://reviews.llvm.org/D61236

llvm-svn: 360226
  • Loading branch information
QingShan Zhang authored and MrSidims committed May 24, 2019
1 parent e0b93c9 commit 4216e9d
Showing 1 changed file with 37 additions and 15 deletions.
52 changes: 37 additions & 15 deletions llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
Expand Up @@ -6120,6 +6120,38 @@ calculateByteProvider(SDValue Op, unsigned Index, unsigned Depth,
return None;
}

static unsigned LittleEndianByteAt(unsigned BW, unsigned i) {
return i;
}

static unsigned BigEndianByteAt(unsigned BW, unsigned i) {
return BW - i - 1;
}

// Check if the bytes offsets we are looking at match with either big or
// little endian value loaded. Return true for big endian, false for little
// endian, and None if match failed.
static Optional<bool> isBigEndian(const SmallVector<int64_t, 4> &ByteOffsets,
int64_t FirstOffset) {
// The endian can be decided only when it is 2 bytes at least.
unsigned Width = ByteOffsets.size();
if (Width < 2)
return None;

bool BigEndian = true, LittleEndian = true;
for (unsigned i = 0; i < Width; i++) {
int64_t CurrentByteOffset = ByteOffsets[i] - FirstOffset;
LittleEndian &= CurrentByteOffset == LittleEndianByteAt(Width, i);
BigEndian &= CurrentByteOffset == BigEndianByteAt(Width, i);
if (!BigEndian && !LittleEndian)
return None;
}

assert((BigEndian != LittleEndian) && "It should be either big endian or"
"little endian");
return BigEndian;
}

/// Match a pattern where a wide type scalar value is loaded by several narrow
/// loads and combined by shifts and ors. Fold it into a single load or a load
/// and a BSWAP if the targets supports it.
Expand Down Expand Up @@ -6167,11 +6199,6 @@ SDValue DAGCombiner::MatchLoadCombine(SDNode *N) {
if (LegalOperations && !TLI.isOperationLegal(ISD::LOAD, VT))
return SDValue();

std::function<unsigned(unsigned, unsigned)> LittleEndianByteAt = [](
unsigned BW, unsigned i) { return i; };
std::function<unsigned(unsigned, unsigned)> BigEndianByteAt = [](
unsigned BW, unsigned i) { return BW - i - 1; };

bool IsBigEndianTarget = DAG.getDataLayout().isBigEndian();
auto MemoryByteOffset = [&] (ByteProvider P) {
assert(P.isMemory() && "Must be a memory byte provider");
Expand Down Expand Up @@ -6238,15 +6265,10 @@ SDValue DAGCombiner::MatchLoadCombine(SDNode *N) {

// 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++) {
int64_t CurrentByteOffset = ByteOffsets[i] - FirstOffset;
LittleEndian &= CurrentByteOffset == LittleEndianByteAt(ByteWidth, i);
BigEndian &= CurrentByteOffset == BigEndianByteAt(ByteWidth, i);
if (!BigEndian && !LittleEndian)
return SDValue();
}
assert((BigEndian != LittleEndian) && "should be either or");
Optional<bool> IsBigEndian = isBigEndian(ByteOffsets, FirstOffset);
if (!IsBigEndian.hasValue())
return SDValue();

assert(FirstByteProvider && "must be set");

// Ensure that the first byte is loaded from zero offset of the first load.
Expand All @@ -6259,7 +6281,7 @@ SDValue DAGCombiner::MatchLoadCombine(SDNode *N) {
// replace it with a single load and bswap if needed.

// If the load needs byte swap check if the target supports it
bool NeedsBswap = IsBigEndianTarget != BigEndian;
bool NeedsBswap = IsBigEndianTarget != *IsBigEndian;

// Before legalize we can introduce illegal bswaps which will be later
// converted to an explicit bswap sequence. This way we end up with a single
Expand Down

0 comments on commit 4216e9d

Please sign in to comment.