mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-21 02:59:15 +00:00
Handle more cases of cast-of-cast in more general forms.
llvm-svn: 3347
This commit is contained in:
parent
aac33658b1
commit
caaca8d4c9
@ -501,20 +501,47 @@ static inline bool isEliminableCastOfCast(const CastInst &CI,
|
||||
|
||||
// Allow free casting and conversion of sizes as long as the sign doesn't
|
||||
// change...
|
||||
if (isCIntegral(SrcTy) && isCIntegral(MidTy) && isCIntegral(DstTy) &&
|
||||
SrcTy->isSigned() == MidTy->isSigned() &&
|
||||
MidTy->isSigned() == DstTy->isSigned()) {
|
||||
// Only accept cases where we are either monotonically increasing the type
|
||||
// size, or monotonically decreasing it.
|
||||
//
|
||||
if (isCIntegral(SrcTy) && isCIntegral(MidTy) && isCIntegral(DstTy)) {
|
||||
unsigned SrcSize = SrcTy->getPrimitiveSize();
|
||||
unsigned MidSize = MidTy->getPrimitiveSize();
|
||||
unsigned DstSize = DstTy->getPrimitiveSize();
|
||||
if (SrcSize <= MidSize && MidSize <= DstSize)
|
||||
return true;
|
||||
|
||||
// Cases where we are monotonically decreasing the size of the type are
|
||||
// always ok, regardless of what sign changes are going on.
|
||||
//
|
||||
if (SrcSize >= MidSize && MidSize >= DstSize)
|
||||
return true;
|
||||
|
||||
// If we are monotonically growing, things are more complex.
|
||||
//
|
||||
if (SrcSize <= MidSize && MidSize <= DstSize) {
|
||||
// We have eight combinations of signedness to worry about. Here's the
|
||||
// table:
|
||||
static const int SignTable[8] = {
|
||||
// CODE, SrcSigned, MidSigned, DstSigned, Comment
|
||||
1, // U U U Always ok
|
||||
1, // U U S Always ok
|
||||
3, // U S U Ok iff SrcSize != MidSize
|
||||
3, // U S S Ok iff SrcSize != MidSize
|
||||
0, // S U U Never ok
|
||||
2, // S U S Ok iff MidSize == DstSize
|
||||
1, // S S U Always ok
|
||||
1, // S S S Always ok
|
||||
};
|
||||
|
||||
// Choose an action based on the current entry of the signtable that this
|
||||
// cast of cast refers to...
|
||||
unsigned Row = SrcTy->isSigned()*4+MidTy->isSigned()*2+DstTy->isSigned();
|
||||
switch (SignTable[Row]) {
|
||||
case 0: return false; // Never ok
|
||||
case 1: return true; // Always ok
|
||||
case 2: return MidSize == DstSize; // Ok iff MidSize == DstSize
|
||||
case 3: // Ok iff SrcSize != MidSize
|
||||
return SrcSize != MidSize || SrcTy == Type::BoolTy;
|
||||
default: assert(0 && "Bad entry in sign table!");
|
||||
}
|
||||
return false; // NOT REACHED
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, we cannot succeed. Specifically we do not want to allow things
|
||||
|
Loading…
Reference in New Issue
Block a user