mirror of
https://github.com/RPCS3/llvm.git
synced 2024-11-29 06:30:30 +00:00
Change instcombine's getShuffleMask to represent undef with negative values.
This code had previously used 2*N, where N is the mask length, to represent undef. That is not safe because the shufflevector operands may have more than N elements -- they don't have to match the result type. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@117721 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
46455096be
commit
822cb58d08
@ -53,22 +53,20 @@ static bool CheapToScalarize(Value *V, bool isConstant) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read and decode a shufflevector mask.
|
/// getShuffleMask - Read and decode a shufflevector mask.
|
||||||
///
|
/// Turn undef elements into negative values.
|
||||||
/// It turns undef elements into values that are larger than the number of
|
static std::vector<int> getShuffleMask(const ShuffleVectorInst *SVI) {
|
||||||
/// elements in the input.
|
|
||||||
static std::vector<unsigned> getShuffleMask(const ShuffleVectorInst *SVI) {
|
|
||||||
unsigned NElts = SVI->getType()->getNumElements();
|
unsigned NElts = SVI->getType()->getNumElements();
|
||||||
if (isa<ConstantAggregateZero>(SVI->getOperand(2)))
|
if (isa<ConstantAggregateZero>(SVI->getOperand(2)))
|
||||||
return std::vector<unsigned>(NElts, 0);
|
return std::vector<int>(NElts, 0);
|
||||||
if (isa<UndefValue>(SVI->getOperand(2)))
|
if (isa<UndefValue>(SVI->getOperand(2)))
|
||||||
return std::vector<unsigned>(NElts, 2*NElts);
|
return std::vector<int>(NElts, -1);
|
||||||
|
|
||||||
std::vector<unsigned> Result;
|
std::vector<int> Result;
|
||||||
const ConstantVector *CP = cast<ConstantVector>(SVI->getOperand(2));
|
const ConstantVector *CP = cast<ConstantVector>(SVI->getOperand(2));
|
||||||
for (User::const_op_iterator i = CP->op_begin(), e = CP->op_end(); i!=e; ++i)
|
for (User::const_op_iterator i = CP->op_begin(), e = CP->op_end(); i!=e; ++i)
|
||||||
if (isa<UndefValue>(*i))
|
if (isa<UndefValue>(*i))
|
||||||
Result.push_back(NElts*2); // undef -> 8
|
Result.push_back(-1); // undef
|
||||||
else
|
else
|
||||||
Result.push_back(cast<ConstantInt>(*i)->getZExtValue());
|
Result.push_back(cast<ConstantInt>(*i)->getZExtValue());
|
||||||
return Result;
|
return Result;
|
||||||
@ -109,14 +107,13 @@ static Value *FindScalarElement(Value *V, unsigned EltNo) {
|
|||||||
|
|
||||||
if (ShuffleVectorInst *SVI = dyn_cast<ShuffleVectorInst>(V)) {
|
if (ShuffleVectorInst *SVI = dyn_cast<ShuffleVectorInst>(V)) {
|
||||||
unsigned LHSWidth =
|
unsigned LHSWidth =
|
||||||
cast<VectorType>(SVI->getOperand(0)->getType())->getNumElements();
|
cast<VectorType>(SVI->getOperand(0)->getType())->getNumElements();
|
||||||
unsigned InEl = getShuffleMask(SVI)[EltNo];
|
int InEl = getShuffleMask(SVI)[EltNo];
|
||||||
if (InEl < LHSWidth)
|
if (InEl < 0)
|
||||||
return FindScalarElement(SVI->getOperand(0), InEl);
|
|
||||||
else if (InEl < LHSWidth*2)
|
|
||||||
return FindScalarElement(SVI->getOperand(1), InEl - LHSWidth);
|
|
||||||
else
|
|
||||||
return UndefValue::get(PTy->getElementType());
|
return UndefValue::get(PTy->getElementType());
|
||||||
|
if (InEl < (int)LHSWidth)
|
||||||
|
return FindScalarElement(SVI->getOperand(0), InEl);
|
||||||
|
return FindScalarElement(SVI->getOperand(1), InEl - LHSWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, we don't know.
|
// Otherwise, we don't know.
|
||||||
@ -215,18 +212,18 @@ Instruction *InstCombiner::visitExtractElementInst(ExtractElementInst &EI) {
|
|||||||
// If this is extracting an element from a shufflevector, figure out where
|
// If this is extracting an element from a shufflevector, figure out where
|
||||||
// it came from and extract from the appropriate input element instead.
|
// it came from and extract from the appropriate input element instead.
|
||||||
if (ConstantInt *Elt = dyn_cast<ConstantInt>(EI.getOperand(1))) {
|
if (ConstantInt *Elt = dyn_cast<ConstantInt>(EI.getOperand(1))) {
|
||||||
unsigned SrcIdx = getShuffleMask(SVI)[Elt->getZExtValue()];
|
int SrcIdx = getShuffleMask(SVI)[Elt->getZExtValue()];
|
||||||
Value *Src;
|
Value *Src;
|
||||||
unsigned LHSWidth =
|
unsigned LHSWidth =
|
||||||
cast<VectorType>(SVI->getOperand(0)->getType())->getNumElements();
|
cast<VectorType>(SVI->getOperand(0)->getType())->getNumElements();
|
||||||
|
|
||||||
if (SrcIdx < LHSWidth)
|
if (SrcIdx < 0)
|
||||||
|
return ReplaceInstUsesWith(EI, UndefValue::get(EI.getType()));
|
||||||
|
if (SrcIdx < (int)LHSWidth)
|
||||||
Src = SVI->getOperand(0);
|
Src = SVI->getOperand(0);
|
||||||
else if (SrcIdx < LHSWidth*2) {
|
else {
|
||||||
SrcIdx -= LHSWidth;
|
SrcIdx -= LHSWidth;
|
||||||
Src = SVI->getOperand(1);
|
Src = SVI->getOperand(1);
|
||||||
} else {
|
|
||||||
return ReplaceInstUsesWith(EI, UndefValue::get(EI.getType()));
|
|
||||||
}
|
}
|
||||||
return ExtractElementInst::Create(Src,
|
return ExtractElementInst::Create(Src,
|
||||||
ConstantInt::get(Type::getInt32Ty(EI.getContext()),
|
ConstantInt::get(Type::getInt32Ty(EI.getContext()),
|
||||||
@ -440,7 +437,7 @@ Instruction *InstCombiner::visitInsertElementInst(InsertElementInst &IE) {
|
|||||||
Instruction *InstCombiner::visitShuffleVectorInst(ShuffleVectorInst &SVI) {
|
Instruction *InstCombiner::visitShuffleVectorInst(ShuffleVectorInst &SVI) {
|
||||||
Value *LHS = SVI.getOperand(0);
|
Value *LHS = SVI.getOperand(0);
|
||||||
Value *RHS = SVI.getOperand(1);
|
Value *RHS = SVI.getOperand(1);
|
||||||
std::vector<unsigned> Mask = getShuffleMask(&SVI);
|
std::vector<int> Mask = getShuffleMask(&SVI);
|
||||||
|
|
||||||
bool MadeChange = false;
|
bool MadeChange = false;
|
||||||
|
|
||||||
@ -472,12 +469,12 @@ Instruction *InstCombiner::visitShuffleVectorInst(ShuffleVectorInst &SVI) {
|
|||||||
// Remap any references to RHS to use LHS.
|
// Remap any references to RHS to use LHS.
|
||||||
std::vector<Constant*> Elts;
|
std::vector<Constant*> Elts;
|
||||||
for (unsigned i = 0, e = Mask.size(); i != e; ++i) {
|
for (unsigned i = 0, e = Mask.size(); i != e; ++i) {
|
||||||
if (Mask[i] >= 2*e)
|
if (Mask[i] < 0)
|
||||||
Elts.push_back(UndefValue::get(Type::getInt32Ty(SVI.getContext())));
|
Elts.push_back(UndefValue::get(Type::getInt32Ty(SVI.getContext())));
|
||||||
else {
|
else {
|
||||||
if ((Mask[i] >= e && isa<UndefValue>(RHS)) ||
|
if ((Mask[i] >= (int)e && isa<UndefValue>(RHS)) ||
|
||||||
(Mask[i] < e && isa<UndefValue>(LHS))) {
|
(Mask[i] < (int)e && isa<UndefValue>(LHS))) {
|
||||||
Mask[i] = 2*e; // Turn into undef.
|
Mask[i] = -1; // Turn into undef.
|
||||||
Elts.push_back(UndefValue::get(Type::getInt32Ty(SVI.getContext())));
|
Elts.push_back(UndefValue::get(Type::getInt32Ty(SVI.getContext())));
|
||||||
} else {
|
} else {
|
||||||
Mask[i] = Mask[i] % e; // Force to LHS.
|
Mask[i] = Mask[i] % e; // Force to LHS.
|
||||||
@ -498,9 +495,9 @@ Instruction *InstCombiner::visitShuffleVectorInst(ShuffleVectorInst &SVI) {
|
|||||||
bool isLHSID = true, isRHSID = true;
|
bool isLHSID = true, isRHSID = true;
|
||||||
|
|
||||||
for (unsigned i = 0, e = Mask.size(); i != e; ++i) {
|
for (unsigned i = 0, e = Mask.size(); i != e; ++i) {
|
||||||
if (Mask[i] >= e*2) continue; // Ignore undef values.
|
if (Mask[i] < 0) continue; // Ignore undef values.
|
||||||
// Is this an identity shuffle of the LHS value?
|
// Is this an identity shuffle of the LHS value?
|
||||||
isLHSID &= (Mask[i] == i);
|
isLHSID &= (Mask[i] == (int)i);
|
||||||
|
|
||||||
// Is this an identity shuffle of the RHS value?
|
// Is this an identity shuffle of the RHS value?
|
||||||
isRHSID &= (Mask[i]-e == i);
|
isRHSID &= (Mask[i]-e == i);
|
||||||
@ -521,19 +518,21 @@ Instruction *InstCombiner::visitShuffleVectorInst(ShuffleVectorInst &SVI) {
|
|||||||
// turning: (splat(splat)) -> splat.
|
// turning: (splat(splat)) -> splat.
|
||||||
if (ShuffleVectorInst *LHSSVI = dyn_cast<ShuffleVectorInst>(LHS)) {
|
if (ShuffleVectorInst *LHSSVI = dyn_cast<ShuffleVectorInst>(LHS)) {
|
||||||
if (isa<UndefValue>(RHS)) {
|
if (isa<UndefValue>(RHS)) {
|
||||||
std::vector<unsigned> LHSMask = getShuffleMask(LHSSVI);
|
std::vector<int> LHSMask = getShuffleMask(LHSSVI);
|
||||||
|
|
||||||
if (LHSMask.size() == Mask.size()) {
|
if (LHSMask.size() == Mask.size()) {
|
||||||
std::vector<unsigned> NewMask;
|
std::vector<int> NewMask;
|
||||||
bool isSplat = true;
|
bool isSplat = true;
|
||||||
unsigned SplatElt = 2 * Mask.size(); // undef
|
int SplatElt = -1; // undef
|
||||||
for (unsigned i = 0, e = Mask.size(); i != e; ++i) {
|
for (unsigned i = 0, e = Mask.size(); i != e; ++i) {
|
||||||
unsigned MaskElt = 2 * e; // undef
|
int MaskElt;
|
||||||
if (Mask[i] < e)
|
if (Mask[i] < 0 || Mask[i] >= (int)e)
|
||||||
|
MaskElt = -1; // undef
|
||||||
|
else
|
||||||
MaskElt = LHSMask[Mask[i]];
|
MaskElt = LHSMask[Mask[i]];
|
||||||
// Check if this could still be a splat.
|
// Check if this could still be a splat.
|
||||||
if (MaskElt < 2*e) {
|
if (MaskElt >= 0) {
|
||||||
if (SplatElt < 2*e && SplatElt != MaskElt)
|
if (SplatElt >=0 && SplatElt != MaskElt)
|
||||||
isSplat = false;
|
isSplat = false;
|
||||||
SplatElt = MaskElt;
|
SplatElt = MaskElt;
|
||||||
}
|
}
|
||||||
@ -543,13 +542,10 @@ Instruction *InstCombiner::visitShuffleVectorInst(ShuffleVectorInst &SVI) {
|
|||||||
// If the result mask is equal to the src shuffle or this
|
// If the result mask is equal to the src shuffle or this
|
||||||
// shuffle mask, do the replacement.
|
// shuffle mask, do the replacement.
|
||||||
if (isSplat || NewMask == LHSMask || NewMask == Mask) {
|
if (isSplat || NewMask == LHSMask || NewMask == Mask) {
|
||||||
unsigned LHSInNElts =
|
|
||||||
cast<VectorType>(LHSSVI->getOperand(0)->getType())->
|
|
||||||
getNumElements();
|
|
||||||
std::vector<Constant*> Elts;
|
std::vector<Constant*> Elts;
|
||||||
const Type *Int32Ty = Type::getInt32Ty(SVI.getContext());
|
const Type *Int32Ty = Type::getInt32Ty(SVI.getContext());
|
||||||
for (unsigned i = 0, e = NewMask.size(); i != e; ++i) {
|
for (unsigned i = 0, e = NewMask.size(); i != e; ++i) {
|
||||||
if (NewMask[i] >= LHSInNElts*2) {
|
if (NewMask[i] < 0) {
|
||||||
Elts.push_back(UndefValue::get(Int32Ty));
|
Elts.push_back(UndefValue::get(Int32Ty));
|
||||||
} else {
|
} else {
|
||||||
Elts.push_back(ConstantInt::get(Int32Ty, NewMask[i]));
|
Elts.push_back(ConstantInt::get(Int32Ty, NewMask[i]));
|
||||||
|
@ -88,6 +88,19 @@ define <4 x i8> @test9(<16 x i8> %tmp6) nounwind {
|
|||||||
ret <4 x i8> %tmp9
|
ret <4 x i8> %tmp9
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; Same as test9, but make sure that "undef" mask values are not confused with
|
||||||
|
; mask values of 2*N, where N is the mask length. These shuffles should not
|
||||||
|
; be folded (because [8,9,4,8] may not be a mask supported by the target).
|
||||||
|
define <4 x i8> @test9a(<16 x i8> %tmp6) nounwind {
|
||||||
|
; CHECK: @test9a
|
||||||
|
; CHECK-NEXT: shufflevector
|
||||||
|
; CHECK-NEXT: shufflevector
|
||||||
|
; CHECK-NEXT: ret
|
||||||
|
%tmp7 = shufflevector <16 x i8> %tmp6, <16 x i8> undef, <4 x i32> < i32 undef, i32 9, i32 4, i32 8 > ; <<4 x i8>> [#uses=1]
|
||||||
|
%tmp9 = shufflevector <4 x i8> %tmp7, <4 x i8> undef, <4 x i32> < i32 3, i32 1, i32 2, i32 0 > ; <<4 x i8>> [#uses=1]
|
||||||
|
ret <4 x i8> %tmp9
|
||||||
|
}
|
||||||
|
|
||||||
; Redundant vector splats should be removed. Radar 8597790.
|
; Redundant vector splats should be removed. Radar 8597790.
|
||||||
define <4 x i32> @test10(<4 x i32> %tmp5) nounwind {
|
define <4 x i32> @test10(<4 x i32> %tmp5) nounwind {
|
||||||
; CHECK: @test10
|
; CHECK: @test10
|
||||||
|
Loading…
Reference in New Issue
Block a user