mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-02 08:26:29 +00:00
[ARM64]Fix a bug when lowering shuffle vector to an EXT instruction.
E.g. Mask like <-1, -1, 1, ...> will generate incorrect EXT index. llvm-svn: 207485
This commit is contained in:
parent
4af26f41d6
commit
6d66b5a2eb
@ -3981,39 +3981,34 @@ static bool isSingletonEXTMask(ArrayRef<int> M, EVT VT, unsigned &Imm) {
|
|||||||
// vector sources of the shuffle are different.
|
// vector sources of the shuffle are different.
|
||||||
static bool isEXTMask(ArrayRef<int> M, EVT VT, bool &ReverseEXT,
|
static bool isEXTMask(ArrayRef<int> M, EVT VT, bool &ReverseEXT,
|
||||||
unsigned &Imm) {
|
unsigned &Imm) {
|
||||||
|
// Look for the first non-undef element.
|
||||||
|
const int *FirstRealElt = std::find_if(M.begin(), M.end(),
|
||||||
|
[](int Elt) {return Elt >= 0;});
|
||||||
|
|
||||||
|
// Benefit form APInt to handle overflow when calculating expected element.
|
||||||
unsigned NumElts = VT.getVectorNumElements();
|
unsigned NumElts = VT.getVectorNumElements();
|
||||||
ReverseEXT = false;
|
unsigned MaskBits = APInt(32, NumElts * 2).logBase2();
|
||||||
|
APInt ExpectedElt = APInt(MaskBits, *FirstRealElt + 1);
|
||||||
|
// The following shuffle indices must be the successive elements after the
|
||||||
|
// first real element.
|
||||||
|
const int *FirstWrongElt = std::find_if(FirstRealElt + 1, M.end(),
|
||||||
|
[&](int Elt) {return Elt != ExpectedElt++ && Elt != -1;});
|
||||||
|
if (FirstWrongElt != M.end())
|
||||||
|
return false;
|
||||||
|
|
||||||
// Look for the first non-undef choice and count backwards from
|
// The index of an EXT is the first element if it is not UNDEF.
|
||||||
// that. E.g. <-1, -1, 3, ...> means that an EXT must start at 3 - 2 = 1. This
|
// Watch out for the beginning UNDEFs. The EXT index should be the expected
|
||||||
// guarantees that at least one index is correct.
|
// value of the first element.
|
||||||
const int *FirstRealElt =
|
// E.g. <-1, -1, 3, ...> is treated as <1, 2, 3, ...>.
|
||||||
std::find_if(M.begin(), M.end(), [](int Elt) { return Elt >= 0; });
|
// <-1, -1, 0, 1, ...> is treated as <IDX, IDX+1, 0, 1, ...>. IDX is
|
||||||
assert(FirstRealElt != M.end() && "Completely UNDEF shuffle? Why bother?");
|
// equal to the ExpectedElt. For this case, ExpectedElt is (NumElts*2 - 2).
|
||||||
Imm = *FirstRealElt - (FirstRealElt - M.begin());
|
Imm = (M[0] >= 0) ? static_cast<unsigned>(M[0]) : ExpectedElt.getZExtValue();
|
||||||
|
|
||||||
// If this is a VEXT shuffle, the immediate value is the index of the first
|
|
||||||
// element. The other shuffle indices must be the successive elements after
|
|
||||||
// the first one.
|
|
||||||
unsigned ExpectedElt = Imm;
|
|
||||||
for (unsigned i = 1; i < NumElts; ++i) {
|
|
||||||
// Increment the expected index. If it wraps around, it may still be
|
|
||||||
// a VEXT but the source vectors must be swapped.
|
|
||||||
ExpectedElt += 1;
|
|
||||||
if (ExpectedElt == NumElts * 2) {
|
|
||||||
ExpectedElt = 0;
|
|
||||||
ReverseEXT = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (M[i] < 0)
|
|
||||||
continue; // ignore UNDEF indices
|
|
||||||
if (ExpectedElt != static_cast<unsigned>(M[i]))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adjust the index value if the source operands will be swapped.
|
// Adjust the index value if the source operands will be swapped.
|
||||||
if (ReverseEXT)
|
if (Imm >= NumElts) {
|
||||||
|
ReverseEXT = true;
|
||||||
Imm -= NumElts;
|
Imm -= NumElts;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -65,6 +65,15 @@ define <8 x i8> @test_vextd_undef(<8 x i8>* %A, <8 x i8>* %B) nounwind {
|
|||||||
ret <8 x i8> %tmp3
|
ret <8 x i8> %tmp3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
define <8 x i8> @test_vextd_undef2(<8 x i8>* %A, <8 x i8>* %B) nounwind {
|
||||||
|
;CHECK-LABEL: test_vextd_undef2:
|
||||||
|
;CHECK: {{ext.8b.*#6}}
|
||||||
|
%tmp1 = load <8 x i8>* %A
|
||||||
|
%tmp2 = load <8 x i8>* %B
|
||||||
|
%tmp3 = shufflevector <8 x i8> %tmp1, <8 x i8> %tmp2, <8 x i32> <i32 undef, i32 undef, i32 undef, i32 undef, i32 2, i32 3, i32 4, i32 5>
|
||||||
|
ret <8 x i8> %tmp3
|
||||||
|
}
|
||||||
|
|
||||||
define <16 x i8> @test_vextRq_undef(<16 x i8>* %A, <16 x i8>* %B) nounwind {
|
define <16 x i8> @test_vextRq_undef(<16 x i8>* %A, <16 x i8>* %B) nounwind {
|
||||||
;CHECK-LABEL: test_vextRq_undef:
|
;CHECK-LABEL: test_vextRq_undef:
|
||||||
;CHECK: {{ext.16b.*#7}}
|
;CHECK: {{ext.16b.*#7}}
|
||||||
@ -74,6 +83,14 @@ define <16 x i8> @test_vextRq_undef(<16 x i8>* %A, <16 x i8>* %B) nounwind {
|
|||||||
ret <16 x i8> %tmp3
|
ret <16 x i8> %tmp3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
define <8 x i16> @test_vextRq_undef2(<8 x i16>* %A) nounwind {
|
||||||
|
;CHECK-LABEL: test_vextRq_undef2:
|
||||||
|
;CHECK: {{ext.16b.*#10}}
|
||||||
|
%tmp1 = load <8 x i16>* %A
|
||||||
|
%vext = shufflevector <8 x i16> %tmp1, <8 x i16> undef, <8 x i32> <i32 undef, i32 undef, i32 undef, i32 undef, i32 1, i32 2, i32 3, i32 4>
|
||||||
|
ret <8 x i16> %vext;
|
||||||
|
}
|
||||||
|
|
||||||
; Tests for ReconstructShuffle function. Indices have to be carefully
|
; Tests for ReconstructShuffle function. Indices have to be carefully
|
||||||
; chosen to reach lowering phase as a BUILD_VECTOR.
|
; chosen to reach lowering phase as a BUILD_VECTOR.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user