Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions llvm/docs/LangRef.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3888,7 +3888,7 @@ integer to memory.

A bitcast from a vector type to a scalar integer type will see the elements
being packed together (without padding). The order in which elements are
inserted in the integer depends on endianess. For little endian element zero
inserted in the integer depends on endianness. For little endian element zero
is put in the least significant bits of the integer, and for big endian
element zero is put in the most significant bits.

Expand Down Expand Up @@ -11677,7 +11677,7 @@ To convert pointers to other types, use the :ref:`inttoptr <i_inttoptr>`
or :ref:`ptrtoint <i_ptrtoint>` instructions first.

There is a caveat for bitcasts involving vector types in relation to
endianess. For example ``bitcast <2 x i8> <value> to i16`` puts element zero
endianness. For example ``bitcast <2 x i8> <value> to i16`` puts element zero
of the vector in the least significant bits of the i16 for little-endian while
element zero ends up in the most significant bits for big-endian.

Expand All @@ -11686,9 +11686,9 @@ Example:

.. code-block:: text

%X = bitcast i8 255 to i8 ; yields i8 :-1
%Y = bitcast i32* %x to i16* ; yields i16*:%x
%Z = bitcast <2 x i32> %V to i64; ; yields i64: %V (depends on endianess)
%X = bitcast i8 255 to i8 ; yields i8 :-1
%Y = bitcast i32* %x to i16* ; yields i16*:%x
%Z = bitcast <2 x i32> %V to i64; ; yields i64: %V (depends on endianness)
%Z = bitcast <2 x i32*> %V to <2 x i64*> ; yields <2 x i64*>

.. _i_addrspacecast:
Expand Down
37 changes: 17 additions & 20 deletions llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7076,12 +7076,23 @@ SDValue DAGCombiner::visitAND(SDNode *N) {
N1, /*AllowUndef=*/false, /*AllowTruncation=*/true)) {
Constant = C->getAPIntValue();
} else if (BuildVectorSDNode *Vector = dyn_cast<BuildVectorSDNode>(N1)) {
unsigned EltBitWidth = Vector->getValueType(0).getScalarSizeInBits();
APInt SplatValue, SplatUndef;
unsigned SplatBitSize;
bool HasAnyUndefs;
bool IsSplat = Vector->isConstantSplat(SplatValue, SplatUndef,
SplatBitSize, HasAnyUndefs);
if (IsSplat) {
// Endianness should not matter here. Code below makes sure that we only
// use the result if the SplatBitSize is a multiple of the vector element
// size. And after that we AND all element sized parts of the splat
// together. So the end result should be the same regardless of in which
// order we do those operations.
const bool IsBigEndian = false;
bool IsSplat =
Vector->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
HasAnyUndefs, EltBitWidth, IsBigEndian);

// Make sure that variable 'Constant' is only set if 'SplatBitSize' is a
// multiple of 'BitWidth'. Otherwise, we could propagate a wrong value.
if (IsSplat && (SplatBitSize % EltBitWidth) == 0) {
// Undef bits can contribute to a possible optimisation if set, so
// set them.
SplatValue |= SplatUndef;
Expand All @@ -7090,23 +7101,9 @@ SDValue DAGCombiner::visitAND(SDNode *N) {
// the first vector value and FF for the rest, repeating. We need a mask
// that will apply equally to all members of the vector, so AND all the
// lanes of the constant together.
unsigned EltBitWidth = Vector->getValueType(0).getScalarSizeInBits();

// If the splat value has been compressed to a bitlength lower
// than the size of the vector lane, we need to re-expand it to
// the lane size.
if (EltBitWidth > SplatBitSize)
for (SplatValue = SplatValue.zextOrTrunc(EltBitWidth);
SplatBitSize < EltBitWidth; SplatBitSize = SplatBitSize * 2)
SplatValue |= SplatValue.shl(SplatBitSize);

// Make sure that variable 'Constant' is only set if 'SplatBitSize' is a
// multiple of 'BitWidth'. Otherwise, we could propagate a wrong value.
if ((SplatBitSize % EltBitWidth) == 0) {
Constant = APInt::getAllOnes(EltBitWidth);
for (unsigned i = 0, n = (SplatBitSize / EltBitWidth); i < n; ++i)
Constant &= SplatValue.extractBits(EltBitWidth, i * EltBitWidth);
}
Constant = APInt::getAllOnes(EltBitWidth);
for (unsigned i = 0, n = (SplatBitSize / EltBitWidth); i < n; ++i)
Constant &= SplatValue.extractBits(EltBitWidth, i * EltBitWidth);
}
}

Expand Down
17 changes: 16 additions & 1 deletion llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,13 @@ bool ISD::isConstantSplatVector(const SDNode *N, APInt &SplatVal) {
unsigned SplatBitSize;
bool HasUndefs;
unsigned EltSize = N->getValueType(0).getVectorElementType().getSizeInBits();
// Endianness does not matter here. We are checking for a splat given the
// element size of the vector, and if we find such a splat for little endian
// layout, then that should be valid also for big endian (as the full vector
// size is known to be a multiple of the element size).
const bool IsBigEndian = false;
return BV->isConstantSplat(SplatVal, SplatUndef, SplatBitSize, HasUndefs,
EltSize) &&
EltSize, IsBigEndian) &&
EltSize == SplatBitSize;
}

Expand Down Expand Up @@ -12357,6 +12362,10 @@ bool BuildVectorSDNode::isConstantSplat(APInt &SplatValue, APInt &SplatUndef,

// FIXME: This does not work for vectors with elements less than 8 bits.
while (VecWidth > 8) {
// If we can't split in half, stop here.
if (VecWidth & 1)
break;

unsigned HalfSize = VecWidth / 2;
APInt HighValue = SplatValue.extractBits(HalfSize, HalfSize);
APInt LowValue = SplatValue.extractBits(HalfSize, 0);
Expand All @@ -12374,6 +12383,12 @@ bool BuildVectorSDNode::isConstantSplat(APInt &SplatValue, APInt &SplatUndef,
VecWidth = HalfSize;
}

// FIXME: The loop above only tries to split in halves. But if the input
// vector for example is <3 x i16> it wouldn't be able to detect a
// SplatBitSize of 16. No idea if that is a design flaw currently limiting
// optimizations. I guess that back in the days when this helper was created
// vectors normally was power-of-2 sized.

SplatBitSize = VecWidth;
return true;
}
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2576,6 +2576,8 @@ performVectorTruncZeroCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI) {
APInt SplatValue, SplatUndef;
unsigned SplatBitSize;
bool HasAnyUndefs;
// Endianness doesn't matter in this context because we are looking for
// an all-zero value.
return Splat &&
Splat->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
HasAnyUndefs) &&
Expand Down