mirror of
https://github.com/RPCS3/llvm.git
synced 2025-02-05 01:56:16 +00:00
significant cleanups to code that uses insert/extractelt heavily. This builds
maximal shuffles out of them where possible. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@27717 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
407428e1ea
commit
efb47359ff
@ -137,6 +137,7 @@ namespace {
|
|||||||
Instruction *visitStoreInst(StoreInst &SI);
|
Instruction *visitStoreInst(StoreInst &SI);
|
||||||
Instruction *visitBranchInst(BranchInst &BI);
|
Instruction *visitBranchInst(BranchInst &BI);
|
||||||
Instruction *visitSwitchInst(SwitchInst &SI);
|
Instruction *visitSwitchInst(SwitchInst &SI);
|
||||||
|
Instruction *visitInsertElementInst(InsertElementInst &IE);
|
||||||
Instruction *visitExtractElementInst(ExtractElementInst &EI);
|
Instruction *visitExtractElementInst(ExtractElementInst &EI);
|
||||||
Instruction *visitShuffleVectorInst(ShuffleVectorInst &SVI);
|
Instruction *visitShuffleVectorInst(ShuffleVectorInst &SVI);
|
||||||
|
|
||||||
@ -6915,6 +6916,126 @@ Instruction *InstCombiner::visitExtractElementInst(ExtractElementInst &EI) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// CollectShuffleElements - We are building a shuffle between V and RHSVec,
|
||||||
|
/// which are both packed values with identical types. Return a shuffle mask
|
||||||
|
/// that computes V.
|
||||||
|
static Value *CollectShuffleElements(Value *V, std::vector<Constant*> &Mask,
|
||||||
|
Value *RHSVec) {
|
||||||
|
assert(isa<PackedType>(V->getType()) && V->getType() == RHSVec->getType() &&
|
||||||
|
"Invalid shuffle!");
|
||||||
|
unsigned NumElts = cast<PackedType>(V->getType())->getNumElements();
|
||||||
|
|
||||||
|
if (isa<UndefValue>(V)) {
|
||||||
|
Mask.assign(NumElts, UndefValue::get(Type::UIntTy));
|
||||||
|
return V;
|
||||||
|
} else if (isa<ConstantAggregateZero>(V)) {
|
||||||
|
Mask.assign(NumElts, ConstantUInt::get(Type::UIntTy, 0));
|
||||||
|
return V;
|
||||||
|
} else if (InsertElementInst *IEI = dyn_cast<InsertElementInst>(V)) {
|
||||||
|
// If this is an insert of an extract from some other vector, include it.
|
||||||
|
Value *VecOp = IEI->getOperand(0);
|
||||||
|
Value *ScalarOp = IEI->getOperand(1);
|
||||||
|
Value *IdxOp = IEI->getOperand(2);
|
||||||
|
|
||||||
|
if (ExtractElementInst *EI = dyn_cast<ExtractElementInst>(ScalarOp)) {
|
||||||
|
if (isa<ConstantInt>(EI->getOperand(1)) && isa<ConstantInt>(IdxOp) &&
|
||||||
|
EI->getOperand(0)->getType() == V->getType()) {
|
||||||
|
unsigned ExtractedIdx =
|
||||||
|
cast<ConstantInt>(EI->getOperand(1))->getRawValue();
|
||||||
|
unsigned InsertedIdx = cast<ConstantInt>(IdxOp)->getRawValue();
|
||||||
|
|
||||||
|
// Either the extracted from or inserted into vector must be RHSVec,
|
||||||
|
// otherwise we'd end up with a shuffle of three inputs.
|
||||||
|
if (EI->getOperand(0) == RHSVec) {
|
||||||
|
Value *V = CollectShuffleElements(VecOp, Mask, RHSVec);
|
||||||
|
Mask[InsertedIdx & (NumElts-1)] =
|
||||||
|
ConstantUInt::get(Type::UIntTy, NumElts+ExtractedIdx);
|
||||||
|
return V;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (VecOp == RHSVec) {
|
||||||
|
Value *V = CollectShuffleElements(EI->getOperand(0), Mask, RHSVec);
|
||||||
|
// Everything but the extracted element is replaced with the RHS.
|
||||||
|
for (unsigned i = 0; i != NumElts; ++i) {
|
||||||
|
if (i != InsertedIdx)
|
||||||
|
Mask[i] = ConstantUInt::get(Type::UIntTy, NumElts+i);
|
||||||
|
}
|
||||||
|
return V;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Otherwise, can't do anything fancy. Return an identity vector.
|
||||||
|
for (unsigned i = 0; i != NumElts; ++i)
|
||||||
|
Mask.push_back(ConstantUInt::get(Type::UIntTy, i));
|
||||||
|
return V;
|
||||||
|
}
|
||||||
|
|
||||||
|
Instruction *InstCombiner::visitInsertElementInst(InsertElementInst &IE) {
|
||||||
|
Value *VecOp = IE.getOperand(0);
|
||||||
|
Value *ScalarOp = IE.getOperand(1);
|
||||||
|
Value *IdxOp = IE.getOperand(2);
|
||||||
|
|
||||||
|
// If the inserted element was extracted from some other vector, and if the
|
||||||
|
// indexes are constant, try to turn this into a shufflevector operation.
|
||||||
|
if (ExtractElementInst *EI = dyn_cast<ExtractElementInst>(ScalarOp)) {
|
||||||
|
if (isa<ConstantInt>(EI->getOperand(1)) && isa<ConstantInt>(IdxOp) &&
|
||||||
|
EI->getOperand(0)->getType() == IE.getType()) {
|
||||||
|
unsigned NumVectorElts = IE.getType()->getNumElements();
|
||||||
|
unsigned ExtractedIdx=cast<ConstantInt>(EI->getOperand(1))->getRawValue();
|
||||||
|
unsigned InsertedIdx = cast<ConstantInt>(IdxOp)->getRawValue();
|
||||||
|
|
||||||
|
if (ExtractedIdx >= NumVectorElts) // Out of range extract.
|
||||||
|
return ReplaceInstUsesWith(IE, VecOp);
|
||||||
|
|
||||||
|
if (InsertedIdx >= NumVectorElts) // Out of range insert.
|
||||||
|
return ReplaceInstUsesWith(IE, UndefValue::get(IE.getType()));
|
||||||
|
|
||||||
|
// If we are extracting a value from a vector, then inserting it right
|
||||||
|
// back into the same place, just use the input vector.
|
||||||
|
if (EI->getOperand(0) == VecOp && ExtractedIdx == InsertedIdx)
|
||||||
|
return ReplaceInstUsesWith(IE, VecOp);
|
||||||
|
|
||||||
|
// We could theoretically do this for ANY input. However, doing so could
|
||||||
|
// turn chains of insertelement instructions into a chain of shufflevector
|
||||||
|
// instructions, and right now we do not merge shufflevectors. As such,
|
||||||
|
// only do this in a situation where it is clear that there is benefit.
|
||||||
|
if (isa<UndefValue>(VecOp) || isa<ConstantAggregateZero>(VecOp)) {
|
||||||
|
// Turn this into shuffle(EIOp0, VecOp, Mask). The result has all of
|
||||||
|
// the values of VecOp, except then one read from EIOp0.
|
||||||
|
// Build a new shuffle mask.
|
||||||
|
std::vector<Constant*> Mask;
|
||||||
|
if (isa<UndefValue>(VecOp))
|
||||||
|
Mask.assign(NumVectorElts, UndefValue::get(Type::UIntTy));
|
||||||
|
else {
|
||||||
|
assert(isa<ConstantAggregateZero>(VecOp) && "Unknown thing");
|
||||||
|
Mask.assign(NumVectorElts, ConstantUInt::get(Type::UIntTy,
|
||||||
|
NumVectorElts));
|
||||||
|
}
|
||||||
|
Mask[InsertedIdx] = ConstantUInt::get(Type::UIntTy, ExtractedIdx);
|
||||||
|
return new ShuffleVectorInst(EI->getOperand(0), VecOp,
|
||||||
|
ConstantPacked::get(Mask));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this insertelement isn't used by some other insertelement, turn it
|
||||||
|
// (and any insertelements it points to), into one big shuffle.
|
||||||
|
if (!IE.hasOneUse() || !isa<InsertElementInst>(IE.use_back())) {
|
||||||
|
std::vector<Constant*> Mask;
|
||||||
|
Value *InVecA = CollectShuffleElements(&IE, Mask, EI->getOperand(0));
|
||||||
|
|
||||||
|
// We now have a shuffle of InVecA, VecOp, Mask.
|
||||||
|
return new ShuffleVectorInst(InVecA, EI->getOperand(0),
|
||||||
|
ConstantPacked::get(Mask));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
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);
|
||||||
@ -6925,6 +7046,11 @@ Instruction *InstCombiner::visitShuffleVectorInst(ShuffleVectorInst &SVI) {
|
|||||||
if (isa<UndefValue>(Mask))
|
if (isa<UndefValue>(Mask))
|
||||||
return ReplaceInstUsesWith(SVI, UndefValue::get(SVI.getType()));
|
return ReplaceInstUsesWith(SVI, UndefValue::get(SVI.getType()));
|
||||||
|
|
||||||
|
// TODO: Canonicalize shuffle(undef,x) -> shuffle(x, undef).
|
||||||
|
|
||||||
|
// TODO: If we have shuffle(x, undef, mask) and any elements of mask refer to
|
||||||
|
// the undef, change them to undefs.
|
||||||
|
|
||||||
// Canonicalize shuffle(x,x) -> shuffle(x,undef)
|
// Canonicalize shuffle(x,x) -> shuffle(x,undef)
|
||||||
if (LHS == RHS) {
|
if (LHS == RHS) {
|
||||||
if (isa<UndefValue>(LHS)) {
|
if (isa<UndefValue>(LHS)) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user