add some helper methods to ShuffleVectorInst and enhance its

"isValidOperands" and "getMaskValue" methods to allow 
ConstantDataSequential.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@148998 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2012-01-25 23:49:49 +00:00
parent e8838d5c5f
commit 83694a984c
2 changed files with 70 additions and 28 deletions

View File

@ -1670,10 +1670,25 @@ public:
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
Constant *getMask() const {
return reinterpret_cast<Constant*>(getOperand(2));
}
/// getMaskValue - Return the index from the shuffle mask for the specified
/// output result. This is either -1 if the element is undef or a number less
/// than 2*numelements.
int getMaskValue(unsigned i) const;
/// getShuffleMask - Return the full mask for this instruction, where each
/// element is the element number and undef's are returned as -1.
void getShuffleMask(SmallVectorImpl<int> &Mask) const;
SmallVector<int, 16> getShuffleMask() const {
SmallVector<int, 16> Mask;
getShuffleMask(Mask);
return Mask;
}
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const ShuffleVectorInst *) { return true; }

View File

@ -1576,53 +1576,84 @@ ShuffleVectorInst::ShuffleVectorInst(Value *V1, Value *V2, Value *Mask,
bool ShuffleVectorInst::isValidOperands(const Value *V1, const Value *V2,
const Value *Mask) {
// V1 and V2 must be vectors of the same type.
if (!V1->getType()->isVectorTy() || V1->getType() != V2->getType())
return false;
// Mask must be vector of i32.
VectorType *MaskTy = dyn_cast<VectorType>(Mask->getType());
if (MaskTy == 0 || !MaskTy->getElementType()->isIntegerTy(32))
return false;
// Check to see if Mask is valid.
if (isa<UndefValue>(Mask) || isa<ConstantAggregateZero>(Mask))
return true;
if (const ConstantVector *MV = dyn_cast<ConstantVector>(Mask)) {
VectorType *VTy = cast<VectorType>(V1->getType());
unsigned V1Size = cast<VectorType>(V1->getType())->getNumElements();
for (unsigned i = 0, e = MV->getNumOperands(); i != e; ++i) {
if (ConstantInt* CI = dyn_cast<ConstantInt>(MV->getOperand(i))) {
if (CI->uge(VTy->getNumElements()*2))
if (ConstantInt *CI = dyn_cast<ConstantInt>(MV->getOperand(i))) {
if (CI->uge(V1Size*2))
return false;
} else if (!isa<UndefValue>(MV->getOperand(i))) {
return false;
}
}
} else if (!isa<UndefValue>(Mask) && !isa<ConstantAggregateZero>(Mask)) {
// The bitcode reader can create a place holder for a forward reference
// used as the shuffle mask. When this occurs, the shuffle mask will
// fall into this case and fail. To avoid this error, do this bit of
// ugliness to allow such a mask pass.
if (const ConstantExpr* CE = dyn_cast<ConstantExpr>(Mask)) {
if (CE->getOpcode() == Instruction::UserOp1)
return true;
}
return false;
return true;
}
return true;
if (const ConstantDataSequential *CDS =
dyn_cast<ConstantDataSequential>(Mask)) {
unsigned V1Size = cast<VectorType>(V1->getType())->getNumElements();
for (unsigned i = 0, e = MaskTy->getNumElements(); i != e; ++i)
if (CDS->getElementAsInteger(i) >= V1Size*2)
return false;
return true;
}
// The bitcode reader can create a place holder for a forward reference
// used as the shuffle mask. When this occurs, the shuffle mask will
// fall into this case and fail. To avoid this error, do this bit of
// ugliness to allow such a mask pass.
if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(Mask))
if (CE->getOpcode() == Instruction::UserOp1)
return true;
return false;
}
/// getMaskValue - Return the index from the shuffle mask for the specified
/// output result. This is either -1 if the element is undef or a number less
/// than 2*numelements.
int ShuffleVectorInst::getMaskValue(unsigned i) const {
const Constant *Mask = cast<Constant>(getOperand(2));
if (isa<UndefValue>(Mask)) return -1;
if (isa<ConstantAggregateZero>(Mask)) return 0;
const ConstantVector *MaskCV = cast<ConstantVector>(Mask);
assert(i < MaskCV->getNumOperands() && "Index out of range");
if (isa<UndefValue>(MaskCV->getOperand(i)))
assert(i < getType()->getNumElements() && "Index out of range");
if (ConstantDataSequential *CDS =dyn_cast<ConstantDataSequential>(getMask()))
return CDS->getElementAsInteger(i);
Constant *C = getMask()->getAggregateElement(i);
if (isa<UndefValue>(C))
return -1;
return cast<ConstantInt>(MaskCV->getOperand(i))->getZExtValue();
return cast<ConstantInt>(C)->getZExtValue();
}
/// getShuffleMask - Return the full mask for this instruction, where each
/// element is the element number and undef's are returned as -1.
void ShuffleVectorInst::getShuffleMask(SmallVectorImpl<int> &Result) const {
unsigned NumElts = getType()->getNumElements();
if (ConstantDataSequential *CDS=dyn_cast<ConstantDataSequential>(getMask())) {
for (unsigned i = 0; i != NumElts; ++i)
Result.push_back(CDS->getElementAsInteger(i));
return;
}
Constant *Mask = getMask();
for (unsigned i = 0; i != NumElts; ++i) {
Constant *C = Mask->getAggregateElement(i);
Result.push_back(isa<UndefValue>(C) ? -1 :
cast<ConstantInt>(Mask)->getZExtValue());
}
}
//===----------------------------------------------------------------------===//
// InsertValueInst Class
//===----------------------------------------------------------------------===//
@ -3457,15 +3488,11 @@ ExtractElementInst *ExtractElementInst::clone_impl() const {
}
InsertElementInst *InsertElementInst::clone_impl() const {
return InsertElementInst::Create(getOperand(0),
getOperand(1),
getOperand(2));
return InsertElementInst::Create(getOperand(0), getOperand(1), getOperand(2));
}
ShuffleVectorInst *ShuffleVectorInst::clone_impl() const {
return new ShuffleVectorInst(getOperand(0),
getOperand(1),
getOperand(2));
return new ShuffleVectorInst(getOperand(0), getOperand(1), getOperand(2));
}
PHINode *PHINode::clone_impl() const {