Skip to content

Commit

Permalink
Teach getCastOpcode about element-by-element vector casts. For exampl…
Browse files Browse the repository at this point in the history
…e, "trunc"

can be used to turn a <4 x i64> into a <4 x i32> but getCastOpcode would assert
if you passed these types to it.  Note that this strictly extends the previous
functionality: if getCastOpcode previously accepted two vector types (i.e. didn't
assert) then it still will and returns the same opcode (BitCast).  That's because
before it would only accept vectors with the same bitwidth, and the new code only
touches vectors with the same length.  However if two vectors have both the same
bitwidth and the same length then their element types have the same bitwidth, so
the new logic will return BitCast as before.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@131530 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
CunningBaldrick committed May 18, 2011
1 parent 2a8eb72 commit 117feba
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 4 deletions.
29 changes: 25 additions & 4 deletions lib/VMCore/Instructions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2254,6 +2254,14 @@ bool CastInst::isCastable(const Type *SrcTy, const Type *DestTy) {
if (SrcTy == DestTy)
return true;

if (const VectorType *SrcVecTy = dyn_cast<VectorType>(SrcTy))
if (const VectorType *DestVecTy = dyn_cast<VectorType>(DestTy))
if (SrcVecTy->getNumElements() == DestVecTy->getNumElements()) {
// An element by element cast. Valid if casting the elements is valid.
SrcTy = SrcVecTy->getElementType();
DestTy = DestVecTy->getElementType();
}

// Get the bit sizes, we'll need these
unsigned SrcBits = SrcTy->getScalarSizeInBits(); // 0 for ptr
unsigned DestBits = DestTy->getScalarSizeInBits(); // 0 for ptr
Expand Down Expand Up @@ -2322,14 +2330,27 @@ bool CastInst::isCastable(const Type *SrcTy, const Type *DestTy) {
Instruction::CastOps
CastInst::getCastOpcode(
const Value *Src, bool SrcIsSigned, const Type *DestTy, bool DestIsSigned) {
// Get the bit sizes, we'll need these
const Type *SrcTy = Src->getType();
unsigned SrcBits = SrcTy->getScalarSizeInBits(); // 0 for ptr
unsigned DestBits = DestTy->getScalarSizeInBits(); // 0 for ptr

assert(SrcTy->isFirstClassType() && DestTy->isFirstClassType() &&
"Only first class types are castable!");

if (SrcTy == DestTy)
return BitCast;

if (const VectorType *SrcVecTy = dyn_cast<VectorType>(SrcTy))
if (const VectorType *DestVecTy = dyn_cast<VectorType>(DestTy))
if (SrcVecTy->getNumElements() == DestVecTy->getNumElements()) {
// An element by element cast. Find the appropriate opcode based on the
// element types.
SrcTy = SrcVecTy->getElementType();
DestTy = DestVecTy->getElementType();
}

// Get the bit sizes, we'll need these
unsigned SrcBits = SrcTy->getScalarSizeInBits(); // 0 for ptr
unsigned DestBits = DestTy->getScalarSizeInBits(); // 0 for ptr

// Run through the possibilities ...
if (DestTy->isIntegerTy()) { // Casting to integral
if (SrcTy->isIntegerTy()) { // Casting from integral
Expand Down Expand Up @@ -2384,7 +2405,7 @@ CastInst::getCastOpcode(
if (const VectorType *SrcPTy = dyn_cast<VectorType>(SrcTy)) {
assert(DestPTy->getBitWidth() == SrcPTy->getBitWidth() &&
"Casting vector to vector of different widths");
SrcPTy = NULL;
(void)SrcPTy;
return BitCast; // vector -> vector
} else if (DestPTy->getBitWidth() == SrcBits) {
return BitCast; // float/int -> vector
Expand Down
8 changes: 8 additions & 0 deletions unittests/VMCore/InstructionsTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,19 @@ TEST(InstructionsTest, CastInst) {
const Type* Int8Ty = Type::getInt8Ty(C);
const Type* Int64Ty = Type::getInt64Ty(C);
const Type* V8x8Ty = VectorType::get(Int8Ty, 8);
const Type* V8x64Ty = VectorType::get(Int64Ty, 8);
const Type* X86MMXTy = Type::getX86_MMXTy(C);

const Constant* c8 = Constant::getNullValue(V8x8Ty);
const Constant* c64 = Constant::getNullValue(V8x64Ty);

EXPECT_TRUE(CastInst::isCastable(V8x8Ty, X86MMXTy));
EXPECT_TRUE(CastInst::isCastable(X86MMXTy, V8x8Ty));
EXPECT_FALSE(CastInst::isCastable(Int64Ty, X86MMXTy));
EXPECT_TRUE(CastInst::isCastable(V8x64Ty, V8x8Ty));
EXPECT_TRUE(CastInst::isCastable(V8x8Ty, V8x64Ty));
EXPECT_EQ(CastInst::getCastOpcode(c64, true, V8x8Ty, true), CastInst::Trunc);
EXPECT_EQ(CastInst::getCastOpcode(c8, true, V8x64Ty, true), CastInst::SExt);
}

} // end anonymous namespace
Expand Down

0 comments on commit 117feba

Please sign in to comment.