For PR950:

The long awaited CAST patch. This introduces 12 new instructions into LLVM
to replace the cast instruction. Corresponding changes throughout LLVM are
provided. This passes llvm-test, llvm/test, and SPEC CPUINT2000 with the
exception of 175.vpr which fails only on a slight floating point output
difference.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@31931 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Reid Spencer 2006-11-27 01:05:10 +00:00
parent 5fed9b9044
commit 3da59db637
105 changed files with 6737 additions and 3700 deletions

View File

@ -27,7 +27,7 @@ namespace llvm {
/// rewrite expressions in canonical form.
///
/// Clients should create an instance of this class when rewriting is needed,
/// and destroying it when finished to allow the release of the associated
/// and destroy it when finished to allow the release of the associated
/// memory.
struct SCEVExpander : public SCEVVisitor<SCEVExpander, Value*> {
ScalarEvolution &SE;
@ -115,12 +115,12 @@ namespace llvm {
Value *visitTruncateExpr(SCEVTruncateExpr *S) {
Value *V = expand(S->getOperand());
return new CastInst(V, S->getType(), "tmp.", InsertPt);
return CastInst::createInferredCast(V, S->getType(), "tmp.", InsertPt);
}
Value *visitZeroExtendExpr(SCEVZeroExtendExpr *S) {
Value *V = expandInTy(S->getOperand(),S->getType()->getUnsignedVersion());
return new CastInst(V, S->getType(), "tmp.", InsertPt);
return CastInst::createInferredCast(V, S->getType(), "tmp.", InsertPt);
}
Value *visitAddExpr(SCEVAddExpr *S) {

View File

@ -516,9 +516,33 @@ public:
/// Cast constant expr
///
static Constant *getTrunc (Constant *C, const Type *Ty);
static Constant *getSignExtend (Constant *C, const Type *Ty);
static Constant *getZeroExtend (Constant *C, const Type *Ty);
static Constant *getFPTrunc (Constant *C, const Type *Ty);
static Constant *getFPExtend (Constant *C, const Type *Ty);
static Constant *getUIToFP (Constant *C, const Type *Ty);
static Constant *getSIToFP (Constant *C, const Type *Ty);
static Constant *getFPToUI (Constant *C, const Type *Ty);
static Constant *getFPToSI (Constant *C, const Type *Ty);
static Constant *getPtrToInt (Constant *C, const Type *Ty);
static Constant *getIntToPtr (Constant *C, const Type *Ty);
static Constant *getBitCast (Constant *C, const Type *Ty);
// @brief Convenience function for getting one of the casting operations
// using a CastOps opcode.
static Constant *getCast(
unsigned ops, ///< The opcode for the conversion
Constant *C, ///< The constant to be converted
const Type *Ty ///< The type to which the constant is converted
);
// @brief Get a ConstantExpr Conversion operator that casts C to Ty
static Constant *getCast(Constant *C, const Type *Ty);
static Constant *getSignExtend(Constant *C, const Type *Ty);
static Constant *getZeroExtend(Constant *C, const Type *Ty);
/// @brief Return true if this is a convert constant expression
bool isCast() const;
/// Select constant expr
///

View File

@ -243,6 +243,161 @@ public:
}
};
//===----------------------------------------------------------------------===//
// CastInst Class
//===----------------------------------------------------------------------===//
/// CastInst - This is the base class for all instructions that perform data
/// casts. It is simply provided so that instruction category testing
/// can be performed with code like:
///
/// if (isa<CastInst>(Instr)) { ... }
/// @brief Base class of casting instructions.
class CastInst : public UnaryInstruction {
/// @brief Copy constructor
CastInst(const CastInst &CI)
: UnaryInstruction(CI.getType(), CI.getOpcode(), CI.getOperand(0)) {
}
/// @brief Do not allow default construction
CastInst();
protected:
/// @brief Constructor with insert-before-instruction semantics for subclasses
CastInst(const Type *Ty, unsigned iType, Value *S,
const std::string &Name = "", Instruction *InsertBefore = 0)
: UnaryInstruction(Ty, iType, S, Name, InsertBefore) {
}
/// @brief Constructor with insert-at-end-of-block semantics for subclasses
CastInst(const Type *Ty, unsigned iType, Value *S,
const std::string &Name, BasicBlock *InsertAtEnd)
: UnaryInstruction(Ty, iType, S, Name, InsertAtEnd) {
}
public:
/// Provides a way to construct any of the CastInst subclasses using an
/// opcode instead of the subclass's constructor. The opcode must be in the
/// CastOps category (Instruction::isCast(opcode) returns true). This
/// constructor has insert-before-instruction semantics to automatically
/// insert the new CastInst before InsertBefore (if it is non-null).
/// @brief Construct any of the CastInst subclasses
static CastInst *create(
Instruction::CastOps, ///< The opcode of the cast instruction
Value *S, ///< The value to be casted (operand 0)
const Type *Ty, ///< The type to which cast should be made
const std::string &Name = "", ///< Name for the instruction
Instruction *InsertBefore = 0 ///< Place to insert the instruction
);
/// Provides a way to construct any of the CastInst subclasses using an
/// opcode instead of the subclass's constructor. The opcode must be in the
/// CastOps category. This constructor has insert-at-end-of-block semantics
/// to automatically insert the new CastInst at the end of InsertAtEnd (if
/// its non-null).
/// @brief Construct any of the CastInst subclasses
static CastInst *create(
Instruction::CastOps, ///< The opcode for the cast instruction
Value *S, ///< The value to be casted (operand 0)
const Type *Ty, ///< The type to which operand is casted
const std::string &Name, ///< The name for the instruction
BasicBlock *InsertAtEnd ///< The block to insert the instruction into
);
/// Returns the opcode necessary to cast Val into Ty using usual casting
/// rules.
static Instruction::CastOps getCastOpcode(
const Value *Val, ///< The value to cast
const Type *Ty ///< The Type to which the value should be casted
);
/// Joins the create method (with insert-before-instruction semantics) above
/// with the getCastOpcode method. getOpcode(S,Ty) is called first to
/// obtain the opcode for casting S to type Ty. Then the get(...) method is
/// called to create the CastInst and insert it. The instruction is
/// inserted before InsertBefore (if it is non-null). The cast created is
/// inferred, because only the types involved are used in determining which
/// cast opcode to use. For specific casts, use one of the create methods.
/// @brief Inline helper method to join create with getCastOpcode.
inline static CastInst *createInferredCast(
Value *S, ///< The value to be casted (operand 0)
const Type *Ty, ///< Type to which operand should be casted
const std::string &Name = "", ///< Name for the instruction
Instruction *InsertBefore = 0 ///< Place to insert the CastInst
) {
return create(getCastOpcode(S, Ty), S, Ty, Name, InsertBefore);
}
/// Joins the get method (with insert-at-end-of-block semantics) method
/// above with the getCastOpcode method. getOpcode(S,Ty) is called first to
/// obtain the usual casting opcode for casting S to type Ty. Then the
/// get(...) method is called to create the CastInst and insert it. The
/// instruction is inserted at the end of InsertAtEnd (if it is non-null).
/// The created cast is inferred, because only the types involved are used
/// in determining which cast opcode to use. For specific casts, use one of
/// the create methods.
/// @brief Inline helper method to join create with getCastOpcode.
inline static CastInst *createInferredCast(
Value *S, ///< The value to be casted (operand 0)
const Type *Ty, ///< Type to which operand should be casted
const std::string &Name, ///< Name for the instruction
BasicBlock *InsertAtEnd ///< The block to insert the instruction into
) {
return create(getCastOpcode(S, Ty), S, Ty, Name, InsertAtEnd);
}
/// There are several places where we need to know if a cast instruction
/// only deals with integer source and destination types. To simplify that
/// logic, this method is provided.
/// @returns true iff the cast has only integral typed operand and dest type.
/// @brief Determine if this is an integer-only cast.
bool isIntegerCast() const;
/// A lossless cast is one that does not alter the basic value. It implies
/// a no-op cast but is more stringent, preventing things like int->float,
/// long->double, int->ptr, or packed->anything.
/// @returns true iff the cast is lossless.
/// @brief Determine if this is a lossless cast.
bool isLosslessCast() const;
/// A no-op cast is one that can be effected without changing any bits.
/// It implies that the source and destination types are the same size. The
/// IntPtrTy argument is used to make accurate determinations for casts
/// involving Integer and Pointer types. They are no-op casts if the integer
/// is the same size as the pointer. However, pointer size varies with
/// platform. Generally, the result of TargetData::getIntPtrType() should be
/// passed in. If that's not available, use Type::ULongTy, which will make
/// the isNoopCast call conservative.
/// @brief Determine if this cast is a no-op cast.
bool isNoopCast(
const Type *IntPtrTy ///< Integer type corresponding to pointer
) const;
/// Determine how a pair of casts can be eliminated, if they can be at all.
/// This is a helper function for both CastInst and ConstantExpr.
/// @returns 0 if the CastInst pair can't be eliminated
/// @returns Instruction::CastOps value for a cast that can replace
/// the pair, casting SrcTy to DstTy.
/// @brief Determine if a cast pair is eliminable
static unsigned isEliminableCastPair(
Instruction::CastOps firstOpcode, ///< Opcode of first cast
Instruction::CastOps secondOpcode, ///< Opcode of second cast
const Type *SrcTy, ///< SrcTy of 1st cast
const Type *MidTy, ///< DstTy of 1st cast & SrcTy of 2nd cast
const Type *DstTy, ///< DstTy of 2nd cast
const Type *IntPtrTy ///< Integer type corresponding to Ptr types
);
/// @brief Return the opcode of this CastInst
Instruction::CastOps getOpcode() const {
return Instruction::CastOps(Instruction::getOpcode());
}
/// @brief Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const CastInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() >= CastOpsBegin && I->getOpcode() < CastOpsEnd;
}
static inline bool classof(const Value *V) {
return isa<Instruction>(V) && classof(cast<Instruction>(V));
}
};
//===----------------------------------------------------------------------===//
// CmpInst Class
//===----------------------------------------------------------------------===//

View File

@ -60,6 +60,20 @@
#define LAST_MEMORY_INST(num)
#endif
#ifndef FIRST_CAST_INST
#define FIRST_CAST_INST(num)
#endif
#ifndef HANDLE_CAST_INST
#ifndef HANDLE_INST
#define HANDLE_CAST_INST(num, opcode, Class)
#else
#define HANDLE_CAST_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class)
#endif
#endif
#ifndef LAST_CAST_INST
#define LAST_CAST_INST(num)
#endif
#ifndef FIRST_OTHER_INST
#define FIRST_OTHER_INST(num)
#endif
@ -124,24 +138,41 @@ HANDLE_MEMORY_INST(29, Store , StoreInst )
HANDLE_MEMORY_INST(30, GetElementPtr, GetElementPtrInst)
LAST_MEMORY_INST(30)
// Cast operators ...
// NOTE: The order matters here because CastInst::isEliminableCastPair
// NOTE: (see Instructions.cpp) encodes a table based on this ordering.
FIRST_CAST_INST(31)
HANDLE_CAST_INST(31, Trunc , CastInst ) // Truncate integers
HANDLE_CAST_INST(32, ZExt , CastInst ) // Zero extend integers
HANDLE_CAST_INST(33, SExt , CastInst ) // Sign extend integers
HANDLE_CAST_INST(34, FPToUI , CastInst ) // floating point -> UInt
HANDLE_CAST_INST(35, FPToSI , CastInst ) // floating point -> SInt
HANDLE_CAST_INST(36, UIToFP , CastInst ) // UInt -> floating point
HANDLE_CAST_INST(37, SIToFP , CastInst ) // SInt -> floating point
HANDLE_CAST_INST(38, FPTrunc , CastInst ) // Truncate floating point
HANDLE_CAST_INST(39, FPExt , CastInst ) // Extend floating point
HANDLE_CAST_INST(40, PtrToInt, CastInst ) // Pointer -> Integer
HANDLE_CAST_INST(41, IntToPtr, CastInst ) // Integer -> Pointer
HANDLE_CAST_INST(42, BitCast , CastInst ) // Type cast
LAST_CAST_INST(42)
// Other operators...
FIRST_OTHER_INST(31)
HANDLE_OTHER_INST(31, ICmp , ICmpInst ) // Integer comparison instruction
HANDLE_OTHER_INST(32, FCmp , FCmpInst ) // Floating point comparison instr.
HANDLE_OTHER_INST(33, PHI , PHINode ) // PHI node instruction
HANDLE_OTHER_INST(34, Cast , CastInst ) // Type cast
HANDLE_OTHER_INST(35, Call , CallInst ) // Call a function
HANDLE_OTHER_INST(36, Shl , ShiftInst ) // Shift Left operations (logical)
HANDLE_OTHER_INST(37, LShr , ShiftInst ) // Logical Shift right (unsigned)
HANDLE_OTHER_INST(38, AShr , ShiftInst ) // Arithmetic shift right (signed)
HANDLE_OTHER_INST(39, Select , SelectInst ) // select instruction
HANDLE_OTHER_INST(40, UserOp1, Instruction) // May be used internally in a pass
HANDLE_OTHER_INST(41, UserOp2, Instruction) // Internal to passes only
HANDLE_OTHER_INST(42, VAArg , VAArgInst ) // vaarg instruction
HANDLE_OTHER_INST(43, ExtractElement, ExtractElementInst)// extract from vector.
HANDLE_OTHER_INST(44, InsertElement, InsertElementInst) // insert into vector
HANDLE_OTHER_INST(45, ShuffleVector, ShuffleVectorInst) // shuffle two vectors.
LAST_OTHER_INST(45)
FIRST_OTHER_INST(43)
HANDLE_OTHER_INST(43, ICmp , ICmpInst ) // Integer comparison instruction
HANDLE_OTHER_INST(44, FCmp , FCmpInst ) // Floating point comparison instr.
HANDLE_OTHER_INST(45, PHI , PHINode ) // PHI node instruction
HANDLE_OTHER_INST(46, Call , CallInst ) // Call a function
HANDLE_OTHER_INST(47, Shl , ShiftInst ) // Shift Left operations (logical)
HANDLE_OTHER_INST(48, LShr , ShiftInst ) // Logical Shift right (unsigned)
HANDLE_OTHER_INST(49, AShr , ShiftInst ) // Arithmetic shift right (signed)
HANDLE_OTHER_INST(50, Select , SelectInst ) // select instruction
HANDLE_OTHER_INST(51, UserOp1, Instruction) // May be used internally in a pass
HANDLE_OTHER_INST(52, UserOp2, Instruction) // Internal to passes only
HANDLE_OTHER_INST(53, VAArg , VAArgInst ) // vaarg instruction
HANDLE_OTHER_INST(54, ExtractElement, ExtractElementInst)// extract from vector.
HANDLE_OTHER_INST(55, InsertElement, InsertElementInst) // insert into vector
HANDLE_OTHER_INST(56, ShuffleVector, ShuffleVectorInst) // shuffle two vectors.
LAST_OTHER_INST(56)
#undef FIRST_TERM_INST
#undef HANDLE_TERM_INST
@ -155,6 +186,10 @@ HANDLE_OTHER_INST(45, ShuffleVector, ShuffleVectorInst) // shuffle two vectors.
#undef HANDLE_MEMORY_INST
#undef LAST_MEMORY_INST
#undef FIRST_CAST_INST
#undef HANDLE_CAST_INST
#undef LAST_CAST_INST
#undef FIRST_OTHER_INST
#undef HANDLE_OTHER_INST
#undef LAST_OTHER_INST

View File

@ -125,6 +125,16 @@ public:
return getOpcode() >= BinaryOpsBegin && getOpcode() < BinaryOpsEnd;
}
/// @brief Determine if the OpCode is one of the CastInst instructions.
static inline bool isCast(unsigned OpCode) {
return OpCode >= CastOpsBegin && OpCode < CastOpsEnd;
}
/// @brief Determine if this is one of the CastInst instructions.
inline bool isCast() const {
return isCast(getOpcode());
}
/// isAssociative - Return true if the instruction is associative:
///
/// Associative operators satisfy: x op (y op z) === (x op y) op z
@ -191,6 +201,13 @@ public:
#include "llvm/Instruction.def"
};
enum CastOps {
#define FIRST_CAST_INST(N) CastOpsBegin = N,
#define HANDLE_CAST_INST(N, OPC, CLASS) OPC = N,
#define LAST_CAST_INST(N) CastOpsEnd = N+1
#include "llvm/Instruction.def"
};
enum OtherOps {
#define FIRST_OTHER_INST(N) OtherOpsBegin = N,
#define HANDLE_OTHER_INST(N, OPC, CLASS) OPC = N,

View File

@ -710,44 +710,6 @@ public:
}
};
//===----------------------------------------------------------------------===//
// CastInst Class
//===----------------------------------------------------------------------===//
/// CastInst - This class represents a cast from Operand[0] to the type of
/// the instruction (i->getType()).
///
class CastInst : public UnaryInstruction {
CastInst(const CastInst &CI)
: UnaryInstruction(CI.getType(), Cast, CI.getOperand(0)) {
}
public:
CastInst(Value *S, const Type *Ty, const std::string &Name = "",
Instruction *InsertBefore = 0)
: UnaryInstruction(Ty, Cast, S, Name, InsertBefore) {
}
CastInst(Value *S, const Type *Ty, const std::string &Name,
BasicBlock *InsertAtEnd)
: UnaryInstruction(Ty, Cast, S, Name, InsertAtEnd) {
}
/// isTruncIntCast - Return true if this is a truncating integer cast
/// instruction, e.g. a cast from long to uint.
bool isTruncIntCast() const;
virtual CastInst *clone() const;
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const CastInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Cast;
}
static inline bool classof(const Value *V) {
return isa<Instruction>(V) && classof(cast<Instruction>(V));
}
};
//===----------------------------------------------------------------------===//
// CallInst Class
@ -1770,6 +1732,477 @@ private:
virtual void setSuccessorV(unsigned idx, BasicBlock *B);
};
//===----------------------------------------------------------------------===//
// TruncInst Class
//===----------------------------------------------------------------------===//
/// @brief This class represents a truncation of integer types.
class TruncInst : public CastInst {
/// Private copy constructor
TruncInst(const TruncInst &CI)
: CastInst(CI.getType(), Trunc, CI.getOperand(0)) {
}
public:
/// @brief Constructor with insert-before-instruction semantics
TruncInst(
Value *S, ///< The value to be truncated
const Type *Ty, ///< The (smaller) type to truncate to
const std::string &Name = "", ///< A name for the new instruction
Instruction *InsertBefore = 0 ///< Where to insert the new instruction
);
/// @brief Constructor with insert-at-end-of-block semantics
TruncInst(
Value *S, ///< The value to be truncated
const Type *Ty, ///< The (smaller) type to truncate to
const std::string &Name, ///< A name for the new instruction
BasicBlock *InsertAtEnd ///< The block to insert the instruction into
);
/// @brief Clone an identical TruncInst
virtual CastInst *clone() const;
/// @brief Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const TruncInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Trunc;
}
static inline bool classof(const Value *V) {
return isa<Instruction>(V) && classof(cast<Instruction>(V));
}
};
//===----------------------------------------------------------------------===//
// ZExtInst Class
//===----------------------------------------------------------------------===//
/// @brief This class represents zero extension of integer types.
class ZExtInst : public CastInst {
/// @brief Private copy constructor
ZExtInst(const ZExtInst &CI)
: CastInst(CI.getType(), ZExt, CI.getOperand(0)) {
}
public:
/// @brief Constructor with insert-before-instruction semantics
ZExtInst(
Value *S, ///< The value to be zero extended
const Type *Ty, ///< The type to zero extend to
const std::string &Name = "", ///< A name for the new instruction
Instruction *InsertBefore = 0 ///< Where to insert the new instruction
);
/// @brief Constructor with insert-at-end semantics.
ZExtInst(
Value *S, ///< The value to be zero extended
const Type *Ty, ///< The type to zero extend to
const std::string &Name, ///< A name for the new instruction
BasicBlock *InsertAtEnd ///< The block to insert the instruction into
);
/// @brief Clone an identical ZExtInst
virtual CastInst *clone() const;
/// @brief Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const ZExtInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == ZExt;
}
static inline bool classof(const Value *V) {
return isa<Instruction>(V) && classof(cast<Instruction>(V));
}
};
//===----------------------------------------------------------------------===//
// SExtInst Class
//===----------------------------------------------------------------------===//
/// @brief This class represents a sign extension of integer types.
class SExtInst : public CastInst {
/// @brief Private copy constructor
SExtInst(const SExtInst &CI)
: CastInst(CI.getType(), SExt, CI.getOperand(0)) {
}
public:
/// @brief Constructor with insert-before-instruction semantics
SExtInst(
Value *S, ///< The value to be sign extended
const Type *Ty, ///< The type to sign extend to
const std::string &Name = "", ///< A name for the new instruction
Instruction *InsertBefore = 0 ///< Where to insert the new instruction
);
/// @brief Constructor with insert-at-end-of-block semantics
SExtInst(
Value *S, ///< The value to be sign extended
const Type *Ty, ///< The type to sign extend to
const std::string &Name, ///< A name for the new instruction
BasicBlock *InsertAtEnd ///< The block to insert the instruction into
);
/// @brief Clone an identical SExtInst
virtual CastInst *clone() const;
/// @brief Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SExtInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == SExt;
}
static inline bool classof(const Value *V) {
return isa<Instruction>(V) && classof(cast<Instruction>(V));
}
};
//===----------------------------------------------------------------------===//
// FPTruncInst Class
//===----------------------------------------------------------------------===//
/// @brief This class represents a truncation of floating point types.
class FPTruncInst : public CastInst {
FPTruncInst(const FPTruncInst &CI)
: CastInst(CI.getType(), FPTrunc, CI.getOperand(0)) {
}
public:
/// @brief Constructor with insert-before-instruction semantics
FPTruncInst(
Value *S, ///< The value to be truncated
const Type *Ty, ///< The type to truncate to
const std::string &Name = "", ///< A name for the new instruction
Instruction *InsertBefore = 0 ///< Where to insert the new instruction
);
/// @brief Constructor with insert-before-instruction semantics
FPTruncInst(
Value *S, ///< The value to be truncated
const Type *Ty, ///< The type to truncate to
const std::string &Name, ///< A name for the new instruction
BasicBlock *InsertAtEnd ///< The block to insert the instruction into
);
/// @brief Clone an identical FPTruncInst
virtual CastInst *clone() const;
/// @brief Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const FPTruncInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == FPTrunc;
}
static inline bool classof(const Value *V) {
return isa<Instruction>(V) && classof(cast<Instruction>(V));
}
};
//===----------------------------------------------------------------------===//
// FPExtInst Class
//===----------------------------------------------------------------------===//
/// @brief This class represents an extension of floating point types.
class FPExtInst : public CastInst {
FPExtInst(const FPExtInst &CI)
: CastInst(CI.getType(), FPExt, CI.getOperand(0)) {
}
public:
/// @brief Constructor with insert-before-instruction semantics
FPExtInst(
Value *S, ///< The value to be extended
const Type *Ty, ///< The type to extend to
const std::string &Name = "", ///< A name for the new instruction
Instruction *InsertBefore = 0 ///< Where to insert the new instruction
);
/// @brief Constructor with insert-at-end-of-block semantics
FPExtInst(
Value *S, ///< The value to be extended
const Type *Ty, ///< The type to extend to
const std::string &Name, ///< A name for the new instruction
BasicBlock *InsertAtEnd ///< The block to insert the instruction into
);
/// @brief Clone an identical FPExtInst
virtual CastInst *clone() const;
/// @brief Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const FPExtInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == FPExt;
}
static inline bool classof(const Value *V) {
return isa<Instruction>(V) && classof(cast<Instruction>(V));
}
};
//===----------------------------------------------------------------------===//
// UIToFPInst Class
//===----------------------------------------------------------------------===//
/// @brief This class represents a cast unsigned integer to floating point.
class UIToFPInst : public CastInst {
UIToFPInst(const UIToFPInst &CI)
: CastInst(CI.getType(), UIToFP, CI.getOperand(0)) {
}
public:
/// @brief Constructor with insert-before-instruction semantics
UIToFPInst(
Value *S, ///< The value to be converted
const Type *Ty, ///< The type to convert to
const std::string &Name = "", ///< A name for the new instruction
Instruction *InsertBefore = 0 ///< Where to insert the new instruction
);
/// @brief Constructor with insert-at-end-of-block semantics
UIToFPInst(
Value *S, ///< The value to be converted
const Type *Ty, ///< The type to convert to
const std::string &Name, ///< A name for the new instruction
BasicBlock *InsertAtEnd ///< The block to insert the instruction into
);
/// @brief Clone an identical UIToFPInst
virtual CastInst *clone() const;
/// @brief Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const UIToFPInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == UIToFP;
}
static inline bool classof(const Value *V) {
return isa<Instruction>(V) && classof(cast<Instruction>(V));
}
};
//===----------------------------------------------------------------------===//
// SIToFPInst Class
//===----------------------------------------------------------------------===//
/// @brief This class represents a cast from signed integer to floating point.
class SIToFPInst : public CastInst {
SIToFPInst(const SIToFPInst &CI)
: CastInst(CI.getType(), SIToFP, CI.getOperand(0)) {
}
public:
/// @brief Constructor with insert-before-instruction semantics
SIToFPInst(
Value *S, ///< The value to be converted
const Type *Ty, ///< The type to convert to
const std::string &Name = "", ///< A name for the new instruction
Instruction *InsertBefore = 0 ///< Where to insert the new instruction
);
/// @brief Constructor with insert-at-end-of-block semantics
SIToFPInst(
Value *S, ///< The value to be converted
const Type *Ty, ///< The type to convert to
const std::string &Name, ///< A name for the new instruction
BasicBlock *InsertAtEnd ///< The block to insert the instruction into
);
/// @brief Clone an identical SIToFPInst
virtual CastInst *clone() const;
/// @brief Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SIToFPInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == SIToFP;
}
static inline bool classof(const Value *V) {
return isa<Instruction>(V) && classof(cast<Instruction>(V));
}
};
//===----------------------------------------------------------------------===//
// FPToUIInst Class
//===----------------------------------------------------------------------===//
/// @brief This class represents a cast from floating point to unsigned integer
class FPToUIInst : public CastInst {
FPToUIInst(const FPToUIInst &CI)
: CastInst(CI.getType(), FPToUI, CI.getOperand(0)) {
}
public:
/// @brief Constructor with insert-before-instruction semantics
FPToUIInst(
Value *S, ///< The value to be converted
const Type *Ty, ///< The type to convert to
const std::string &Name = "", ///< A name for the new instruction
Instruction *InsertBefore = 0 ///< Where to insert the new instruction
);
/// @brief Constructor with insert-at-end-of-block semantics
FPToUIInst(
Value *S, ///< The value to be converted
const Type *Ty, ///< The type to convert to
const std::string &Name, ///< A name for the new instruction
BasicBlock *InsertAtEnd ///< Where to insert the new instruction
);
/// @brief Clone an identical FPToUIInst
virtual CastInst *clone() const;
/// @brief Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const FPToUIInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == FPToUI;
}
static inline bool classof(const Value *V) {
return isa<Instruction>(V) && classof(cast<Instruction>(V));
}
};
//===----------------------------------------------------------------------===//
// FPToSIInst Class
//===----------------------------------------------------------------------===//
/// @brief This class represents a cast from floating point to signed integer.
class FPToSIInst : public CastInst {
FPToSIInst(const FPToSIInst &CI)
: CastInst(CI.getType(), FPToSI, CI.getOperand(0)) {
}
public:
/// @brief Constructor with insert-before-instruction semantics
FPToSIInst(
Value *S, ///< The value to be converted
const Type *Ty, ///< The type to convert to
const std::string &Name = "", ///< A name for the new instruction
Instruction *InsertBefore = 0 ///< Where to insert the new instruction
);
/// @brief Constructor with insert-at-end-of-block semantics
FPToSIInst(
Value *S, ///< The value to be converted
const Type *Ty, ///< The type to convert to
const std::string &Name, ///< A name for the new instruction
BasicBlock *InsertAtEnd ///< The block to insert the instruction into
);
/// @brief Clone an identical FPToSIInst
virtual CastInst *clone() const;
/// @brief Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const FPToSIInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == FPToSI;
}
static inline bool classof(const Value *V) {
return isa<Instruction>(V) && classof(cast<Instruction>(V));
}
};
//===----------------------------------------------------------------------===//
// IntToPtrInst Class
//===----------------------------------------------------------------------===//
/// @brief This class represents a cast from an integer to a pointer.
class IntToPtrInst : public CastInst {
IntToPtrInst(const IntToPtrInst &CI)
: CastInst(CI.getType(), IntToPtr, CI.getOperand(0)) {
}
public:
/// @brief Constructor with insert-before-instruction semantics
IntToPtrInst(
Value *S, ///< The value to be converted
const Type *Ty, ///< The type to convert to
const std::string &Name = "", ///< A name for the new instruction
Instruction *InsertBefore = 0 ///< Where to insert the new instruction
);
/// @brief Constructor with insert-at-end-of-block semantics
IntToPtrInst(
Value *S, ///< The value to be converted
const Type *Ty, ///< The type to convert to
const std::string &Name, ///< A name for the new instruction
BasicBlock *InsertAtEnd ///< The block to insert the instruction into
);
/// @brief Clone an identical IntToPtrInst
virtual CastInst *clone() const;
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const IntToPtrInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == IntToPtr;
}
static inline bool classof(const Value *V) {
return isa<Instruction>(V) && classof(cast<Instruction>(V));
}
};
//===----------------------------------------------------------------------===//
// PtrToIntInst Class
//===----------------------------------------------------------------------===//
/// @brief This class represents a cast from a pointer to an integer
class PtrToIntInst : public CastInst {
PtrToIntInst(const PtrToIntInst &CI)
: CastInst(CI.getType(), PtrToInt, CI.getOperand(0)) {
}
public:
/// @brief Constructor with insert-before-instruction semantics
PtrToIntInst(
Value *S, ///< The value to be converted
const Type *Ty, ///< The type to convert to
const std::string &Name = "", ///< A name for the new instruction
Instruction *InsertBefore = 0 ///< Where to insert the new instruction
);
/// @brief Constructor with insert-at-end-of-block semantics
PtrToIntInst(
Value *S, ///< The value to be converted
const Type *Ty, ///< The type to convert to
const std::string &Name, ///< A name for the new instruction
BasicBlock *InsertAtEnd ///< The block to insert the instruction into
);
/// @brief Clone an identical PtrToIntInst
virtual CastInst *clone() const;
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const PtrToIntInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == PtrToInt;
}
static inline bool classof(const Value *V) {
return isa<Instruction>(V) && classof(cast<Instruction>(V));
}
};
//===----------------------------------------------------------------------===//
// BitCastInst Class
//===----------------------------------------------------------------------===//
/// @brief This class represents a no-op cast from one type to another.
class BitCastInst : public CastInst {
BitCastInst(const BitCastInst &CI)
: CastInst(CI.getType(), BitCast, CI.getOperand(0)) {
}
public:
/// @brief Constructor with insert-before-instruction semantics
BitCastInst(
Value *S, ///< The value to be casted
const Type *Ty, ///< The type to casted to
const std::string &Name = "", ///< A name for the new instruction
Instruction *InsertBefore = 0 ///< Where to insert the new instruction
);
/// @brief Constructor with insert-at-end-of-block semantics
BitCastInst(
Value *S, ///< The value to be casted
const Type *Ty, ///< The type to casted to
const std::string &Name, ///< A name for the new instruction
BasicBlock *InsertAtEnd ///< The block to insert the instruction into
);
/// @brief Clone an identical BitCastInst
virtual CastInst *clone() const;
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const BitCastInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == BitCast;
}
static inline bool classof(const Value *V) {
return isa<Instruction>(V) && classof(cast<Instruction>(V));
}
};
} // End llvm namespace
#endif

View File

@ -143,7 +143,6 @@ public:
void visitFunction (Function &F) {}
void visitBasicBlock(BasicBlock &BB) {}
// Define instruction specific visitor functions that can be overridden to
// handle SPECIFIC instructions. These functions automatically define
// visitMul to proxy to visitBinaryOperator for instance in case the user does
@ -183,7 +182,7 @@ public:
RetTy visitCallInst(CallInst &I) { DELEGATE(Instruction); }
RetTy visitShiftInst(ShiftInst &I) { DELEGATE(Instruction); }
RetTy visitVAArgInst(VAArgInst &I) { DELEGATE(Instruction); }
RetTy visitExtractElementInst(ExtractElementInst &I) { DELEGATE(Instruction); }
RetTy visitExtractElementInst(ExtractElementInst &I) { DELEGATE(Instruction);}
RetTy visitInsertElementInst(InsertElementInst &I) { DELEGATE(Instruction); }
RetTy visitShuffleVectorInst(ShuffleVectorInst &I) { DELEGATE(Instruction); }

View File

@ -10,7 +10,7 @@
// This file provides a simple and efficient mechanism for performing general
// tree-based pattern matches on the LLVM IR. The power of these routines is
// that it allows you to write concise patterns that are expressive and easy to
// understand. The other major advantage of this is that is allows to you
// understand. The other major advantage of this is that it allows you to
// trivially capture/bind elements in the pattern to variables. For example,
// you can do something like this:
//
@ -336,38 +336,6 @@ template<typename LHS>
inline not_match<LHS> m_Not(const LHS &L) { return L; }
template<typename Op_t>
struct cast_match {
Op_t Op;
const Type **DestTy;
cast_match(const Op_t &op, const Type **destTy) : Op(op), DestTy(destTy) {}
template<typename OpTy>
bool match(OpTy *V) {
if (CastInst *I = dyn_cast<CastInst>(V)) {
if (DestTy) *DestTy = I->getType();
return Op.match(I->getOperand(0));
} else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
if (CE->getOpcode() == Instruction::Cast) {
if (DestTy) *DestTy = CE->getType();
return Op.match(CE->getOperand(0));
}
}
return false;
}
};
template<typename Op_t>
inline cast_match<Op_t> m_Cast(const Op_t &Op, const Type *&Ty) {
return cast_match<Op_t>(Op, &Ty);
}
template<typename Op_t>
inline cast_match<Op_t> m_Cast(const Op_t &Op) {
return cast_match<Op_t>(Op, 0);
}
//===----------------------------------------------------------------------===//
// Matchers for control flow
//

View File

@ -194,10 +194,12 @@ public:
///
inline bool isAbstract() const { return Abstract; }
/// isLosslesslyConvertibleTo - Return true if this type can be converted to
/// 'Ty' without any reinterpretation of bits. For example, uint to int.
///
bool isLosslesslyConvertibleTo(const Type *Ty) const;
/// canLosslesslyBitCastTo - Return true if this type could be converted
/// with a lossless BitCast to type 'Ty'. For example, uint to int. BitCasts
/// are valid for types of the same size only where no re-interpretation of
/// the bits is done.
/// @brief Determine if this type could be losslessly bitcast to Ty
bool canLosslesslyBitCastTo(const Type *Ty) const;
/// Here are some useful little methods to query what type derived types are

View File

@ -129,27 +129,23 @@ ImmutablePass *llvm::createBasicAliasAnalysisPass() {
return new BasicAliasAnalysis();
}
// hasUniqueAddress - Return true if the specified value points to something
// with a unique, discernable, address.
static inline bool hasUniqueAddress(const Value *V) {
return isa<GlobalValue>(V) || isa<AllocationInst>(V);
}
// getUnderlyingObject - This traverses the use chain to figure out what object
// the specified value points to. If the value points to, or is derived from, a
// unique object or an argument, return it.
static const Value *getUnderlyingObject(const Value *V) {
if (!isa<PointerType>(V->getType())) return 0;
// If we are at some type of object... return it.
if (hasUniqueAddress(V) || isa<Argument>(V)) return V;
// If we are at some type of object, return it. GlobalValues and Allocations
// have unique addresses.
if (isa<GlobalValue>(V) || isa<AllocationInst>(V) || isa<Argument>(V))
return V;
// Traverse through different addressing mechanisms...
if (const Instruction *I = dyn_cast<Instruction>(V)) {
if (isa<CastInst>(I) || isa<GetElementPtrInst>(I))
if (isa<BitCastInst>(I) || isa<GetElementPtrInst>(I))
return getUnderlyingObject(I->getOperand(0));
} else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
if (CE->getOpcode() == Instruction::Cast ||
if (CE->getOpcode() == Instruction::BitCast ||
CE->getOpcode() == Instruction::GetElementPtr)
return getUnderlyingObject(CE->getOperand(0));
}
@ -192,28 +188,34 @@ bool BasicAliasAnalysis::pointsToConstantMemory(const Value *P) {
return false;
}
// Determine if an AllocationInst instruction escapes from the function it is
// contained in. If it does not escape, there is no way for another function to
// mod/ref it. We do this by looking at its uses and determining if the uses
// can escape (recursively).
static bool AddressMightEscape(const Value *V) {
for (Value::use_const_iterator UI = V->use_begin(), E = V->use_end();
UI != E; ++UI) {
const Instruction *I = cast<Instruction>(*UI);
switch (I->getOpcode()) {
case Instruction::Load: break;
case Instruction::Load:
break; //next use.
case Instruction::Store:
if (I->getOperand(0) == V)
return true; // Escapes if the pointer is stored.
break;
break; // next use.
case Instruction::GetElementPtr:
if (AddressMightEscape(I)) return true;
break;
case Instruction::Cast:
if (AddressMightEscape(I))
return true;
case Instruction::BitCast:
if (!isa<PointerType>(I->getType()))
return true;
if (AddressMightEscape(I)) return true;
break;
if (AddressMightEscape(I))
return true;
break; // next use
case Instruction::Ret:
// If returned, the address will escape to calling functions, but no
// callees could modify it.
break;
break; // next use
default:
return true;
}
@ -257,12 +259,10 @@ BasicAliasAnalysis::alias(const Value *V1, unsigned V1Size,
const Value *V2, unsigned V2Size) {
// Strip off any constant expression casts if they exist
if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(V1))
if (CE->getOpcode() == Instruction::Cast &&
isa<PointerType>(CE->getOperand(0)->getType()))
if (CE->isCast() && isa<PointerType>(CE->getOperand(0)->getType()))
V1 = CE->getOperand(0);
if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(V2))
if (CE->getOpcode() == Instruction::Cast &&
isa<PointerType>(CE->getOperand(0)->getType()))
if (CE->isCast() && isa<PointerType>(CE->getOperand(0)->getType()))
V2 = CE->getOperand(0);
// Are we checking for alias of the same value?
@ -273,10 +273,10 @@ BasicAliasAnalysis::alias(const Value *V1, unsigned V1Size,
return NoAlias; // Scalars cannot alias each other
// Strip off cast instructions...
if (const Instruction *I = dyn_cast<CastInst>(V1))
if (const BitCastInst *I = dyn_cast<BitCastInst>(V1))
if (isa<PointerType>(I->getOperand(0)->getType()))
return alias(I->getOperand(0), V1Size, V2, V2Size);
if (const Instruction *I = dyn_cast<CastInst>(V2))
if (const BitCastInst *I = dyn_cast<BitCastInst>(V2))
if (isa<PointerType>(I->getOperand(0)->getType()))
return alias(V1, V1Size, I->getOperand(0), V2Size);
@ -450,14 +450,22 @@ BasicAliasAnalysis::alias(const Value *V1, unsigned V1Size,
return MayAlias;
}
static bool ValuesEqual(Value *V1, Value *V2) {
// This function is used to determin if the indices of two GEP instructions are
// equal. V1 and V2 are the indices.
static bool IndexOperandsEqual(Value *V1, Value *V2) {
if (V1->getType() == V2->getType())
return V1 == V2;
if (Constant *C1 = dyn_cast<Constant>(V1))
if (Constant *C2 = dyn_cast<Constant>(V2)) {
// Sign extend the constants to long types.
C1 = ConstantExpr::getSignExtend(C1, Type::LongTy);
C2 = ConstantExpr::getSignExtend(C2, Type::LongTy);
// Sign extend the constants to long types, if necessary
if (C1->getType()->getPrimitiveSizeInBits() < 64)
C1 = ConstantExpr::getSignExtend(C1, Type::LongTy);
else if (C1->getType() == Type::ULongTy)
C1 = ConstantExpr::getBitCast(C1, Type::LongTy);
if (C2->getType()->getPrimitiveSizeInBits() < 64)
C2 = ConstantExpr::getSignExtend(C2, Type::LongTy);
else if (C2->getType() == Type::ULongTy)
C2 = ConstantExpr::getBitCast(C2, Type::LongTy);
return C1 == C2;
}
return false;
@ -485,7 +493,7 @@ BasicAliasAnalysis::CheckGEPInstructions(
unsigned MaxOperands = std::max(NumGEP1Operands, NumGEP2Operands);
unsigned UnequalOper = 0;
while (UnequalOper != MinOperands &&
ValuesEqual(GEP1Ops[UnequalOper], GEP2Ops[UnequalOper])) {
IndexOperandsEqual(GEP1Ops[UnequalOper], GEP2Ops[UnequalOper])) {
// Advance through the type as we go...
++UnequalOper;
if (const CompositeType *CT = dyn_cast<CompositeType>(BasePtr1Ty))
@ -546,8 +554,14 @@ BasicAliasAnalysis::CheckGEPInstructions(
if (Constant *G2OC = dyn_cast<ConstantInt>(const_cast<Value*>(G2Oper))){
if (G1OC->getType() != G2OC->getType()) {
// Sign extend both operands to long.
G1OC = ConstantExpr::getSignExtend(G1OC, Type::LongTy);
G2OC = ConstantExpr::getSignExtend(G2OC, Type::LongTy);
if (G1OC->getType()->getPrimitiveSizeInBits() < 64)
G1OC = ConstantExpr::getSignExtend(G1OC, Type::LongTy);
else if (G1OC->getType() == Type::ULongTy)
G1OC = ConstantExpr::getBitCast(G1OC, Type::LongTy);
if (G2OC->getType()->getPrimitiveSizeInBits() < 64)
G2OC = ConstantExpr::getSignExtend(G2OC, Type::LongTy);
else if (G2OC->getType() == Type::ULongTy)
G2OC = ConstantExpr::getBitCast(G2OC, Type::LongTy);
GEP1Ops[FirstConstantOper] = G1OC;
GEP2Ops[FirstConstantOper] = G2OC;
}

View File

@ -410,7 +410,7 @@ static bool ElementTypesAreCompatible(const Type *T1, const Type *T2,
const Type *T1 = T1W.getCurrentType();
const Type *T2 = T2W.getCurrentType();
if (T1 != T2 && !T1->isLosslesslyConvertibleTo(T2))
if (T1 != T2 && !T1->canLosslesslyBitCastTo(T2))
return false;
T1W.StepToNextType();
@ -701,7 +701,7 @@ bool DSNode::mergeTypeInfo(const Type *NewTy, unsigned Offset,
// Check to see if we have a compatible, but different type...
if (NewTySize == SubTypeSize) {
// Check to see if this type is obviously convertible... int -> uint f.e.
if (NewTy->isLosslesslyConvertibleTo(SubType))
if (NewTy->canLosslesslyBitCastTo(SubType))
return false;
// Check to see if we have a pointer & integer mismatch going on here,

View File

@ -240,7 +240,7 @@ DSNodeHandle GraphBuilder::getValueDest(Value &Val) {
N->addGlobal(GV);
} else if (Constant *C = dyn_cast<Constant>(V)) {
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
if (CE->getOpcode() == Instruction::Cast) {
if (CE->isCast()) {
if (isa<PointerType>(CE->getOperand(0)->getType()))
NH = getValueDest(*CE->getOperand(0));
else
@ -1091,20 +1091,27 @@ void GraphBuilder::visitFreeInst(FreeInst &FI) {
/// Handle casts...
void GraphBuilder::visitCastInst(CastInst &CI) {
if (isPointerType(CI.getType()))
if (isPointerType(CI.getOperand(0)->getType())) {
DSNodeHandle Ptr = getValueDest(*CI.getOperand(0));
if (Ptr.getNode() == 0) return;
// Cast one pointer to the other, just act like a copy instruction
setDestTo(CI, Ptr);
} else {
// Cast something (floating point, small integer) to a pointer. We need
// to track the fact that the node points to SOMETHING, just something we
// don't know about. Make an "Unknown" node.
//
setDestTo(CI, createNode()->setUnknownNodeMarker());
}
// Pointers can only be cast with BitCast so check that the instruction
// is a BitConvert. If not, its guaranteed not to involve any pointers so
// we don't do anything.
switch (CI.getOpcode()) {
default: break;
case Instruction::BitCast:
case Instruction::IntToPtr:
if (isPointerType(CI.getType()))
if (isPointerType(CI.getOperand(0)->getType())) {
DSNodeHandle Ptr = getValueDest(*CI.getOperand(0));
if (Ptr.getNode() == 0) return;
// Cast one pointer to the other, just act like a copy instruction
setDestTo(CI, Ptr);
} else {
// Cast something (floating point, small integer) to a pointer. We
// need to track the fact that the node points to SOMETHING, just
// something we don't know about. Make an "Unknown" node.
setDestTo(CI, createNode()->setUnknownNodeMarker());
}
break;
}
}

View File

@ -529,11 +529,10 @@ Andersens::Node *Andersens::getNodeForConstantPointer(Constant *C) {
switch (CE->getOpcode()) {
case Instruction::GetElementPtr:
return getNodeForConstantPointer(CE->getOperand(0));
case Instruction::Cast:
if (isa<PointerType>(CE->getOperand(0)->getType()))
return getNodeForConstantPointer(CE->getOperand(0));
else
return &GraphNodes[UniversalSet];
case Instruction::IntToPtr:
return &GraphNodes[UniversalSet];
case Instruction::BitCast:
return getNodeForConstantPointer(CE->getOperand(0));
default:
std::cerr << "Constant Expr not yet handled: " << *CE << "\n";
assert(0);
@ -557,11 +556,10 @@ Andersens::Node *Andersens::getNodeForConstantPointerTarget(Constant *C) {
switch (CE->getOpcode()) {
case Instruction::GetElementPtr:
return getNodeForConstantPointerTarget(CE->getOperand(0));
case Instruction::Cast:
if (isa<PointerType>(CE->getOperand(0)->getType()))
return getNodeForConstantPointerTarget(CE->getOperand(0));
else
return &GraphNodes[UniversalSet];
case Instruction::IntToPtr:
return &GraphNodes[UniversalSet];
case Instruction::BitCast:
return getNodeForConstantPointerTarget(CE->getOperand(0));
default:
std::cerr << "Constant Expr not yet handled: " << *CE << "\n";
assert(0);

View File

@ -167,10 +167,10 @@ static Value *getUnderlyingObject(Value *V) {
// Traverse through different addressing mechanisms.
if (Instruction *I = dyn_cast<Instruction>(V)) {
if (isa<CastInst>(I) || isa<GetElementPtrInst>(I))
if (isa<BitCastInst>(I) || isa<GetElementPtrInst>(I))
return getUnderlyingObject(I->getOperand(0));
} else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
if (CE->getOpcode() == Instruction::Cast ||
if (CE->getOpcode() == Instruction::BitCast ||
CE->getOpcode() == Instruction::GetElementPtr)
return getUnderlyingObject(CE->getOperand(0));
}
@ -252,8 +252,8 @@ bool GlobalsModRef::AnalyzeUsesOfPointer(Value *V,
for (unsigned i = 3, e = II->getNumOperands(); i != e; ++i)
if (II->getOperand(i) == V) return true;
} else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(*UI)) {
if (CE->getOpcode() == Instruction::GetElementPtr ||
CE->getOpcode() == Instruction::Cast) {
if (CE->getOpcode() == Instruction::GetElementPtr ||
CE->getOpcode() == Instruction::BitCast) {
if (AnalyzeUsesOfPointer(CE, Readers, Writers))
return true;
} else {

View File

@ -203,7 +203,6 @@ static ManagedStatic<std::map<std::pair<SCEV*, const Type*>,
SCEVTruncateExpr::SCEVTruncateExpr(const SCEVHandle &op, const Type *ty)
: SCEV(scTruncate), Op(op), Ty(ty) {
assert(Op->getType()->isInteger() && Ty->isInteger() &&
Ty->isUnsigned() &&
"Cannot truncate non-integer value!");
assert(Op->getType()->getPrimitiveSize() > Ty->getPrimitiveSize() &&
"This is not a truncating conversion!");
@ -230,7 +229,6 @@ static ManagedStatic<std::map<std::pair<SCEV*, const Type*>,
SCEVZeroExtendExpr::SCEVZeroExtendExpr(const SCEVHandle &op, const Type *ty)
: SCEV(scZeroExtend), Op(op), Ty(ty) {
assert(Op->getType()->isInteger() && Ty->isInteger() &&
Ty->isUnsigned() &&
"Cannot zero extend non-integer value!");
assert(Op->getType()->getPrimitiveSize() < Ty->getPrimitiveSize() &&
"This is not an extending conversion!");
@ -1139,7 +1137,6 @@ namespace {
/// createSCEV - We know that there is no SCEV for the specified value.
/// Analyze the expression.
SCEVHandle createSCEV(Value *V);
SCEVHandle createNodeForCast(CastInst *CI);
/// createNodeForPHI - Provide the special handling we need to analyze PHI
/// SCEVs.
@ -1341,35 +1338,6 @@ SCEVHandle ScalarEvolutionsImpl::createNodeForPHI(PHINode *PN) {
return SCEVUnknown::get(PN);
}
/// createNodeForCast - Handle the various forms of casts that we support.
///
SCEVHandle ScalarEvolutionsImpl::createNodeForCast(CastInst *CI) {
const Type *SrcTy = CI->getOperand(0)->getType();
const Type *DestTy = CI->getType();
// If this is a noop cast (ie, conversion from int to uint), ignore it.
if (SrcTy->isLosslesslyConvertibleTo(DestTy))
return getSCEV(CI->getOperand(0));
if (SrcTy->isInteger() && DestTy->isInteger()) {
// Otherwise, if this is a truncating integer cast, we can represent this
// cast.
if (SrcTy->getPrimitiveSize() > DestTy->getPrimitiveSize())
return SCEVTruncateExpr::get(getSCEV(CI->getOperand(0)),
CI->getType()->getUnsignedVersion());
if (SrcTy->isUnsigned() &&
SrcTy->getPrimitiveSize() <= DestTy->getPrimitiveSize())
return SCEVZeroExtendExpr::get(getSCEV(CI->getOperand(0)),
CI->getType()->getUnsignedVersion());
}
// If this is an sign or zero extending cast and we can prove that the value
// will never overflow, we could do similar transformations.
// Otherwise, we can't handle this cast!
return SCEVUnknown::get(CI);
}
/// createSCEV - We know that there is no SCEV for the specified value.
/// Analyze the expression.
@ -1401,8 +1369,21 @@ SCEVHandle ScalarEvolutionsImpl::createSCEV(Value *V) {
}
break;
case Instruction::Cast:
return createNodeForCast(cast<CastInst>(I));
case Instruction::Trunc:
if (I->getType()->isInteger() && I->getOperand(0)->getType()->isInteger())
return SCEVTruncateExpr::get(getSCEV(I->getOperand(0)),
I->getType()->getUnsignedVersion());
break;
case Instruction::ZExt:
if (I->getType()->isInteger() && I->getOperand(0)->getType()->isInteger())
return SCEVZeroExtendExpr::get(getSCEV(I->getOperand(0)),
I->getType()->getUnsignedVersion());
break;
case Instruction::BitCast:
// BitCasts are no-op casts so we just eliminate the cast.
return getSCEV(I->getOperand(0));
case Instruction::PHI:
return createNodeForPHI(cast<PHINode>(I));
@ -1724,9 +1705,10 @@ static Constant *ConstantFold(const Instruction *I,
if (isa<BinaryOperator>(I) || isa<ShiftInst>(I))
return ConstantExpr::get(I->getOpcode(), Operands[0], Operands[1]);
if (isa<CastInst>(I))
return ConstantExpr::getCast(I->getOpcode(), Operands[0], I->getType());
switch (I->getOpcode()) {
case Instruction::Cast:
return ConstantExpr::getCast(Operands[0], I->getType());
case Instruction::Select:
return ConstantExpr::getSelect(Operands[0], Operands[1], Operands[2]);
case Instruction::Call:
@ -1734,7 +1716,6 @@ static Constant *ConstantFold(const Instruction *I,
Operands.erase(Operands.begin());
return ConstantFoldCall(cast<Function>(GV), Operands);
}
return 0;
case Instruction::GetElementPtr:
Constant *Base = Operands[0];

View File

@ -30,8 +30,7 @@ Value *SCEVExpander::InsertCastOfTo(Value *V, const Type *Ty) {
UI != E; ++UI) {
if ((*UI)->getType() == Ty)
if (CastInst *CI = dyn_cast<CastInst>(cast<Instruction>(*UI))) {
// If the cast isn't in the first instruction of the function,
// move it.
// If the cast isn't the first instruction of the function, move it.
if (BasicBlock::iterator(CI) !=
A->getParent()->getEntryBlock().begin()) {
CI->moveBefore(A->getParent()->getEntryBlock().begin());
@ -39,8 +38,8 @@ Value *SCEVExpander::InsertCastOfTo(Value *V, const Type *Ty) {
return CI;
}
}
return new CastInst(V, Ty, V->getName(),
A->getParent()->getEntryBlock().begin());
return CastInst::createInferredCast(V, Ty, V->getName(),
A->getParent()->getEntryBlock().begin());
}
Instruction *I = cast<Instruction>(V);
@ -65,7 +64,7 @@ Value *SCEVExpander::InsertCastOfTo(Value *V, const Type *Ty) {
if (InvokeInst *II = dyn_cast<InvokeInst>(I))
IP = II->getNormalDest()->begin();
while (isa<PHINode>(IP)) ++IP;
return new CastInst(V, Ty, V->getName(), IP);
return CastInst::createInferredCast(V, Ty, V->getName(), IP);
}
Value *SCEVExpander::visitMulExpr(SCEVMulExpr *S) {

View File

@ -113,8 +113,10 @@ void BVNImpl::visitCastInst(CastInst &CI) {
for (Value::use_iterator UI = Op->use_begin(), UE = Op->use_end();
UI != UE; ++UI)
if (CastInst *Other = dyn_cast<CastInst>(*UI))
// Check that the types are the same, since this code handles casts...
if (Other->getType() == I.getType() &&
// Check that the opcode is the same
if (Other->getOpcode() == Instruction::CastOps(I.getOpcode()) &&
// Check that the destination types are the same
Other->getType() == I.getType() &&
// Is it embedded in the same function? (This could be false if LHS
// is a constant or global!)
Other->getParent()->getParent() == F &&

File diff suppressed because it is too large Load Diff

View File

@ -288,7 +288,19 @@ setge { RET_TOK(BinaryOpVal, SetGE, SETGE); }
phi { RET_TOK(OtherOpVal, PHI, PHI_TOK); }
call { RET_TOK(OtherOpVal, Call, CALL); }
cast { RET_TOK(OtherOpVal, Cast, CAST); }
cast { RET_TOK_OBSOLETE(CastOpVal, Trunc, TRUNC); }
trunc { RET_TOK(CastOpVal, Trunc, TRUNC); }
zext { RET_TOK(CastOpVal, ZExt, ZEXT); }
sext { RET_TOK(CastOpVal, SExt, SEXT); }
fptrunc { RET_TOK(CastOpVal, FPTrunc, FPTRUNC); }
fpext { RET_TOK(CastOpVal, FPExt, FPEXT); }
uitofp { RET_TOK(CastOpVal, UIToFP, UITOFP); }
sitofp { RET_TOK(CastOpVal, SIToFP, SITOFP); }
fptoui { RET_TOK(CastOpVal, FPToUI, FPTOUI); }
fptosi { RET_TOK(CastOpVal, FPToSI, FPTOSI); }
inttoptr { RET_TOK(CastOpVal, IntToPtr, INTTOPTR); }
ptrtoint { RET_TOK(CastOpVal, PtrToInt, PTRTOINT); }
bitcast { RET_TOK(CastOpVal, BitCast, BITCAST); }
select { RET_TOK(OtherOpVal, Select, SELECT); }
shl { RET_TOK(OtherOpVal, Shl, SHL); }
shr { RET_TOK_OBSOLETE(OtherOpVal, LShr, LSHR); }

View File

@ -51,6 +51,17 @@ void set_scan_string (const char * str) {
llvmAsmlval.type.obsolete = true; \
return sym
// Construct a token value for a non-obsolete type
#define RET_TY(CType, sym) \
llvmAsmlval.TypeVal.type = new PATypeHolder(CType); \
llvmAsmlval.TypeVal.signedness = isSignless; \
return sym
// Construct a token value for an obsolete token
#define RET_TY_OBSOLETE(CType, sign, sym) \
llvmAsmlval.TypeVal.type = new PATypeHolder(CType); \
llvmAsmlval.TypeVal.signedness = sign; \
return sym
namespace llvm {
@ -238,19 +249,19 @@ coldcc { return COLDCC_TOK; }
x86_stdcallcc { return X86_STDCALLCC_TOK; }
x86_fastcallcc { return X86_FASTCALLCC_TOK; }
void { llvmAsmlval.PrimType = Type::VoidTy ; return VOID; }
bool { llvmAsmlval.PrimType = Type::BoolTy ; return BOOL; }
sbyte { llvmAsmlval.PrimType = Type::SByteTy ; return SBYTE; }
ubyte { llvmAsmlval.PrimType = Type::UByteTy ; return UBYTE; }
short { llvmAsmlval.PrimType = Type::ShortTy ; return SHORT; }
ushort { llvmAsmlval.PrimType = Type::UShortTy; return USHORT; }
int { llvmAsmlval.PrimType = Type::IntTy ; return INT; }
uint { llvmAsmlval.PrimType = Type::UIntTy ; return UINT; }
long { llvmAsmlval.PrimType = Type::LongTy ; return LONG; }
ulong { llvmAsmlval.PrimType = Type::ULongTy ; return ULONG; }
float { llvmAsmlval.PrimType = Type::FloatTy ; return FLOAT; }
double { llvmAsmlval.PrimType = Type::DoubleTy; return DOUBLE; }
label { llvmAsmlval.PrimType = Type::LabelTy ; return LABEL; }
void { RET_TY(Type::VoidTy, VOID); }
bool { RET_TY(Type::BoolTy, BOOL); }
sbyte { RET_TY_OBSOLETE(Type::SByteTy, isSigned, SBYTE); }
ubyte { RET_TY_OBSOLETE(Type::UByteTy, isUnsigned, UBYTE); }
short { RET_TY_OBSOLETE(Type::ShortTy, isSigned, SHORT); }
ushort { RET_TY_OBSOLETE(Type::UShortTy,isUnsigned, USHORT); }
int { RET_TY_OBSOLETE(Type::IntTy, isSigned, INT); }
uint { RET_TY_OBSOLETE(Type::UIntTy, isUnsigned, UINT); }
long { RET_TY_OBSOLETE(Type::LongTy, isSigned, LONG); }
ulong { RET_TY_OBSOLETE(Type::ULongTy, isUnsigned, ULONG); }
float { RET_TY(Type::FloatTy, FLOAT); }
double { RET_TY(Type::DoubleTy, DOUBLE); }
label { RET_TY(Type::LabelTy, LABEL); }
type { return TYPE; }
opaque { return OPAQUE; }
@ -277,10 +288,24 @@ setge { RET_TOK(BinaryOpVal, SetGE, SETGE); }
phi { RET_TOK(OtherOpVal, PHI, PHI_TOK); }
call { RET_TOK(OtherOpVal, Call, CALL); }
cast { RET_TOK(OtherOpVal, Cast, CAST); }
cast { RET_TOK_OBSOLETE(CastOpVal, Trunc, TRUNC); }
trunc { RET_TOK(CastOpVal, Trunc, TRUNC); }
zext { RET_TOK(CastOpVal, ZExt, ZEXT); }
sext { RET_TOK(CastOpVal, SExt, SEXT); }
fptrunc { RET_TOK(CastOpVal, FPTrunc, FPTRUNC); }
fpext { RET_TOK(CastOpVal, FPExt, FPEXT); }
uitofp { RET_TOK(CastOpVal, UIToFP, UITOFP); }
sitofp { RET_TOK(CastOpVal, SIToFP, SITOFP); }
fptoui { RET_TOK(CastOpVal, FPToUI, FPTOUI); }
fptosi { RET_TOK(CastOpVal, FPToSI, FPTOSI); }
inttoptr { RET_TOK(CastOpVal, IntToPtr, INTTOPTR); }
ptrtoint { RET_TOK(CastOpVal, PtrToInt, PTRTOINT); }
bitcast { RET_TOK(CastOpVal, BitCast, BITCAST); }
select { RET_TOK(OtherOpVal, Select, SELECT); }
shl { RET_TOK(OtherOpVal, Shl, SHL); }
shr { RET_TOK(OtherOpVal, Shr, SHR); }
shr { RET_TOK_OBSOLETE(OtherOpVal, LShr, LSHR); }
lshr { RET_TOK(OtherOpVal, LShr, LSHR); }
ashr { RET_TOK(OtherOpVal, AShr, ASHR); }
vanext { return VANEXT_old; }
vaarg { return VAARG_old; }
va_arg { RET_TOK(OtherOpVal, VAArg , VAARG); }

View File

@ -212,10 +212,11 @@ struct OpcodeInfo {
Enum opcode;
bool obsolete;
};
typedef OpcodeInfo<llvm::Instruction::BinaryOps> BinaryOpInfo;
typedef OpcodeInfo<llvm::Instruction::TermOps> TermOpInfo;
typedef OpcodeInfo<llvm::Instruction::MemoryOps> MemOpInfo;
typedef OpcodeInfo<llvm::Instruction::OtherOps> OtherOpInfo;
typedef OpcodeInfo<llvm::Instruction::BinaryOps> BinaryOpInfo;
typedef OpcodeInfo<llvm::Instruction::TermOps> TermOpInfo;
typedef OpcodeInfo<llvm::Instruction::MemoryOps> MemOpInfo;
typedef OpcodeInfo<llvm::Instruction::CastOps> CastOpInfo;
typedef OpcodeInfo<llvm::Instruction::OtherOps> OtherOpInfo;
/// This enumeration is used to indicate if a type is signed, signless or
/// unsigned. It is used for backwards compatibility with assembly code that

File diff suppressed because it is too large Load Diff

View File

@ -128,18 +128,29 @@
LOAD = 354,
STORE = 355,
GETELEMENTPTR = 356,
PHI_TOK = 357,
CAST = 358,
SELECT = 359,
SHL = 360,
LSHR = 361,
ASHR = 362,
VAARG = 363,
EXTRACTELEMENT = 364,
INSERTELEMENT = 365,
SHUFFLEVECTOR = 366,
VAARG_old = 367,
VANEXT_old = 368
TRUNC = 357,
ZEXT = 358,
SEXT = 359,
FPTRUNC = 360,
FPEXT = 361,
BITCAST = 362,
UITOFP = 363,
SITOFP = 364,
FPTOUI = 365,
FPTOSI = 366,
INTTOPTR = 367,
PTRTOINT = 368,
PHI_TOK = 369,
SELECT = 370,
SHL = 371,
LSHR = 372,
ASHR = 373,
VAARG = 374,
EXTRACTELEMENT = 375,
INSERTELEMENT = 376,
SHUFFLEVECTOR = 377,
VAARG_old = 378,
VANEXT_old = 379
};
#endif
/* Tokens. */
@ -242,40 +253,50 @@
#define LOAD 354
#define STORE 355
#define GETELEMENTPTR 356
#define PHI_TOK 357
#define CAST 358
#define SELECT 359
#define SHL 360
#define LSHR 361
#define ASHR 362
#define VAARG 363
#define EXTRACTELEMENT 364
#define INSERTELEMENT 365
#define SHUFFLEVECTOR 366
#define VAARG_old 367
#define VANEXT_old 368
#define TRUNC 357
#define ZEXT 358
#define SEXT 359
#define FPTRUNC 360
#define FPEXT 361
#define BITCAST 362
#define UITOFP 363
#define SITOFP 364
#define FPTOUI 365
#define FPTOSI 366
#define INTTOPTR 367
#define PTRTOINT 368
#define PHI_TOK 369
#define SELECT 370
#define SHL 371
#define LSHR 372
#define ASHR 373
#define VAARG 374
#define EXTRACTELEMENT 375
#define INSERTELEMENT 376
#define SHUFFLEVECTOR 377
#define VAARG_old 378
#define VANEXT_old 379
#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
#line 1040 "/proj/llvm/llvm-3/lib/AsmParser/llvmAsmParser.y"
#line 1040 "/proj/llvm/llvm-1/lib/AsmParser/llvmAsmParser.y"
typedef union YYSTYPE {
llvm::Module *ModuleVal;
llvm::Function *FunctionVal;
std::pair<llvm::PATypeHolder*, char*> *ArgVal;
std::pair<TypeInfo, char*> *ArgVal;
llvm::BasicBlock *BasicBlockVal;
llvm::TerminatorInst *TermInstVal;
llvm::Instruction *InstVal;
llvm::Constant *ConstVal;
const llvm::Type *PrimType;
llvm::PATypeHolder *TypeVal;
TypeInfo TypeVal;
llvm::Value *ValueVal;
std::vector<std::pair<llvm::PATypeHolder*,char*> > *ArgList;
std::vector<std::pair<TypeInfo,char*> >*ArgList;
std::vector<llvm::Value*> *ValueList;
std::list<llvm::PATypeHolder> *TypeList;
std::list<TypeInfo> *TypeList;
// Represent the RHS of PHI node
std::list<std::pair<llvm::Value*,
llvm::BasicBlock*> > *PHIList;
@ -296,11 +317,12 @@ typedef union YYSTYPE {
BinaryOpInfo BinaryOpVal;
TermOpInfo TermOpVal;
MemOpInfo MemOpVal;
CastOpInfo CastOpVal;
OtherOpInfo OtherOpVal;
llvm::Module::Endianness Endianness;
} YYSTYPE;
/* Line 1447 of yacc.c. */
#line 304 "llvmAsmParser.tab.h"
#line 326 "llvmAsmParser.tab.h"
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
# define YYSTYPE_IS_TRIVIAL 1

View File

@ -824,14 +824,14 @@ static PATypeHolder HandleUpRefs(const Type *ty) {
/// instruction. This function handles converting div -> [usf]div appropriately.
/// @brief Convert obsolete BinaryOps opcodes to new values
static void
sanitizeOpCode(OpcodeInfo<Instruction::BinaryOps> &OI, const Type *Ty)
sanitizeOpcode(OpcodeInfo<Instruction::BinaryOps> &OI, const Type *Ty)
{
// If its not obsolete, don't do anything
if (!OI.obsolete)
return;
// If its a packed type we want to use the element type
if (const PackedType* PTy = dyn_cast<PackedType>(Ty))
if (const PackedType *PTy = dyn_cast<PackedType>(Ty))
Ty = PTy->getElementType();
// Depending on the opcode ..
@ -857,11 +857,11 @@ sanitizeOpCode(OpcodeInfo<Instruction::BinaryOps> &OI, const Type *Ty)
OI.obsolete = false;
}
/// This function is similar to the previous overload of sanitizeOpCode but
/// This function is similar to the previous overload of sanitizeOpcode but
/// operates on Instruction::OtherOps instead of Instruction::BinaryOps.
/// @brief Convert obsolete OtherOps opcodes to new values
static void
sanitizeOpCode(OpcodeInfo<Instruction::OtherOps> &OI, const Type *Ty)
sanitizeOpcode(OpcodeInfo<Instruction::OtherOps> &OI, const Type *Ty)
{
// If its not obsolete, don't do anything
if (!OI.obsolete)
@ -1072,6 +1072,7 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
BinaryOpInfo BinaryOpVal;
TermOpInfo TermOpVal;
MemOpInfo MemOpVal;
CastOpInfo CastOpVal;
OtherOpInfo OtherOpVal;
llvm::Module::Endianness Endianness;
}
@ -1147,9 +1148,14 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
// Memory Instructions
%token <MemOpVal> MALLOC ALLOCA FREE LOAD STORE GETELEMENTPTR
// Cast Operators
%type <CastOpVal> CastOps
%token <CastOpVal> TRUNC ZEXT SEXT FPTRUNC FPEXT BITCAST
%token <CastOpVal> UITOFP SITOFP FPTOUI FPTOSI INTTOPTR PTRTOINT
// Other Operators
%type <OtherOpVal> ShiftOps
%token <OtherOpVal> PHI_TOK CAST SELECT SHL LSHR ASHR VAARG
%token <OtherOpVal> PHI_TOK SELECT SHL LSHR ASHR VAARG
%token <OtherOpVal> EXTRACTELEMENT INSERTELEMENT SHUFFLEVECTOR
%token VAARG_old VANEXT_old //OBSOLETE
@ -1182,8 +1188,9 @@ EINT64VAL : EUINT64VAL {
ArithmeticOps: ADD | SUB | MUL | UDIV | SDIV | FDIV | UREM | SREM | FREM;
LogicalOps : AND | OR | XOR;
SetCondOps : SETLE | SETGE | SETLT | SETGT | SETEQ | SETNE;
ShiftOps : SHL | LSHR | ASHR;
CastOps : TRUNC | ZEXT | SEXT | FPTRUNC | FPEXT | BITCAST |
UITOFP | SITOFP | FPTOUI | FPTOSI | INTTOPTR | PTRTOINT;
ShiftOps : SHL | LSHR | ASHR;
// These are some types that allow classification if we only want a particular
// thing... for example, only a signed, unsigned, or integral type.
@ -1676,16 +1683,31 @@ ConstVal : SIntType EINT64VAL { // integral constants
};
ConstExpr: CAST '(' ConstVal TO Types ')' {
if (!$3->getType()->isFirstClassType())
ConstExpr: CastOps '(' ConstVal TO Types ')' {
Constant *Val = $3;
const Type *Ty = $5.type->get();
if (!Val->getType()->isFirstClassType())
GEN_ERROR("cast constant expression from a non-primitive type: '" +
$3->getType()->getDescription() + "'!");
if (!$5.type->get()->isFirstClassType())
Val->getType()->getDescription() + "'!");
if (!Ty->isFirstClassType())
GEN_ERROR("cast constant expression to a non-primitive type: '" +
$5.type->get()->getDescription() + "'!");
$$ = ConstantExpr::getCast($3, $5.type->get());
Ty->getDescription() + "'!");
if ($1.obsolete) {
if (Ty == Type::BoolTy) {
// The previous definition of cast to bool was a compare against zero.
// We have to retain that semantic so we do it here.
$$ = ConstantExpr::get(Instruction::SetNE, Val,
Constant::getNullValue(Val->getType()));
} else if (Val->getType()->isFloatingPoint() && isa<PointerType>(Ty)) {
Constant *CE = ConstantExpr::getFPToUI(Val, Type::ULongTy);
$$ = ConstantExpr::getIntToPtr(CE, Ty);
} else {
$$ = ConstantExpr::getCast(Val, Ty);
}
} else {
$$ = ConstantExpr::getCast($1.opcode, $3, $5.type->get());
}
delete $5.type;
CHECK_FOR_ERROR
}
| GETELEMENTPTR '(' ConstVal IndexList ')' {
if (!isa<PointerType>($3->getType()))
@ -1732,7 +1754,7 @@ ConstExpr: CAST '(' ConstVal TO Types ')' {
GEN_ERROR("Binary operator types must match!");
// First, make sure we're dealing with the right opcode by upgrading from
// obsolete versions.
sanitizeOpCode($1,$3->getType());
sanitizeOpcode($1, $3->getType());
CHECK_FOR_ERROR;
// HACK: llvm 1.3 and earlier used to emit invalid pointer constant exprs.
@ -1777,7 +1799,7 @@ ConstExpr: CAST '(' ConstVal TO Types ')' {
if (!$3->getType()->isInteger())
GEN_ERROR("Shift constant expression requires integer operand!");
// Handle opcode upgrade situations
sanitizeOpCode($1, $3->getType());
sanitizeOpcode($1, $3->getType());
CHECK_FOR_ERROR;
$$ = ConstantExpr::get($1.opcode, $3, $5);
CHECK_FOR_ERROR
@ -2296,6 +2318,10 @@ BasicBlock : InstructionList OptAssign BBTerminatorInst {
};
InstructionList : InstructionList Inst {
if (CastInst *CI1 = dyn_cast<CastInst>($2))
if (CastInst *CI2 = dyn_cast<CastInst>(CI1->getOperand(0)))
if (CI2->getParent() == 0)
$1->getInstList().push_back(CI2);
$1->getInstList().push_back($2);
$$ = $1;
CHECK_FOR_ERROR
@ -2527,7 +2553,7 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
$1.opcode == Instruction::FRem))
GEN_ERROR("U/S/FRem not supported on packed types!");
// Upgrade the opcode from obsolete versions before we do anything with it.
sanitizeOpCode($1,$2.type->get());
sanitizeOpcode($1,$2.type->get());
CHECK_FOR_ERROR;
Value* val1 = getVal($2.type->get(), $3);
CHECK_FOR_ERROR
@ -2586,18 +2612,36 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
if (!$2->getType()->isInteger())
GEN_ERROR("Shift constant expression requires integer operand!");
// Handle opcode upgrade situations
sanitizeOpCode($1, $2->getType());
sanitizeOpcode($1, $2->getType());
CHECK_FOR_ERROR;
$$ = new ShiftInst($1.opcode, $2, $4);
CHECK_FOR_ERROR
}
| CAST ResolvedVal TO Types {
if (!$4.type->get()->isFirstClassType())
GEN_ERROR("cast instruction to a non-primitive type: '" +
$4.type->get()->getDescription() + "'!");
$$ = new CastInst($2, $4.type->get());
| CastOps ResolvedVal TO Types {
Value* Val = $2;
const Type* Ty = $4.type->get();
if (!Val->getType()->isFirstClassType())
GEN_ERROR("cast from a non-primitive type: '" +
Val->getType()->getDescription() + "'!");
if (!Ty->isFirstClassType())
GEN_ERROR("cast to a non-primitive type: '" + Ty->getDescription() +"'!");
if ($1.obsolete) {
if (Ty == Type::BoolTy) {
// The previous definition of cast to bool was a compare against zero.
// We have to retain that semantic so we do it here.
$$ = new SetCondInst(Instruction::SetNE, $2,
Constant::getNullValue($2->getType()));
} else if (Val->getType()->isFloatingPoint() && isa<PointerType>(Ty)) {
CastInst *CI = new FPToUIInst(Val, Type::ULongTy);
$$ = new IntToPtrInst(CI, Ty);
} else {
$$ = CastInst::createInferredCast(Val, Ty);
}
} else {
$$ = CastInst::create($1.opcode, $2, $4.type->get());
}
delete $4.type;
CHECK_FOR_ERROR
}
| SELECT ResolvedVal ',' ResolvedVal ',' ResolvedVal {
if ($2->getType() != Type::BoolTy)

File diff suppressed because it is too large Load Diff

View File

@ -461,24 +461,23 @@ void BytecodeReader::insertArguments(Function* F) {
insertValue(AI, getTypeSlot(AI->getType()), FunctionValues);
}
// Convert previous opcode values into the current value and/or construct
// the instruction. This function handles all *abnormal* cases for instruction
// generation based on obsolete opcode values. The normal cases are handled
// in ParseInstruction below. Generally this function just produces a new
// Opcode value (first argument). In a few cases (VAArg, VANext) the upgrade
// path requies that the instruction (sequence) be generated differently from
// the normal case in order to preserve the original semantics. In these
// cases the result of the function will be a non-zero Instruction pointer. In
// all other cases, zero will be returned indicating that the *normal*
// instruction generation should be used, but with the new Opcode value.
//
/// Convert previous opcode values into the current value and/or construct
/// the instruction. This function handles all *abnormal* cases for instruction
/// generation based on obsolete opcode values. The normal cases are handled
/// in ParseInstruction below. Generally this function just produces a new
/// Opcode value (first argument). In a few cases (VAArg, VANext) the upgrade
/// path requies that the instruction (sequence) be generated differently from
/// the normal case in order to preserve the original semantics. In these
/// cases the result of the function will be a non-zero Instruction pointer. In
/// all other cases, zero will be returned indicating that the *normal*
/// instruction generation should be used, but with the new Opcode value.
Instruction*
BytecodeReader::upgradeInstrOpcodes(
unsigned &Opcode, ///< The old opcode, possibly updated by this function
std::vector<unsigned> &Oprnds, ///< The operands to the instruction
unsigned &iType, ///< The type code from the bytecode file
const Type* InstTy, ///< The type of the instruction
BasicBlock* BB ///< The basic block to insert into, if we need to
const Type *InstTy, ///< The type of the instruction
BasicBlock *BB ///< The basic block to insert into, if we need to
) {
// First, short circuit this if no conversion is required. When signless
@ -632,8 +631,27 @@ BytecodeReader::upgradeInstrOpcodes(
Opcode = Instruction::PHI;
break;
case 28: // Cast
Opcode = Instruction::Cast;
{
Value *Source = getValue(iType, Oprnds[0]);
const Type *DestTy = getType(Oprnds[1]);
// The previous definition of cast to bool was a compare against zero.
// We have to retain that semantic so we do it here.
if (DestTy == Type::BoolTy) { // if its a cast to bool
Opcode = Instruction::SetNE;
Result = new SetCondInst(Instruction::SetNE, Source,
Constant::getNullValue(Source->getType()));
} else if (Source->getType()->isFloatingPoint() &&
isa<PointerType>(DestTy)) {
// Upgrade what is now an illegal cast (fp -> ptr) into two casts,
// fp -> ui, and ui -> ptr
CastInst *CI = new FPToUIInst(Source, Type::ULongTy);
BB->getInstList().push_back(CI);
Result = new IntToPtrInst(CI, DestTy);
} else {
Result = CastInst::createInferredCast(Source, DestTy);
}
break;
}
case 29: // Call
Opcode = Instruction::Call;
break;
@ -720,8 +738,66 @@ BytecodeReader::upgradeInstrOpcodes(
case 40: // ShuffleVector
Opcode = Instruction::ShuffleVector;
break;
case 56: // Invoke with encoded CC
case 57: // Invoke Fast CC
case 56: // Invoke with encoded CC
case 57: { // Invoke Fast CC
if (Oprnds.size() < 3)
error("Invalid invoke instruction!");
Value *F = getValue(iType, Oprnds[0]);
// Check to make sure we have a pointer to function type
const PointerType *PTy = dyn_cast<PointerType>(F->getType());
if (PTy == 0)
error("Invoke to non function pointer value!");
const FunctionType *FTy = dyn_cast<FunctionType>(PTy->getElementType());
if (FTy == 0)
error("Invoke to non function pointer value!");
std::vector<Value *> Params;
BasicBlock *Normal, *Except;
unsigned CallingConv = CallingConv::C;
if (Opcode == 57)
CallingConv = CallingConv::Fast;
else if (Opcode == 56) {
CallingConv = Oprnds.back();
Oprnds.pop_back();
}
Opcode = Instruction::Invoke;
if (!FTy->isVarArg()) {
Normal = getBasicBlock(Oprnds[1]);
Except = getBasicBlock(Oprnds[2]);
FunctionType::param_iterator It = FTy->param_begin();
for (unsigned i = 3, e = Oprnds.size(); i != e; ++i) {
if (It == FTy->param_end())
error("Invalid invoke instruction!");
Params.push_back(getValue(getTypeSlot(*It++), Oprnds[i]));
}
if (It != FTy->param_end())
error("Invalid invoke instruction!");
} else {
Oprnds.erase(Oprnds.begin(), Oprnds.begin()+1);
Normal = getBasicBlock(Oprnds[0]);
Except = getBasicBlock(Oprnds[1]);
unsigned FirstVariableArgument = FTy->getNumParams()+2;
for (unsigned i = 2; i != FirstVariableArgument; ++i)
Params.push_back(getValue(getTypeSlot(FTy->getParamType(i-2)),
Oprnds[i]));
// Must be type/value pairs. If not, error out.
if (Oprnds.size()-FirstVariableArgument & 1)
error("Invalid invoke instruction!");
for (unsigned i = FirstVariableArgument; i < Oprnds.size(); i += 2)
Params.push_back(getValue(Oprnds[i], Oprnds[i+1]));
}
Result = new InvokeInst(F, Normal, Except, Params);
if (CallingConv) cast<InvokeInst>(Result)->setCallingConv(CallingConv);
break;
}
case 58: // Call with extra operand for calling conv
case 59: // tail call, Fast CC
case 60: // normal call, Fast CC
@ -889,12 +965,78 @@ void BytecodeReader::ParseInstruction(std::vector<unsigned> &Oprnds,
Result = new ShuffleVectorInst(V1, V2, V3);
break;
}
case Instruction::Cast:
case Instruction::Trunc:
if (Oprnds.size() != 2)
error("Invalid cast instruction!");
Result = new TruncInst(getValue(iType, Oprnds[0]),
getType(Oprnds[1]));
break;
case Instruction::ZExt:
if (Oprnds.size() != 2)
error("Invalid cast instruction!");
Result = new ZExtInst(getValue(iType, Oprnds[0]),
getType(Oprnds[1]));
break;
case Instruction::SExt:
if (Oprnds.size() != 2)
error("Invalid Cast instruction!");
Result = new CastInst(getValue(iType, Oprnds[0]),
Result = new SExtInst(getValue(iType, Oprnds[0]),
getType(Oprnds[1]));
break;
case Instruction::FPTrunc:
if (Oprnds.size() != 2)
error("Invalid cast instruction!");
Result = new FPTruncInst(getValue(iType, Oprnds[0]),
getType(Oprnds[1]));
break;
case Instruction::FPExt:
if (Oprnds.size() != 2)
error("Invalid cast instruction!");
Result = new FPExtInst(getValue(iType, Oprnds[0]),
getType(Oprnds[1]));
break;
case Instruction::UIToFP:
if (Oprnds.size() != 2)
error("Invalid cast instruction!");
Result = new UIToFPInst(getValue(iType, Oprnds[0]),
getType(Oprnds[1]));
break;
case Instruction::SIToFP:
if (Oprnds.size() != 2)
error("Invalid cast instruction!");
Result = new SIToFPInst(getValue(iType, Oprnds[0]),
getType(Oprnds[1]));
break;
case Instruction::FPToUI:
if (Oprnds.size() != 2)
error("Invalid cast instruction!");
Result = new FPToUIInst(getValue(iType, Oprnds[0]),
getType(Oprnds[1]));
break;
case Instruction::FPToSI:
if (Oprnds.size() != 2)
error("Invalid cast instruction!");
Result = new FPToSIInst(getValue(iType, Oprnds[0]),
getType(Oprnds[1]));
break;
case Instruction::IntToPtr:
if (Oprnds.size() != 2)
error("Invalid cast instruction!");
Result = new IntToPtrInst(getValue(iType, Oprnds[0]),
getType(Oprnds[1]));
break;
case Instruction::PtrToInt:
if (Oprnds.size() != 2)
error("Invalid cast instruction!");
Result = new PtrToIntInst(getValue(iType, Oprnds[0]),
getType(Oprnds[1]));
break;
case Instruction::BitCast:
if (Oprnds.size() != 2)
error("Invalid cast instruction!");
Result = new BitCastInst(getValue(iType, Oprnds[0]),
getType(Oprnds[1]));
break;
case Instruction::Select:
if (Oprnds.size() != 3)
error("Invalid Select instruction!");
@ -914,7 +1056,6 @@ void BytecodeReader::ParseInstruction(std::vector<unsigned> &Oprnds,
Result = PN;
break;
}
case Instruction::Shl:
case Instruction::LShr:
case Instruction::AShr:
@ -960,7 +1101,6 @@ void BytecodeReader::ParseInstruction(std::vector<unsigned> &Oprnds,
case Instruction::Call: { // Normal Call, C Calling Convention
if (Oprnds.size() == 0)
error("Invalid call instruction encountered!");
Value *F = getValue(iType, Oprnds[0]);
unsigned CallingConv = CallingConv::C;
@ -1021,8 +1161,6 @@ void BytecodeReader::ParseInstruction(std::vector<unsigned> &Oprnds,
if (CallingConv) cast<CallInst>(Result)->setCallingConv(CallingConv);
break;
}
case 56: // Invoke with encoded CC
case 57: // Invoke Fast CC
case Instruction::Invoke: { // Invoke C CC
if (Oprnds.size() < 3)
error("Invalid invoke instruction!");
@ -1038,14 +1176,8 @@ void BytecodeReader::ParseInstruction(std::vector<unsigned> &Oprnds,
std::vector<Value *> Params;
BasicBlock *Normal, *Except;
unsigned CallingConv = CallingConv::C;
if (Opcode == 57)
CallingConv = CallingConv::Fast;
else if (Opcode == 56) {
CallingConv = Oprnds.back();
Oprnds.pop_back();
}
unsigned CallingConv = Oprnds.back();
Oprnds.pop_back();
if (!FTy->isVarArg()) {
Normal = getBasicBlock(Oprnds[1]);
@ -1486,12 +1618,12 @@ void BytecodeReader::ParseTypes(TypeListTy &Tab, unsigned NumEntries){
// We can't use that function because of that functions argument requirements.
// This function only deals with the subset of opcodes that are applicable to
// constant expressions and is therefore simpler than upgradeInstrOpcodes.
inline unsigned BytecodeReader::upgradeCEOpcodes(
unsigned Opcode, const std::vector<Constant*> &ArgVec
inline Constant *BytecodeReader::upgradeCEOpcodes(
unsigned &Opcode, const std::vector<Constant*> &ArgVec, unsigned TypeID
) {
// Determine if no upgrade necessary
if (!hasSignlessDivRem && !hasSignlessShrCastSetcc)
return Opcode;
return 0;
// If this is bytecode version 6, that only had signed Rem and Div
// instructions, then we must compensate for those two instructions only.
@ -1587,9 +1719,25 @@ inline unsigned BytecodeReader::upgradeCEOpcodes(
case 26: // GetElementPtr
Opcode = Instruction::GetElementPtr;
break;
case 28: // Cast
Opcode = Instruction::Cast;
case 28: { // Cast
const Type *Ty = getType(TypeID);
if (Ty == Type::BoolTy) {
// The previous definition of cast to bool was a compare against zero.
// We have to retain that semantic so we do it here.
Opcode = Instruction::SetEQ;
return ConstantExpr::get(Instruction::SetEQ, ArgVec[0],
Constant::getNullValue(ArgVec[0]->getType()));
} else if (ArgVec[0]->getType()->isFloatingPoint() &&
isa<PointerType>(Ty)) {
// Upgrade what is now an illegal cast (fp -> ptr) into two casts,
// fp -> ui, and ui -> ptr
Constant *CE = ConstantExpr::getFPToUI(ArgVec[0], Type::ULongTy);
return ConstantExpr::getIntToPtr(CE, Ty);
} else {
Opcode = CastInst::getCastOpcode(ArgVec[0], Ty);
}
break;
}
case 30: // Shl
Opcode = Instruction::Shl;
break;
@ -1612,7 +1760,7 @@ inline unsigned BytecodeReader::upgradeCEOpcodes(
Opcode = Instruction::ShuffleVector;
break;
}
return Opcode;
return 0;
}
/// Parse a single constant value
@ -1663,19 +1811,22 @@ Value *BytecodeReader::ParseConstantPoolValue(unsigned TypeID) {
}
// Handle backwards compatibility for the opcode numbers
Opcode = upgradeCEOpcodes(Opcode, ArgVec);
if (Constant *C = upgradeCEOpcodes(Opcode, ArgVec, TypeID)) {
if (Handler) Handler->handleConstantExpression(Opcode, ArgVec, C);
return C;
}
// Construct a ConstantExpr of the appropriate kind
if (isExprNumArgs == 1) { // All one-operand expressions
if (Opcode != Instruction::Cast)
if (!Instruction::isCast(Opcode))
error("Only cast instruction has one argument for ConstantExpr");
Constant* Result = ConstantExpr::getCast(ArgVec[0], getType(TypeID));
Constant *Result = ConstantExpr::getCast(ArgVec[0], getType(TypeID));
if (Handler) Handler->handleConstantExpression(Opcode, ArgVec, Result);
return Result;
} else if (Opcode == Instruction::GetElementPtr) { // GetElementPtr
std::vector<Constant*> IdxList(ArgVec.begin()+1, ArgVec.end());
Constant* Result = ConstantExpr::getGetElementPtr(ArgVec[0], IdxList);
Constant *Result = ConstantExpr::getGetElementPtr(ArgVec[0], IdxList);
if (Handler) Handler->handleConstantExpression(Opcode, ArgVec, Result);
return Result;
} else if (Opcode == Instruction::Select) {

View File

@ -230,19 +230,20 @@ protected:
/// the instruction. This function handles all *abnormal* cases for
/// instruction generation based on obsolete opcode values. The normal cases
/// are handled by the ParseInstruction function.
Instruction* upgradeInstrOpcodes(
Instruction *upgradeInstrOpcodes(
unsigned &opcode, ///< The old opcode, possibly updated by this function
std::vector<unsigned> &Oprnds, ///< The operands to the instruction
unsigned &iType, ///< The type code from the bytecode file
const Type* InstTy, ///< The type of the instruction
BasicBlock* BB ///< The basic block to insert into, if we need to
const Type *InstTy, ///< The type of the instruction
BasicBlock *BB ///< The basic block to insert into, if we need to
);
/// @brief Convert previous opcode values for ConstantExpr into the current
/// value.
unsigned upgradeCEOpcodes(
unsigned Opcode, ///< Opcode read from bytecode
const std::vector<Constant*> &ArgVec ///< Arguments of instruction
Constant *upgradeCEOpcodes(
unsigned &Opcode, ///< Opcode read from bytecode
const std::vector<Constant*> &ArgVec, ///< Arguments of instruction
unsigned TypeID ///< TypeID of the instruction type
);
/// @brief Parse a single instruction.

View File

@ -291,7 +291,7 @@ void BytecodeWriter::outputConstant(const Constant *CPV) {
if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CPV)) {
// FIXME: Encoding of constant exprs could be much more compact!
assert(CE->getNumOperands() > 0 && "ConstantExpr with 0 operands");
assert(CE->getNumOperands() != 1 || CE->getOpcode() == Instruction::Cast);
assert(CE->getNumOperands() != 1 || CE->isCast());
output_vbr(1+CE->getNumOperands()); // flags as an expr
output_vbr(CE->getOpcode()); // Put out the CE op code
@ -446,8 +446,8 @@ void BytecodeWriter::outputInstructionFormat0(const Instruction *I,
output_typeid(Type); // Result type
unsigned NumArgs = I->getNumOperands();
output_vbr(NumArgs + (isa<CastInst>(I) ||
isa<VAArgInst>(I) || Opcode == 56 || Opcode == 58));
output_vbr(NumArgs + (isa<CastInst>(I) || isa<InvokeInst>(I) ||
isa<VAArgInst>(I) || Opcode == 58));
if (!isa<GetElementPtrInst>(&I)) {
for (unsigned i = 0; i < NumArgs; ++i) {
@ -460,7 +460,7 @@ void BytecodeWriter::outputInstructionFormat0(const Instruction *I,
int Slot = Table.getSlot(I->getType());
assert(Slot != -1 && "Cast return type unknown?");
output_typeid((unsigned)Slot);
} else if (Opcode == 56) { // Invoke escape sequence
} else if (isa<InvokeInst>(I)) {
output_vbr(cast<InvokeInst>(I)->getCallingConv());
} else if (Opcode == 58) { // Call escape sequence
output_vbr((cast<CallInst>(I)->getCallingConv() << 1) |
@ -528,8 +528,8 @@ void BytecodeWriter::outputInstrVarArgsCall(const Instruction *I,
// variable argument.
NumFixedOperands = 3+NumParams;
}
output_vbr(2 * I->getNumOperands()-NumFixedOperands +
unsigned(Opcode == 56 || Opcode == 58));
output_vbr(2 * I->getNumOperands()-NumFixedOperands +
unsigned(Opcode == 58 || isa<InvokeInst>(I)));
// The type for the function has already been emitted in the type field of the
// instruction. Just emit the slot # now.
@ -551,12 +551,12 @@ void BytecodeWriter::outputInstrVarArgsCall(const Instruction *I,
output_vbr((unsigned)Slot);
}
// If this is the escape sequence for call, emit the tailcall/cc info.
if (Opcode == 58) {
if (isa<InvokeInst>(I)) {
// Emit the tail call/calling conv for invoke instructions
output_vbr(cast<InvokeInst>(I)->getCallingConv());
} else if (Opcode == 58) {
const CallInst *CI = cast<CallInst>(I);
output_vbr((CI->getCallingConv() << 1) | unsigned(CI->isTailCall()));
} else if (Opcode == 56) { // Invoke escape sequence.
output_vbr(cast<InvokeInst>(I)->getCallingConv());
}
}
@ -619,7 +619,7 @@ inline void BytecodeWriter::outputInstructionFormat3(const Instruction *I,
}
void BytecodeWriter::outputInstruction(const Instruction &I) {
assert(I.getOpcode() < 56 && "Opcode too big???");
assert(I.getOpcode() < 57 && "Opcode too big???");
unsigned Opcode = I.getOpcode();
unsigned NumOperands = I.getNumOperands();
@ -639,12 +639,6 @@ void BytecodeWriter::outputInstruction(const Instruction &I) {
} else {
Opcode = 58; // Call escape sequence.
}
} else if (const InvokeInst *II = dyn_cast<InvokeInst>(&I)) {
if (II->getCallingConv() == CallingConv::Fast)
Opcode = 57; // FastCC invoke.
else if (II->getCallingConv() != CallingConv::C)
Opcode = 56; // Invoke escape sequence.
} else if (isa<LoadInst>(I) && cast<LoadInst>(I).isVolatile()) {
Opcode = 62;
} else if (isa<StoreInst>(I) && cast<StoreInst>(I).isVolatile()) {
@ -750,7 +744,7 @@ void BytecodeWriter::outputInstruction(const Instruction &I) {
if (Slots[NumOperands-1] > MaxOpSlot)
MaxOpSlot = Slots[NumOperands-1];
}
} else if (Opcode == 56) {
} else if (isa<InvokeInst>(I)) {
// Invoke escape seq has at least 4 operands to encode.
++NumOperands;
}

View File

@ -423,7 +423,20 @@ void AsmPrinter::EmitConstantValueOnly(const Constant *CV) {
}
break;
}
case Instruction::Cast: {
case Instruction::Trunc:
case Instruction::ZExt:
case Instruction::SExt:
case Instruction::FPTrunc:
case Instruction::FPExt:
case Instruction::UIToFP:
case Instruction::SIToFP:
case Instruction::FPToUI:
case Instruction::FPToSI:
assert(0 && "FIXME: Don't yet support this kind of constant cast expr");
break;
case Instruction::IntToPtr:
case Instruction::PtrToInt:
case Instruction::BitCast: {
// Support only foldable casts to/from pointers that can be eliminated by
// changing the pointer to the appropriately sized integer type.
Constant *Op = CE->getOperand(0);

View File

@ -40,6 +40,7 @@ static Function *EnsureFunctionExists(Module &M, const char *Name,
template <class ArgIt>
static CallInst *ReplaceCallWith(const char *NewFn, CallInst *CI,
ArgIt ArgBegin, ArgIt ArgEnd,
const unsigned *castOpcodes,
const Type *RetTy, Function *&FCache) {
if (!FCache) {
// If we haven't already looked up this function, check to see if the
@ -63,7 +64,12 @@ static CallInst *ReplaceCallWith(const char *NewFn, CallInst *CI,
++I, ++ArgNo) {
Value *Arg = *I;
if (Arg->getType() != FT->getParamType(ArgNo))
Arg = new CastInst(Arg, FT->getParamType(ArgNo), Arg->getName(), CI);
if (castOpcodes[ArgNo])
Arg = CastInst::create(Instruction::CastOps(castOpcodes[ArgNo]),
Arg, FT->getParamType(ArgNo), Arg->getName(), CI);
else
Arg = CastInst::createInferredCast(Arg, FT->getParamType(ArgNo),
Arg->getName(), CI);
Operands.push_back(Arg);
}
// Pass nulls into any additional arguments...
@ -76,7 +82,7 @@ static CallInst *ReplaceCallWith(const char *NewFn, CallInst *CI,
if (!CI->use_empty()) {
Value *V = NewCI;
if (CI->getType() != NewCI->getType())
V = new CastInst(NewCI, CI->getType(), Name, CI);
V = CastInst::createInferredCast(NewCI, CI->getType(), Name, CI);
CI->replaceAllUsesWith(V);
}
return NewCI;
@ -283,8 +289,9 @@ void IntrinsicLowering::LowerIntrinsicCall(CallInst *CI) {
// convert the call to an explicit setjmp or longjmp call.
case Intrinsic::setjmp: {
static Function *SetjmpFCache = 0;
static const unsigned castOpcodes[] = { Instruction::BitCast };
Value *V = ReplaceCallWith("setjmp", CI, CI->op_begin()+1, CI->op_end(),
Type::IntTy, SetjmpFCache);
castOpcodes, Type::IntTy, SetjmpFCache);
if (CI->getType() != Type::VoidTy)
CI->replaceAllUsesWith(V);
break;
@ -296,16 +303,20 @@ void IntrinsicLowering::LowerIntrinsicCall(CallInst *CI) {
case Intrinsic::longjmp: {
static Function *LongjmpFCache = 0;
static const unsigned castOpcodes[] =
{ Instruction::BitCast, 0 };
ReplaceCallWith("longjmp", CI, CI->op_begin()+1, CI->op_end(),
Type::VoidTy, LongjmpFCache);
castOpcodes, Type::VoidTy, LongjmpFCache);
break;
}
case Intrinsic::siglongjmp: {
// Insert the call to abort
static Function *AbortFCache = 0;
ReplaceCallWith("abort", CI, CI->op_end(), CI->op_end(), Type::VoidTy,
AbortFCache);
static const unsigned castOpcodes[] =
{ Instruction::BitCast, 0 };
ReplaceCallWith("abort", CI, CI->op_end(), CI->op_end(),
castOpcodes, Type::VoidTy, AbortFCache);
break;
}
case Intrinsic::ctpop_i8:
@ -383,31 +394,76 @@ void IntrinsicLowering::LowerIntrinsicCall(CallInst *CI) {
case Intrinsic::dbg_declare:
break; // Simply strip out debugging intrinsics
case Intrinsic::memcpy_i32:
case Intrinsic::memcpy_i64: {
case Intrinsic::memcpy_i32: {
// The memcpy intrinsic take an extra alignment argument that the memcpy
// libc function does not.
static unsigned opcodes[] =
{ Instruction::BitCast, Instruction::BitCast, Instruction::BitCast };
// FIXME:
// if (target_is_64_bit) opcodes[2] = Instruction::ZExt;
// else opcodes[2] = Instruction::BitCast;
static Function *MemcpyFCache = 0;
ReplaceCallWith("memcpy", CI, CI->op_begin()+1, CI->op_end()-1,
(*(CI->op_begin()+1))->getType(), MemcpyFCache);
opcodes, (*(CI->op_begin()+1))->getType(), MemcpyFCache);
break;
}
case Intrinsic::memcpy_i64: {
static unsigned opcodes[] =
{ Instruction::BitCast, Instruction::BitCast, Instruction::Trunc };
// FIXME:
// if (target_is_64_bit) opcodes[2] = Instruction::BitCast;
// else opcodes[2] = Instruction::Trunc;
static Function *MemcpyFCache = 0;
ReplaceCallWith("memcpy", CI, CI->op_begin()+1, CI->op_end()-1,
opcodes, (*(CI->op_begin()+1))->getType(), MemcpyFCache);
break;
}
case Intrinsic::memmove_i32: {
// The memmove intrinsic take an extra alignment argument that the memmove
// libc function does not.
static unsigned opcodes[] =
{ Instruction::BitCast, Instruction::BitCast, Instruction::BitCast };
// FIXME:
// if (target_is_64_bit) opcodes[2] = Instruction::ZExt;
// else opcodes[2] = Instruction::BitCast;
static Function *MemmoveFCache = 0;
ReplaceCallWith("memmove", CI, CI->op_begin()+1, CI->op_end()-1,
opcodes, (*(CI->op_begin()+1))->getType(), MemmoveFCache);
break;
}
case Intrinsic::memmove_i32:
case Intrinsic::memmove_i64: {
// The memmove intrinsic take an extra alignment argument that the memmove
// libc function does not.
static const unsigned opcodes[] =
{ Instruction::BitCast, Instruction::BitCast, Instruction::Trunc };
// if (target_is_64_bit) opcodes[2] = Instruction::BitCast;
// else opcodes[2] = Instruction::Trunc;
static Function *MemmoveFCache = 0;
ReplaceCallWith("memmove", CI, CI->op_begin()+1, CI->op_end()-1,
(*(CI->op_begin()+1))->getType(), MemmoveFCache);
opcodes, (*(CI->op_begin()+1))->getType(), MemmoveFCache);
break;
}
case Intrinsic::memset_i32:
case Intrinsic::memset_i32: {
// The memset intrinsic take an extra alignment argument that the memset
// libc function does not.
static const unsigned opcodes[] =
{ Instruction::BitCast, Instruction::ZExt, Instruction::ZExt, 0 };
// if (target_is_64_bit) opcodes[2] = Instruction::BitCast;
// else opcodes[2] = Instruction::ZExt;
static Function *MemsetFCache = 0;
ReplaceCallWith("memset", CI, CI->op_begin()+1, CI->op_end()-1,
opcodes, (*(CI->op_begin()+1))->getType(), MemsetFCache);
}
case Intrinsic::memset_i64: {
// The memset intrinsic take an extra alignment argument that the memset
// libc function does not.
static const unsigned opcodes[] =
{ Instruction::BitCast, Instruction::ZExt, Instruction::Trunc, 0 };
// if (target_is_64_bit) opcodes[2] = Instruction::BitCast;
// else opcodes[2] = Instruction::Trunc;
static Function *MemsetFCache = 0;
ReplaceCallWith("memset", CI, CI->op_begin()+1, CI->op_end()-1,
(*(CI->op_begin()+1))->getType(), MemsetFCache);
opcodes, (*(CI->op_begin()+1))->getType(), MemsetFCache);
break;
}
case Intrinsic::isunordered_f32:
@ -422,16 +478,18 @@ void IntrinsicLowering::LowerIntrinsicCall(CallInst *CI) {
"isunordered", CI));
break;
}
case Intrinsic::sqrt_f32:
case Intrinsic::sqrt_f64: {
static Function *sqrtFCache = 0;
case Intrinsic::sqrt_f32: {
static const unsigned opcodes[] = { 0 };
static Function *sqrtfFCache = 0;
if(CI->getType() == Type::FloatTy)
ReplaceCallWith("sqrtf", CI, CI->op_begin()+1, CI->op_end(),
Type::FloatTy, sqrtfFCache);
else
ReplaceCallWith("sqrt", CI, CI->op_begin()+1, CI->op_end(),
Type::DoubleTy, sqrtFCache);
ReplaceCallWith("sqrtf", CI, CI->op_begin()+1, CI->op_end(),
opcodes, Type::FloatTy, sqrtfFCache);
break;
}
case Intrinsic::sqrt_f64: {
static const unsigned opcodes[] = { 0 };
static Function *sqrtFCache = 0;
ReplaceCallWith("sqrt", CI, CI->op_begin()+1, CI->op_end(),
opcodes, Type::DoubleTy, sqrtFCache);
break;
}
}

View File

@ -102,7 +102,7 @@ static GlobalVariable *getGlobalVariable(Value *V) {
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) {
return GV;
} else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
if (CE->getOpcode() == Instruction::Cast) {
if (CE->getOpcode() == Instruction::BitCast) {
return dyn_cast<GlobalVariable>(CE->getOperand(0));
}
}
@ -115,7 +115,7 @@ static bool isGlobalVariable(Value *V) {
if (isa<GlobalVariable>(V) || isa<ConstantPointerNull>(V)) {
return true;
} else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
if (CE->getOpcode() == Instruction::Cast) {
if (CE->getOpcode() == Instruction::BitCast) {
return isa<GlobalVariable>(CE->getOperand(0));
}
}

View File

@ -557,13 +557,25 @@ public:
ISD::SETOLT); }
void visitSetGT(User &I) { visitSetCC(I, ISD::SETGT, ISD::SETUGT,
ISD::SETOGT); }
// Visit the conversion instructions
void visitTrunc(User &I);
void visitZExt(User &I);
void visitSExt(User &I);
void visitFPTrunc(User &I);
void visitFPExt(User &I);
void visitFPToUI(User &I);
void visitFPToSI(User &I);
void visitUIToFP(User &I);
void visitSIToFP(User &I);
void visitPtrToInt(User &I);
void visitIntToPtr(User &I);
void visitBitCast(User &I);
void visitExtractElement(User &I);
void visitInsertElement(User &I);
void visitShuffleVector(User &I);
void visitGetElementPtr(User &I);
void visitCast(User &I);
void visitSelect(User &I);
void visitMalloc(MallocInst &I);
@ -1525,63 +1537,127 @@ void SelectionDAGLowering::visitSelect(User &I) {
}
}
void SelectionDAGLowering::visitCast(User &I) {
void SelectionDAGLowering::visitTrunc(User &I) {
// TruncInst cannot be a no-op cast because sizeof(src) > sizeof(dest).
SDOperand N = getValue(I.getOperand(0));
MVT::ValueType DestVT = TLI.getValueType(I.getType());
setValue(&I, DAG.getNode(ISD::TRUNCATE, DestVT, N));
}
void SelectionDAGLowering::visitZExt(User &I) {
// ZExt cannot be a no-op cast because sizeof(src) < sizeof(dest).
// ZExt also can't be a cast to bool for same reason. So, nothing much to do
SDOperand N = getValue(I.getOperand(0));
MVT::ValueType DestVT = TLI.getValueType(I.getType());
setValue(&I, DAG.getNode(ISD::ZERO_EXTEND, DestVT, N));
}
void SelectionDAGLowering::visitSExt(User &I) {
// SExt cannot be a no-op cast because sizeof(src) < sizeof(dest).
// SExt also can't be a cast to bool for same reason. So, nothing much to do
SDOperand N = getValue(I.getOperand(0));
MVT::ValueType DestVT = TLI.getValueType(I.getType());
setValue(&I, DAG.getNode(ISD::SIGN_EXTEND, DestVT, N));
}
void SelectionDAGLowering::visitFPTrunc(User &I) {
// FPTrunc is never a no-op cast, no need to check
SDOperand N = getValue(I.getOperand(0));
MVT::ValueType DestVT = TLI.getValueType(I.getType());
setValue(&I, DAG.getNode(ISD::FP_ROUND, DestVT, N));
}
void SelectionDAGLowering::visitFPExt(User &I){
// FPTrunc is never a no-op cast, no need to check
SDOperand N = getValue(I.getOperand(0));
MVT::ValueType DestVT = TLI.getValueType(I.getType());
setValue(&I, DAG.getNode(ISD::FP_EXTEND, DestVT, N));
}
void SelectionDAGLowering::visitFPToUI(User &I) {
// FPToUI is never a no-op cast, no need to check
SDOperand N = getValue(I.getOperand(0));
MVT::ValueType DestVT = TLI.getValueType(I.getType());
setValue(&I, DAG.getNode(ISD::FP_TO_UINT, DestVT, N));
}
void SelectionDAGLowering::visitFPToSI(User &I) {
// FPToSI is never a no-op cast, no need to check
SDOperand N = getValue(I.getOperand(0));
MVT::ValueType DestVT = TLI.getValueType(I.getType());
setValue(&I, DAG.getNode(ISD::FP_TO_SINT, DestVT, N));
}
void SelectionDAGLowering::visitUIToFP(User &I) {
// UIToFP is never a no-op cast, no need to check
SDOperand N = getValue(I.getOperand(0));
MVT::ValueType DestVT = TLI.getValueType(I.getType());
setValue(&I, DAG.getNode(ISD::UINT_TO_FP, DestVT, N));
}
void SelectionDAGLowering::visitSIToFP(User &I){
// UIToFP is never a no-op cast, no need to check
SDOperand N = getValue(I.getOperand(0));
MVT::ValueType DestVT = TLI.getValueType(I.getType());
setValue(&I, DAG.getNode(ISD::SINT_TO_FP, DestVT, N));
}
void SelectionDAGLowering::visitPtrToInt(User &I) {
// What to do depends on the size of the integer and the size of the pointer.
// We can either truncate, zero extend, or no-op, accordingly.
SDOperand N = getValue(I.getOperand(0));
MVT::ValueType SrcVT = N.getValueType();
MVT::ValueType DestVT = TLI.getValueType(I.getType());
SDOperand Result;
if (MVT::getSizeInBits(DestVT) < MVT::getSizeInBits(SrcVT))
Result = DAG.getNode(ISD::TRUNCATE, DestVT, N);
else
// Note: ZERO_EXTEND can handle cases where the sizes are equal too
Result = DAG.getNode(ISD::ZERO_EXTEND, DestVT, N);
setValue(&I, Result);
}
void SelectionDAGLowering::visitIntToPtr(User &I) {
// What to do depends on the size of the integer and the size of the pointer.
// We can either truncate, zero extend, or no-op, accordingly.
SDOperand N = getValue(I.getOperand(0));
MVT::ValueType SrcVT = N.getValueType();
MVT::ValueType DestVT = TLI.getValueType(I.getType());
if (MVT::getSizeInBits(DestVT) < MVT::getSizeInBits(SrcVT))
setValue(&I, DAG.getNode(ISD::TRUNCATE, DestVT, N));
else
// Note: ZERO_EXTEND can handle cases where the sizes are equal too
setValue(&I, DAG.getNode(ISD::ZERO_EXTEND, DestVT, N));
}
void SelectionDAGLowering::visitBitCast(User &I) {
SDOperand N = getValue(I.getOperand(0));
MVT::ValueType DestVT = TLI.getValueType(I.getType());
if (DestVT == MVT::Vector) {
// This is a cast to a vector from something else. This is always a bit
// convert. Get information about the input vector.
// This is a cast to a vector from something else.
// Get information about the output vector.
const PackedType *DestTy = cast<PackedType>(I.getType());
MVT::ValueType EltVT = TLI.getValueType(DestTy->getElementType());
setValue(&I, DAG.getNode(ISD::VBIT_CONVERT, DestVT, N,
DAG.getConstant(DestTy->getNumElements(),MVT::i32),
DAG.getValueType(EltVT)));
} else if (SrcVT == DestVT) {
setValue(&I, N); // noop cast.
} else if (DestVT == MVT::i1) {
// Cast to bool is a comparison against zero, not truncation to zero.
SDOperand Zero = isInteger(SrcVT) ? DAG.getConstant(0, N.getValueType()) :
DAG.getConstantFP(0.0, N.getValueType());
setValue(&I, DAG.getSetCC(MVT::i1, N, Zero, ISD::SETNE));
} else if (isInteger(SrcVT)) {
if (isInteger(DestVT)) { // Int -> Int cast
if (DestVT < SrcVT) // Truncating cast?
setValue(&I, DAG.getNode(ISD::TRUNCATE, DestVT, N));
else if (I.getOperand(0)->getType()->isSigned())
setValue(&I, DAG.getNode(ISD::SIGN_EXTEND, DestVT, N));
else
setValue(&I, DAG.getNode(ISD::ZERO_EXTEND, DestVT, N));
} else if (isFloatingPoint(DestVT)) { // Int -> FP cast
if (I.getOperand(0)->getType()->isSigned())
setValue(&I, DAG.getNode(ISD::SINT_TO_FP, DestVT, N));
else
setValue(&I, DAG.getNode(ISD::UINT_TO_FP, DestVT, N));
} else {
assert(0 && "Unknown cast!");
}
} else if (isFloatingPoint(SrcVT)) {
if (isFloatingPoint(DestVT)) { // FP -> FP cast
if (DestVT < SrcVT) // Rounding cast?
setValue(&I, DAG.getNode(ISD::FP_ROUND, DestVT, N));
else
setValue(&I, DAG.getNode(ISD::FP_EXTEND, DestVT, N));
} else if (isInteger(DestVT)) { // FP -> Int cast.
if (I.getType()->isSigned())
setValue(&I, DAG.getNode(ISD::FP_TO_SINT, DestVT, N));
else
setValue(&I, DAG.getNode(ISD::FP_TO_UINT, DestVT, N));
} else {
assert(0 && "Unknown cast!");
}
} else {
assert(SrcVT == MVT::Vector && "Unknown cast!");
assert(DestVT != MVT::Vector && "Casts to vector already handled!");
// This is a cast from a vector to something else. This is always a bit
// convert. Get information about the input vector.
return;
}
MVT::ValueType SrcVT = N.getValueType();
if (SrcVT == MVT::Vector) {
// This is a cast from a vctor to something else.
// Get information about the input vector.
setValue(&I, DAG.getNode(ISD::VBIT_CONVERT, DestVT, N));
return;
}
// BitCast assures us that source and destination are the same size so this
// is either a BIT_CONVERT or a no-op.
if (DestVT != N.getValueType())
setValue(&I, DAG.getNode(ISD::BIT_CONVERT, DestVT, N)); // convert types
else
setValue(&I, N); // noop cast.
}
void SelectionDAGLowering::visitInsertElement(User &I) {
@ -3402,7 +3478,8 @@ static bool OptimizeNoopCopyExpression(CastInst *CI) {
while (isa<PHINode>(InsertPt)) ++InsertPt;
InsertedCast =
new CastInst(CI->getOperand(0), CI->getType(), "", InsertPt);
CastInst::createInferredCast(CI->getOperand(0), CI->getType(), "",
InsertPt);
MadeChange = true;
}
@ -3424,9 +3501,10 @@ static Instruction *InsertGEPComputeCode(Instruction *&V, BasicBlock *BB,
Value *PtrOffset) {
if (V) return V; // Already computed.
// Figure out the insertion point
BasicBlock::iterator InsertPt;
if (BB == GEPI->getParent()) {
// If insert into the GEP's block, insert right after the GEP.
// If GEP is already inserted into BB, insert right after the GEP.
InsertPt = GEPI;
++InsertPt;
} else {
@ -3440,11 +3518,14 @@ static Instruction *InsertGEPComputeCode(Instruction *&V, BasicBlock *BB,
// operand).
if (CastInst *CI = dyn_cast<CastInst>(Ptr))
if (CI->getParent() != BB && isa<PointerType>(CI->getOperand(0)->getType()))
Ptr = new CastInst(CI->getOperand(0), CI->getType(), "", InsertPt);
Ptr = CastInst::createInferredCast(CI->getOperand(0), CI->getType(), "",
InsertPt);
// Add the offset, cast it to the right type.
Ptr = BinaryOperator::createAdd(Ptr, PtrOffset, "", InsertPt);
return V = new CastInst(Ptr, GEPI->getType(), "", InsertPt);
// Ptr is an integer type, GEPI is pointer type ==> IntToPtr
return V = CastInst::create(Instruction::IntToPtr, Ptr, GEPI->getType(),
"", InsertPt);
}
/// ReplaceUsesOfGEPInst - Replace all uses of RepPtr with inserted code to
@ -3461,8 +3542,9 @@ static void ReplaceUsesOfGEPInst(Instruction *RepPtr, Value *Ptr,
while (!RepPtr->use_empty()) {
Instruction *User = cast<Instruction>(RepPtr->use_back());
// If the user is a Pointer-Pointer cast, recurse.
if (isa<CastInst>(User) && isa<PointerType>(User->getType())) {
// If the user is a Pointer-Pointer cast, recurse. Only BitCast can be
// used for a Pointer-Pointer cast.
if (isa<BitCastInst>(User)) {
ReplaceUsesOfGEPInst(User, Ptr, PtrOffset, DefBB, GEPI, InsertedExprs);
// Drop the use of RepPtr. The cast is dead. Don't delete it now, else we
@ -3489,7 +3571,8 @@ static void ReplaceUsesOfGEPInst(Instruction *RepPtr, Value *Ptr,
if (GEPI->getType() != RepPtr->getType()) {
BasicBlock::iterator IP = NewVal;
++IP;
NewVal = new CastInst(NewVal, RepPtr->getType(), "", IP);
// NewVal must be a GEP which must be pointer type, so BitCast
NewVal = new BitCastInst(NewVal, RepPtr->getType(), "", IP);
}
User->replaceUsesOfWith(RepPtr, NewVal);
}
@ -3535,7 +3618,8 @@ static bool OptimizeGEPExpression(GetElementPtrInst *GEPI,
// If this is a "GEP X, 0, 0, 0", turn this into a cast.
if (!hasConstantIndex && !hasVariableIndex) {
Value *NC = new CastInst(GEPI->getOperand(0), GEPI->getType(),
/// The GEP operand must be a pointer, so must its result -> BitCast
Value *NC = new BitCastInst(GEPI->getOperand(0), GEPI->getType(),
GEPI->getName(), GEPI);
GEPI->replaceAllUsesWith(NC);
GEPI->eraseFromParent();
@ -3550,7 +3634,7 @@ static bool OptimizeGEPExpression(GetElementPtrInst *GEPI,
// constant offset (which we now know is non-zero) and deal with it later.
uint64_t ConstantOffset = 0;
const Type *UIntPtrTy = TD->getIntPtrType();
Value *Ptr = new CastInst(GEPI->getOperand(0), UIntPtrTy, "", GEPI);
Value *Ptr = new PtrToIntInst(GEPI->getOperand(0), UIntPtrTy, "", GEPI);
const Type *Ty = GEPI->getOperand(0)->getType();
for (GetElementPtrInst::op_iterator OI = GEPI->op_begin()+1,
@ -3577,7 +3661,7 @@ static bool OptimizeGEPExpression(GetElementPtrInst *GEPI,
// Ptr = Ptr + Idx * ElementSize;
// Cast Idx to UIntPtrTy if needed.
Idx = new CastInst(Idx, UIntPtrTy, "", GEPI);
Idx = CastInst::createInferredCast(Idx, UIntPtrTy, "", GEPI);
uint64_t ElementSize = TD->getTypeSize(Ty);
// Mask off bits that should not be set.

View File

@ -213,7 +213,7 @@ void ExecutionEngine::runStaticConstructorsDestructors(bool isDtors) {
break; // Found a null terminator, exit.
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(FP))
if (CE->getOpcode() == Instruction::Cast)
if (CE->isCast())
FP = CE->getOperand(0);
if (Function *F = dyn_cast<Function>(FP)) {
// Execute the ctor/dtor function!
@ -299,15 +299,21 @@ void *ExecutionEngine::getPointerToGlobal(const GlobalValue *GV) {
return state.getGlobalAddressMap(locked)[GV];
}
/// FIXME: document
///
/// This function converts a Constant* into a GenericValue. The interesting
/// part is if C is a ConstantExpr.
/// @brief Get a GenericValue for a Constnat*
GenericValue ExecutionEngine::getConstantValue(const Constant *C) {
// Declare the result as garbage.
GenericValue Result;
// If its undefined, return the garbage.
if (isa<UndefValue>(C)) return Result;
if (ConstantExpr *CE = const_cast<ConstantExpr*>(dyn_cast<ConstantExpr>(C))) {
// If the value is a ConstantExpr
if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
switch (CE->getOpcode()) {
case Instruction::GetElementPtr: {
// Compute the index
Result = getConstantValue(CE->getOperand(0));
std::vector<Value*> Indexes(CE->op_begin()+1, CE->op_end());
uint64_t Offset =
@ -319,24 +325,35 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) {
Result.LongVal += Offset;
return Result;
}
case Instruction::Cast: {
// We only need to handle a few cases here. Almost all casts will
// automatically fold, just the ones involving pointers won't.
//
case Instruction::Trunc:
case Instruction::ZExt:
case Instruction::SExt:
case Instruction::FPTrunc:
case Instruction::FPExt:
case Instruction::UIToFP:
case Instruction::SIToFP:
case Instruction::FPToUI:
case Instruction::FPToSI:
break;
case Instruction::PtrToInt: {
Constant *Op = CE->getOperand(0);
GenericValue GV = getConstantValue(Op);
return GV;
}
case Instruction::BitCast: {
// Bit casts are no-ops but we can only return the GV of the operand if
// they are the same basic type (pointer->pointer, packed->packed, etc.)
Constant *Op = CE->getOperand(0);
GenericValue GV = getConstantValue(Op);
// Handle cast of pointer to pointer...
if (Op->getType()->getTypeID() == C->getType()->getTypeID())
return GV;
// Handle a cast of pointer to any integral type...
if (isa<PointerType>(Op->getType()) && C->getType()->isIntegral())
return GV;
// Handle cast of integer to a pointer...
if (isa<PointerType>(C->getType()) && Op->getType()->isIntegral())
switch (Op->getType()->getTypeID()) {
break;
}
case Instruction::IntToPtr: {
// IntToPtr casts are just so special. Cast to intptr_t first.
Constant *Op = CE->getOperand(0);
GenericValue GV = getConstantValue(Op);
switch (Op->getType()->getTypeID()) {
case Type::BoolTyID: return PTOGV((void*)(uintptr_t)GV.BoolVal);
case Type::SByteTyID: return PTOGV((void*)( intptr_t)GV.SByteVal);
case Type::UByteTyID: return PTOGV((void*)(uintptr_t)GV.UByteVal);
@ -347,10 +364,9 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) {
case Type::LongTyID: return PTOGV((void*)( intptr_t)GV.LongVal);
case Type::ULongTyID: return PTOGV((void*)(uintptr_t)GV.ULongVal);
default: assert(0 && "Unknown integral type!");
}
}
break;
}
case Instruction::Add:
switch (CE->getOperand(0)->getType()->getTypeID()) {
default: assert(0 && "Bad add type!"); abort();

View File

@ -81,8 +81,20 @@ static GenericValue executeSelectInst(GenericValue Src1, GenericValue Src2,
GenericValue Interpreter::getConstantExprValue (ConstantExpr *CE,
ExecutionContext &SF) {
switch (CE->getOpcode()) {
case Instruction::Cast:
return executeCastOperation(CE->getOperand(0), CE->getType(), SF);
case Instruction::Trunc:
case Instruction::ZExt:
case Instruction::SExt:
case Instruction::FPTrunc:
case Instruction::FPExt:
case Instruction::UIToFP:
case Instruction::SIToFP:
case Instruction::FPToUI:
case Instruction::FPToSI:
case Instruction::PtrToInt:
case Instruction::IntToPtr:
case Instruction::BitCast:
return executeCastOperation(Instruction::CastOps(CE->getOpcode()),
CE->getOperand(0), CE->getType(), SF);
case Instruction::GetElementPtr:
return executeGEPOperation(CE->getOperand(0), gep_type_begin(CE),
gep_type_end(CE), SF);
@ -1030,12 +1042,15 @@ void Interpreter::visitAShr(ShiftInst &I) {
SetValue(&I, Dest, SF);
}
#define IMPLEMENT_CAST(DTY, DCTY, STY) \
case Type::STY##TyID: Dest.DTY##Val = DCTY Src.STY##Val; break;
#define IMPLEMENT_CAST_START \
switch (DstTy->getTypeID()) {
#define IMPLEMENT_CAST_CASE_START(DESTTY, DESTCTY) \
#define IMPLEMENT_CAST(DTY, DCTY, STY) \
case Type::STY##TyID: Dest.DTY##Val = DCTY Src.STY##Val; break;
#define IMPLEMENT_CAST_CASE(DESTTY, DESTCTY) \
case Type::DESTTY##TyID: \
switch (SrcTy->getTypeID()) { \
switch (SrcTy->getTypeID()) { \
IMPLEMENT_CAST(DESTTY, DESTCTY, Bool); \
IMPLEMENT_CAST(DESTTY, DESTCTY, UByte); \
IMPLEMENT_CAST(DESTTY, DESTCTY, SByte); \
@ -1045,52 +1060,182 @@ void Interpreter::visitAShr(ShiftInst &I) {
IMPLEMENT_CAST(DESTTY, DESTCTY, Int); \
IMPLEMENT_CAST(DESTTY, DESTCTY, ULong); \
IMPLEMENT_CAST(DESTTY, DESTCTY, Long); \
IMPLEMENT_CAST(DESTTY, DESTCTY, Pointer);
#define IMPLEMENT_CAST_CASE_FP_IMP(DESTTY, DESTCTY) \
IMPLEMENT_CAST(DESTTY, DESTCTY, Pointer); \
IMPLEMENT_CAST(DESTTY, DESTCTY, Float); \
IMPLEMENT_CAST(DESTTY, DESTCTY, Double)
#define IMPLEMENT_CAST_CASE_END() \
default: std::cout << "Unhandled cast: " << *SrcTy << " to " << *Ty << "\n"; \
IMPLEMENT_CAST(DESTTY, DESTCTY, Double) \
default: \
std::cout << "Unhandled cast: " \
<< *SrcTy << " to " << *DstTy << "\n"; \
abort(); \
} \
break
#define IMPLEMENT_CAST_CASE(DESTTY, DESTCTY) \
IMPLEMENT_CAST_CASE_START(DESTTY, DESTCTY); \
IMPLEMENT_CAST_CASE_FP_IMP(DESTTY, DESTCTY); \
IMPLEMENT_CAST_CASE_END()
#define IMPLEMENT_CAST_END \
default: std::cout \
<< "Unhandled dest type for cast instruction: " \
<< *DstTy << "\n"; \
abort(); \
}
GenericValue Interpreter::executeCastOperation(Value *SrcVal, const Type *Ty,
GenericValue Interpreter::executeCastOperation(Instruction::CastOps opcode,
Value *SrcVal, const Type *DstTy,
ExecutionContext &SF) {
const Type *SrcTy = SrcVal->getType();
GenericValue Dest, Src = getOperandValue(SrcVal, SF);
switch (Ty->getTypeID()) {
IMPLEMENT_CAST_CASE(UByte , (unsigned char));
IMPLEMENT_CAST_CASE(SByte , ( signed char));
IMPLEMENT_CAST_CASE(UShort , (unsigned short));
IMPLEMENT_CAST_CASE(Short , ( signed short));
IMPLEMENT_CAST_CASE(UInt , (unsigned int ));
IMPLEMENT_CAST_CASE(Int , ( signed int ));
IMPLEMENT_CAST_CASE(ULong , (uint64_t));
IMPLEMENT_CAST_CASE(Long , ( int64_t));
IMPLEMENT_CAST_CASE(Pointer, (PointerTy));
IMPLEMENT_CAST_CASE(Float , (float));
IMPLEMENT_CAST_CASE(Double , (double));
IMPLEMENT_CAST_CASE(Bool , (bool));
default:
std::cout << "Unhandled dest type for cast instruction: " << *Ty << "\n";
abort();
if (opcode == Instruction::Trunc && DstTy->getTypeID() == Type::BoolTyID) {
// For truncations to bool, we must clear the high order bits of the source
switch (SrcTy->getTypeID()) {
case Type::BoolTyID: Src.BoolVal &= 1; break;
case Type::SByteTyID: Src.SByteVal &= 1; break;
case Type::UByteTyID: Src.UByteVal &= 1; break;
case Type::ShortTyID: Src.ShortVal &= 1; break;
case Type::UShortTyID: Src.UShortVal &= 1; break;
case Type::IntTyID: Src.IntVal &= 1; break;
case Type::UIntTyID: Src.UIntVal &= 1; break;
case Type::LongTyID: Src.LongVal &= 1; break;
case Type::ULongTyID: Src.ULongVal &= 1; break;
default:
assert(0 && "Can't trunc a non-integer!");
break;
}
} else if (opcode == Instruction::SExt &&
SrcTy->getTypeID() == Type::BoolTyID) {
// For sign extension from bool, we must extend the source bits.
SrcTy = Type::LongTy;
Src.LongVal = 0 - Src.BoolVal;
}
switch (opcode) {
case Instruction::Trunc: // src integer, dest integral (can't be long)
IMPLEMENT_CAST_START
IMPLEMENT_CAST_CASE(Bool , (bool));
IMPLEMENT_CAST_CASE(UByte , (unsigned char));
IMPLEMENT_CAST_CASE(SByte , ( signed char));
IMPLEMENT_CAST_CASE(UShort , (unsigned short));
IMPLEMENT_CAST_CASE(Short , ( signed short));
IMPLEMENT_CAST_CASE(UInt , (unsigned int ));
IMPLEMENT_CAST_CASE(Int , ( signed int ));
IMPLEMENT_CAST_END
break;
case Instruction::ZExt: // src integral (can't be long), dest integer
IMPLEMENT_CAST_START
IMPLEMENT_CAST_CASE(UByte , (unsigned char));
IMPLEMENT_CAST_CASE(SByte , (signed char)(unsigned char));
IMPLEMENT_CAST_CASE(UShort , (unsigned short));
IMPLEMENT_CAST_CASE(Short , (signed short)(unsigned short));
IMPLEMENT_CAST_CASE(UInt , (unsigned int ));
IMPLEMENT_CAST_CASE(Int , (signed int)(unsigned int ));
IMPLEMENT_CAST_CASE(ULong , (uint64_t));
IMPLEMENT_CAST_CASE(Long , (int64_t)(uint64_t));
IMPLEMENT_CAST_END
break;
case Instruction::SExt: // src integral (can't be long), dest integer
IMPLEMENT_CAST_START
IMPLEMENT_CAST_CASE(UByte , (unsigned char)(signed char));
IMPLEMENT_CAST_CASE(SByte , (signed char));
IMPLEMENT_CAST_CASE(UShort , (unsigned short)(signed short));
IMPLEMENT_CAST_CASE(Short , (signed short));
IMPLEMENT_CAST_CASE(UInt , (unsigned int )(signed int));
IMPLEMENT_CAST_CASE(Int , (signed int));
IMPLEMENT_CAST_CASE(ULong , (uint64_t)(int64_t));
IMPLEMENT_CAST_CASE(Long , (int64_t));
IMPLEMENT_CAST_END
break;
case Instruction::FPTrunc: // src double, dest float
IMPLEMENT_CAST_START
IMPLEMENT_CAST_CASE(Float , (float));
IMPLEMENT_CAST_END
break;
case Instruction::FPExt: // src float, dest double
IMPLEMENT_CAST_START
IMPLEMENT_CAST_CASE(Double , (double));
IMPLEMENT_CAST_END
break;
case Instruction::UIToFP: // src integral, dest floating
IMPLEMENT_CAST_START
IMPLEMENT_CAST_CASE(Float , (float)(uint64_t));
IMPLEMENT_CAST_CASE(Double , (double)(uint64_t));
IMPLEMENT_CAST_END
break;
case Instruction::SIToFP: // src integeral, dest floating
IMPLEMENT_CAST_START
IMPLEMENT_CAST_CASE(Float , (float)(int64_t));
IMPLEMENT_CAST_CASE(Double , (double)(int64_t));
IMPLEMENT_CAST_END
break;
case Instruction::FPToUI: // src floating, dest integral
IMPLEMENT_CAST_START
IMPLEMENT_CAST_CASE(Bool , (bool));
IMPLEMENT_CAST_CASE(UByte , (unsigned char));
IMPLEMENT_CAST_CASE(SByte , (signed char)(unsigned char));
IMPLEMENT_CAST_CASE(UShort , (unsigned short));
IMPLEMENT_CAST_CASE(Short , (signed short)(unsigned short));
IMPLEMENT_CAST_CASE(UInt , (unsigned int ));
IMPLEMENT_CAST_CASE(Int , (signed int)(unsigned int ));
IMPLEMENT_CAST_CASE(ULong , (uint64_t));
IMPLEMENT_CAST_CASE(Long , (int64_t)(uint64_t));
IMPLEMENT_CAST_END
break;
case Instruction::FPToSI: // src floating, dest integral
IMPLEMENT_CAST_START
IMPLEMENT_CAST_CASE(Bool , (bool));
IMPLEMENT_CAST_CASE(UByte , (unsigned char)(signed char));
IMPLEMENT_CAST_CASE(SByte , (signed char));
IMPLEMENT_CAST_CASE(UShort , (unsigned short)(signed short));
IMPLEMENT_CAST_CASE(Short , (signed short));
IMPLEMENT_CAST_CASE(UInt , (unsigned int )(signed int));
IMPLEMENT_CAST_CASE(Int , (signed int));
IMPLEMENT_CAST_CASE(ULong , (uint64_t)(int64_t));
IMPLEMENT_CAST_CASE(Long , (int64_t));
IMPLEMENT_CAST_END
break;
case Instruction::PtrToInt: // src pointer, dest integral
IMPLEMENT_CAST_START
IMPLEMENT_CAST_CASE(Bool , (bool));
IMPLEMENT_CAST_CASE(UByte , (unsigned char));
IMPLEMENT_CAST_CASE(SByte , (signed char)(unsigned char));
IMPLEMENT_CAST_CASE(UShort , (unsigned short));
IMPLEMENT_CAST_CASE(Short , (signed short)(unsigned short));
IMPLEMENT_CAST_CASE(UInt , (unsigned int));
IMPLEMENT_CAST_CASE(Int , (signed int)(unsigned int));
IMPLEMENT_CAST_CASE(ULong , (uint64_t));
IMPLEMENT_CAST_CASE(Long , (int64_t)(uint64_t));
IMPLEMENT_CAST_END
break;
case Instruction::IntToPtr: // src integral, dest pointer
IMPLEMENT_CAST_START
IMPLEMENT_CAST_CASE(Pointer, (PointerTy));
IMPLEMENT_CAST_END
break;
case Instruction::BitCast: // src any, dest any (same size)
IMPLEMENT_CAST_START
IMPLEMENT_CAST_CASE(Bool , (bool));
IMPLEMENT_CAST_CASE(UByte , (unsigned char));
IMPLEMENT_CAST_CASE(SByte , ( signed char));
IMPLEMENT_CAST_CASE(UShort , (unsigned short));
IMPLEMENT_CAST_CASE(Short , ( signed short));
IMPLEMENT_CAST_CASE(UInt , (unsigned int));
IMPLEMENT_CAST_CASE(Int , ( signed int));
IMPLEMENT_CAST_CASE(ULong , (uint64_t));
IMPLEMENT_CAST_CASE(Long , ( int64_t));
IMPLEMENT_CAST_CASE(Pointer, (PointerTy));
IMPLEMENT_CAST_CASE(Float , (float));
IMPLEMENT_CAST_CASE(Double , (double));
IMPLEMENT_CAST_END
break;
default:
std::cout
<< "Invalid cast opcode for cast instruction: " << opcode << "\n";
abort();
}
return Dest;
}
void Interpreter::visitCastInst(CastInst &I) {
ExecutionContext &SF = ECStack.back();
SetValue(&I, executeCastOperation(I.getOperand(0), I.getType(), SF), SF);
SetValue(&I, executeCastOperation(I.getOpcode(), I.getOperand(0),
I.getType(), SF), SF);
}
#define IMPLEMENT_VAARG(TY) \

View File

@ -192,8 +192,8 @@ private: // Helper functions
void initializeExternalFunctions();
GenericValue getConstantExprValue(ConstantExpr *CE, ExecutionContext &SF);
GenericValue getOperandValue(Value *V, ExecutionContext &SF);
GenericValue executeCastOperation(Value *SrcVal, const Type *Ty,
ExecutionContext &SF);
GenericValue executeCastOperation(Instruction::CastOps opcode, Value *SrcVal,
const Type *Ty, ExecutionContext &SF);
void popStackAndReturnValueToCaller(const Type *RetTy, GenericValue Result);
};

View File

@ -137,6 +137,7 @@ namespace {
void printBasicBlock(BasicBlock *BB);
void printLoop(Loop *L);
void printCast(unsigned opcode, const Type *SrcTy, const Type *DstTy);
void printConstant(Constant *CPV);
void printConstantWithCast(Constant *CPV, unsigned Opcode);
bool printConstExprCast(const ConstantExpr *CE);
@ -560,15 +561,76 @@ static bool isFPCSafeToPrint(const ConstantFP *CFP) {
#endif
}
/// Print out the casting for a cast operation. This does the double casting
/// necessary for conversion to the destination type, if necessary.
/// @returns true if a closing paren is necessary
/// @brief Print a cast
void CWriter::printCast(unsigned opc, const Type *SrcTy, const Type *DstTy) {
Out << '(';
printType(Out, DstTy);
Out << ')';
switch (opc) {
case Instruction::UIToFP:
case Instruction::ZExt:
if (SrcTy->isSigned()) {
Out << '(';
printType(Out, SrcTy->getUnsignedVersion());
Out << ')';
}
break;
case Instruction::SIToFP:
case Instruction::SExt:
if (SrcTy->isUnsigned()) {
Out << '(';
printType(Out, SrcTy->getSignedVersion());
Out << ')';
}
break;
case Instruction::IntToPtr:
case Instruction::PtrToInt:
// Avoid "cast to pointer from integer of different size" warnings
Out << "(unsigned long)";
break;
case Instruction::Trunc:
case Instruction::BitCast:
case Instruction::FPExt:
case Instruction::FPTrunc:
case Instruction::FPToSI:
case Instruction::FPToUI:
default:
break;
}
}
// printConstant - The LLVM Constant to C Constant converter.
void CWriter::printConstant(Constant *CPV) {
if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CPV)) {
switch (CE->getOpcode()) {
case Instruction::Cast:
Out << "((";
printType(Out, CPV->getType());
Out << ')';
case Instruction::Trunc:
case Instruction::ZExt:
case Instruction::SExt:
case Instruction::FPTrunc:
case Instruction::FPExt:
case Instruction::UIToFP:
case Instruction::SIToFP:
case Instruction::FPToUI:
case Instruction::FPToSI:
case Instruction::PtrToInt:
case Instruction::IntToPtr:
case Instruction::BitCast:
Out << "(";
printCast(CE->getOpcode(), CE->getOperand(0)->getType(), CE->getType());
if (CE->getOpcode() == Instruction::SExt &&
CE->getOperand(0)->getType() == Type::BoolTy) {
// Make sure we really sext from bool here by subtracting from 0
Out << "0-";
}
printConstant(CE->getOperand(0));
if (CE->getOpcode() == Instruction::Trunc &&
CE->getType() == Type::BoolTy) {
// Make sure we really truncate to bool here by anding with 1
Out << "&1u";
}
Out << ')';
return;
@ -829,14 +891,31 @@ void CWriter::printConstant(Constant *CPV) {
// care of detecting that case and printing the cast for the ConstantExpr.
bool CWriter::printConstExprCast(const ConstantExpr* CE) {
bool NeedsExplicitCast = false;
const Type* Ty = CE->getOperand(0)->getType();
const Type *Ty = CE->getOperand(0)->getType();
switch (CE->getOpcode()) {
case Instruction::LShr:
case Instruction::URem:
case Instruction::UDiv: NeedsExplicitCast = Ty->isSigned(); break;
case Instruction::UDiv:
NeedsExplicitCast = Ty->isSigned(); break;
case Instruction::AShr:
case Instruction::SRem:
case Instruction::SDiv: NeedsExplicitCast = Ty->isUnsigned(); break;
case Instruction::SDiv:
NeedsExplicitCast = Ty->isUnsigned(); break;
case Instruction::ZExt:
case Instruction::SExt:
case Instruction::Trunc:
case Instruction::FPTrunc:
case Instruction::FPExt:
case Instruction::UIToFP:
case Instruction::SIToFP:
case Instruction::FPToUI:
case Instruction::FPToSI:
case Instruction::PtrToInt:
case Instruction::IntToPtr:
case Instruction::BitCast:
Ty = CE->getType();
NeedsExplicitCast = true;
break;
default: break;
}
if (NeedsExplicitCast) {
@ -860,7 +939,8 @@ void CWriter::printConstantWithCast(Constant* CPV, unsigned Opcode) {
// Based on the Opcode for which this Constant is being written, determine
// the new type to which the operand should be casted by setting the value
// of OpTy. If we change OpTy, also set shouldCast to true.
// of OpTy. If we change OpTy, also set shouldCast to true so it gets
// casted below.
switch (Opcode) {
default:
// for most instructions, it doesn't matter
@ -885,7 +965,7 @@ void CWriter::printConstantWithCast(Constant* CPV, unsigned Opcode) {
break;
}
// Write out the casted constnat if we should, otherwise just write the
// Write out the casted constant if we should, otherwise just write the
// operand.
if (shouldCast) {
Out << "((";
@ -918,7 +998,7 @@ void CWriter::writeOperandInternal(Value *Operand) {
void CWriter::writeOperand(Value *Operand) {
if (isa<GlobalVariable>(Operand) || isDirectAlloca(Operand))
Out << "(&"; // Global variables are references as their addresses by llvm
Out << "(&"; // Global variables are referenced as their addresses by llvm
writeOperandInternal(Operand);
@ -932,14 +1012,31 @@ void CWriter::writeOperand(Value *Operand) {
// for the Instruction.
bool CWriter::writeInstructionCast(const Instruction &I) {
bool NeedsExplicitCast = false;
const Type* Ty = I.getOperand(0)->getType();
const Type *Ty = I.getOperand(0)->getType();
switch (I.getOpcode()) {
case Instruction::LShr:
case Instruction::URem:
case Instruction::UDiv: NeedsExplicitCast = Ty->isSigned(); break;
case Instruction::UDiv:
NeedsExplicitCast = Ty->isSigned(); break;
case Instruction::AShr:
case Instruction::SRem:
case Instruction::SDiv: NeedsExplicitCast = Ty->isUnsigned(); break;
case Instruction::SDiv:
NeedsExplicitCast = Ty->isUnsigned(); break;
case Instruction::ZExt:
case Instruction::SExt:
case Instruction::Trunc:
case Instruction::FPTrunc:
case Instruction::FPExt:
case Instruction::UIToFP:
case Instruction::SIToFP:
case Instruction::FPToUI:
case Instruction::FPToSI:
case Instruction::PtrToInt:
case Instruction::IntToPtr:
case Instruction::BitCast:
Ty = I.getType();
NeedsExplicitCast = true;
break;
default: break;
}
if (NeedsExplicitCast) {
@ -1136,7 +1233,7 @@ static void FindStaticTors(GlobalVariable *GV, std::set<Function*> &StaticTors){
return; // Found a null terminator, exit printing.
Constant *FP = CS->getOperand(1);
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(FP))
if (CE->getOpcode() == Instruction::Cast)
if (CE->isCast())
FP = CE->getOperand(0);
if (Function *F = dyn_cast<Function>(FP))
StaticTors.insert(F);
@ -1854,22 +1951,20 @@ void CWriter::visitBinaryOperator(Instruction &I) {
}
void CWriter::visitCastInst(CastInst &I) {
if (I.getType() == Type::BoolTy) {
Out << '(';
writeOperand(I.getOperand(0));
Out << " != 0)";
return;
}
const Type *DstTy = I.getType();
const Type *SrcTy = I.getOperand(0)->getType();
Out << '(';
printType(Out, I.getType());
Out << ')';
if (isa<PointerType>(I.getType())&&I.getOperand(0)->getType()->isIntegral() ||
isa<PointerType>(I.getOperand(0)->getType())&&I.getType()->isIntegral()) {
// Avoid "cast to pointer from integer of different size" warnings
Out << "(long)";
printCast(I.getOpcode(), SrcTy, DstTy);
if (I.getOpcode() == Instruction::SExt && SrcTy == Type::BoolTy) {
// Make sure we really get a sext from bool by subtracing the bool from 0
Out << "0-";
}
writeOperand(I.getOperand(0));
if (I.getOpcode() == Instruction::Trunc && DstTy == Type::BoolTy) {
// Make sure we really get a trunc to bool by anding the operand with 1
Out << "&1u";
}
Out << ')';
}
void CWriter::visitSelectInst(SelectInst &I) {
@ -2076,7 +2171,7 @@ void CWriter::visitCallInst(CallInst &I) {
// match exactly.
//
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Callee))
if (CE->getOpcode() == Instruction::Cast)
if (CE->isCast())
if (Function *RF = dyn_cast<Function>(CE->getOperand(0))) {
NeedsCast = true;
Callee = RF;

View File

@ -137,6 +137,7 @@ namespace {
void printBasicBlock(BasicBlock *BB);
void printLoop(Loop *L);
void printCast(unsigned opcode, const Type *SrcTy, const Type *DstTy);
void printConstant(Constant *CPV);
void printConstantWithCast(Constant *CPV, unsigned Opcode);
bool printConstExprCast(const ConstantExpr *CE);
@ -560,15 +561,76 @@ static bool isFPCSafeToPrint(const ConstantFP *CFP) {
#endif
}
/// Print out the casting for a cast operation. This does the double casting
/// necessary for conversion to the destination type, if necessary.
/// @returns true if a closing paren is necessary
/// @brief Print a cast
void CWriter::printCast(unsigned opc, const Type *SrcTy, const Type *DstTy) {
Out << '(';
printType(Out, DstTy);
Out << ')';
switch (opc) {
case Instruction::UIToFP:
case Instruction::ZExt:
if (SrcTy->isSigned()) {
Out << '(';
printType(Out, SrcTy->getUnsignedVersion());
Out << ')';
}
break;
case Instruction::SIToFP:
case Instruction::SExt:
if (SrcTy->isUnsigned()) {
Out << '(';
printType(Out, SrcTy->getSignedVersion());
Out << ')';
}
break;
case Instruction::IntToPtr:
case Instruction::PtrToInt:
// Avoid "cast to pointer from integer of different size" warnings
Out << "(unsigned long)";
break;
case Instruction::Trunc:
case Instruction::BitCast:
case Instruction::FPExt:
case Instruction::FPTrunc:
case Instruction::FPToSI:
case Instruction::FPToUI:
default:
break;
}
}
// printConstant - The LLVM Constant to C Constant converter.
void CWriter::printConstant(Constant *CPV) {
if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CPV)) {
switch (CE->getOpcode()) {
case Instruction::Cast:
Out << "((";
printType(Out, CPV->getType());
Out << ')';
case Instruction::Trunc:
case Instruction::ZExt:
case Instruction::SExt:
case Instruction::FPTrunc:
case Instruction::FPExt:
case Instruction::UIToFP:
case Instruction::SIToFP:
case Instruction::FPToUI:
case Instruction::FPToSI:
case Instruction::PtrToInt:
case Instruction::IntToPtr:
case Instruction::BitCast:
Out << "(";
printCast(CE->getOpcode(), CE->getOperand(0)->getType(), CE->getType());
if (CE->getOpcode() == Instruction::SExt &&
CE->getOperand(0)->getType() == Type::BoolTy) {
// Make sure we really sext from bool here by subtracting from 0
Out << "0-";
}
printConstant(CE->getOperand(0));
if (CE->getOpcode() == Instruction::Trunc &&
CE->getType() == Type::BoolTy) {
// Make sure we really truncate to bool here by anding with 1
Out << "&1u";
}
Out << ')';
return;
@ -829,14 +891,31 @@ void CWriter::printConstant(Constant *CPV) {
// care of detecting that case and printing the cast for the ConstantExpr.
bool CWriter::printConstExprCast(const ConstantExpr* CE) {
bool NeedsExplicitCast = false;
const Type* Ty = CE->getOperand(0)->getType();
const Type *Ty = CE->getOperand(0)->getType();
switch (CE->getOpcode()) {
case Instruction::LShr:
case Instruction::URem:
case Instruction::UDiv: NeedsExplicitCast = Ty->isSigned(); break;
case Instruction::UDiv:
NeedsExplicitCast = Ty->isSigned(); break;
case Instruction::AShr:
case Instruction::SRem:
case Instruction::SDiv: NeedsExplicitCast = Ty->isUnsigned(); break;
case Instruction::SDiv:
NeedsExplicitCast = Ty->isUnsigned(); break;
case Instruction::ZExt:
case Instruction::SExt:
case Instruction::Trunc:
case Instruction::FPTrunc:
case Instruction::FPExt:
case Instruction::UIToFP:
case Instruction::SIToFP:
case Instruction::FPToUI:
case Instruction::FPToSI:
case Instruction::PtrToInt:
case Instruction::IntToPtr:
case Instruction::BitCast:
Ty = CE->getType();
NeedsExplicitCast = true;
break;
default: break;
}
if (NeedsExplicitCast) {
@ -860,7 +939,8 @@ void CWriter::printConstantWithCast(Constant* CPV, unsigned Opcode) {
// Based on the Opcode for which this Constant is being written, determine
// the new type to which the operand should be casted by setting the value
// of OpTy. If we change OpTy, also set shouldCast to true.
// of OpTy. If we change OpTy, also set shouldCast to true so it gets
// casted below.
switch (Opcode) {
default:
// for most instructions, it doesn't matter
@ -885,7 +965,7 @@ void CWriter::printConstantWithCast(Constant* CPV, unsigned Opcode) {
break;
}
// Write out the casted constnat if we should, otherwise just write the
// Write out the casted constant if we should, otherwise just write the
// operand.
if (shouldCast) {
Out << "((";
@ -918,7 +998,7 @@ void CWriter::writeOperandInternal(Value *Operand) {
void CWriter::writeOperand(Value *Operand) {
if (isa<GlobalVariable>(Operand) || isDirectAlloca(Operand))
Out << "(&"; // Global variables are references as their addresses by llvm
Out << "(&"; // Global variables are referenced as their addresses by llvm
writeOperandInternal(Operand);
@ -932,14 +1012,31 @@ void CWriter::writeOperand(Value *Operand) {
// for the Instruction.
bool CWriter::writeInstructionCast(const Instruction &I) {
bool NeedsExplicitCast = false;
const Type* Ty = I.getOperand(0)->getType();
const Type *Ty = I.getOperand(0)->getType();
switch (I.getOpcode()) {
case Instruction::LShr:
case Instruction::URem:
case Instruction::UDiv: NeedsExplicitCast = Ty->isSigned(); break;
case Instruction::UDiv:
NeedsExplicitCast = Ty->isSigned(); break;
case Instruction::AShr:
case Instruction::SRem:
case Instruction::SDiv: NeedsExplicitCast = Ty->isUnsigned(); break;
case Instruction::SDiv:
NeedsExplicitCast = Ty->isUnsigned(); break;
case Instruction::ZExt:
case Instruction::SExt:
case Instruction::Trunc:
case Instruction::FPTrunc:
case Instruction::FPExt:
case Instruction::UIToFP:
case Instruction::SIToFP:
case Instruction::FPToUI:
case Instruction::FPToSI:
case Instruction::PtrToInt:
case Instruction::IntToPtr:
case Instruction::BitCast:
Ty = I.getType();
NeedsExplicitCast = true;
break;
default: break;
}
if (NeedsExplicitCast) {
@ -1136,7 +1233,7 @@ static void FindStaticTors(GlobalVariable *GV, std::set<Function*> &StaticTors){
return; // Found a null terminator, exit printing.
Constant *FP = CS->getOperand(1);
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(FP))
if (CE->getOpcode() == Instruction::Cast)
if (CE->isCast())
FP = CE->getOperand(0);
if (Function *F = dyn_cast<Function>(FP))
StaticTors.insert(F);
@ -1854,22 +1951,20 @@ void CWriter::visitBinaryOperator(Instruction &I) {
}
void CWriter::visitCastInst(CastInst &I) {
if (I.getType() == Type::BoolTy) {
Out << '(';
writeOperand(I.getOperand(0));
Out << " != 0)";
return;
}
const Type *DstTy = I.getType();
const Type *SrcTy = I.getOperand(0)->getType();
Out << '(';
printType(Out, I.getType());
Out << ')';
if (isa<PointerType>(I.getType())&&I.getOperand(0)->getType()->isIntegral() ||
isa<PointerType>(I.getOperand(0)->getType())&&I.getType()->isIntegral()) {
// Avoid "cast to pointer from integer of different size" warnings
Out << "(long)";
printCast(I.getOpcode(), SrcTy, DstTy);
if (I.getOpcode() == Instruction::SExt && SrcTy == Type::BoolTy) {
// Make sure we really get a sext from bool by subtracing the bool from 0
Out << "0-";
}
writeOperand(I.getOperand(0));
if (I.getOpcode() == Instruction::Trunc && DstTy == Type::BoolTy) {
// Make sure we really get a trunc to bool by anding the operand with 1
Out << "&1u";
}
Out << ')';
}
void CWriter::visitSelectInst(SelectInst &I) {
@ -2076,7 +2171,7 @@ void CWriter::visitCallInst(CallInst &I) {
// match exactly.
//
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Callee))
if (CE->getOpcode() == Instruction::Cast)
if (CE->isCast())
if (Function *RF = dyn_cast<Function>(CE->getOperand(0))) {
NeedsCast = true;
Callee = RF;

View File

@ -52,12 +52,10 @@ bool llvm::ExpressionConvertibleToType(Value *V, const Type *Ty,
if (I == 0) return false; // Otherwise, we can't convert!
switch (I->getOpcode()) {
case Instruction::Cast:
// We can convert the expr if the cast destination type is losslessly
// convertible to the requested type.
if (!Ty->isLosslesslyConvertibleTo(I->getType())) return false;
// We also do not allow conversion of a cast that casts from a ptr to array
case Instruction::BitCast:
if (!cast<BitCastInst>(I)->isLosslessCast())
return false;
// We do not allow conversion of a cast that casts from a ptr to array
// of X to a *X. For example: cast [4 x %List *] * %val to %List * *
//
if (const PointerType *SPT =
@ -66,6 +64,7 @@ bool llvm::ExpressionConvertibleToType(Value *V, const Type *Ty,
if (const ArrayType *AT = dyn_cast<ArrayType>(SPT->getElementType()))
if (AT->getElementType() == DPT->getElementType())
return false;
// Otherwise it is a lossless cast and we can allow it
break;
case Instruction::Add:
@ -227,9 +226,9 @@ Value *llvm::ConvertExpressionToType(Value *V, const Type *Ty,
Constant *Dummy = Constant::getNullValue(Ty);
switch (I->getOpcode()) {
case Instruction::Cast:
case Instruction::BitCast:
assert(VMC.NewCasts.count(ValueHandle(VMC, I)) == 0);
Res = new CastInst(I->getOperand(0), Ty, Name);
Res = CastInst::createInferredCast(I->getOperand(0), Ty, Name);
VMC.NewCasts.insert(ValueHandle(VMC, Res));
break;
@ -307,7 +306,8 @@ Value *llvm::ConvertExpressionToType(Value *V, const Type *Ty,
Indices.pop_back();
if (GetElementPtrInst::getIndexedType(BaseType, Indices, true) == PVTy) {
if (Indices.size() == 0)
Res = new CastInst(GEP->getPointerOperand(), BaseType); // NOOP CAST
// We want to no-op cast this so use BitCast
Res = new BitCastInst(GEP->getPointerOperand(), BaseType);
else
Res = new GetElementPtrInst(GEP->getPointerOperand(), Indices, Name);
break;
@ -411,10 +411,6 @@ bool llvm::ValueConvertibleToType(Value *V, const Type *Ty,
return true;
}
// OperandConvertibleToType - Return true if it is possible to convert operand
// V of User (instruction) U to the specified type. This is true iff it is
// possible to change the specified instruction to accept this. CTMap is a map
@ -431,29 +427,18 @@ static bool OperandConvertibleToType(User *U, Value *V, const Type *Ty,
return false;
Instruction *I = dyn_cast<Instruction>(U);
if (I == 0) return false; // We can't convert!
if (I == 0) return false; // We can't convert non-instructions!
switch (I->getOpcode()) {
case Instruction::Cast:
case Instruction::BitCast:
assert(I->getOperand(0) == V);
// We can convert the expr if the cast destination type is losslessly
// convertible to the requested type.
// Also, do not change a cast that is a noop cast. For all intents and
// purposes it should be eliminated.
if (!Ty->isLosslesslyConvertibleTo(I->getOperand(0)->getType()) ||
// convertible to the requested type. Also, do not change a cast that
// is a noop cast. For all intents and purposes it should be eliminated.
if (!cast<BitCastInst>(I)->isLosslessCast() ||
I->getType() == I->getOperand(0)->getType())
return false;
// Do not allow a 'cast ushort %V to uint' to have it's first operand be
// converted to a 'short' type. Doing so changes the way sign promotion
// happens, and breaks things. Only allow the cast to take place if the
// signedness doesn't change... or if the current cast is not a lossy
// conversion.
//
if (!I->getType()->isLosslesslyConvertibleTo(I->getOperand(0)->getType()) &&
I->getOperand(0)->getType()->isSigned() != Ty->isSigned())
return false;
// We also do not allow conversion of a cast that casts from a ptr to array
// of X to a *X. For example: cast [4 x %List *] * %val to %List * *
//
@ -642,7 +627,8 @@ static bool OperandConvertibleToType(User *U, Value *V, const Type *Ty,
// arguments if possible.
//
for (unsigned i = 0, NA = FTy->getNumParams(); i < NA; ++i)
if (!FTy->getParamType(i)->isLosslesslyConvertibleTo(I->getOperand(i+1)->getType()))
if (!FTy->getParamType(i)->canLosslesslyBitCastTo(
I->getOperand(i+1)->getType()))
return false; // Operands must have compatible types!
// Okay, at this point, we know that all of the arguments can be
@ -662,7 +648,7 @@ static bool OperandConvertibleToType(User *U, Value *V, const Type *Ty,
// If we get this far, we know the value is in the varargs section of the
// function! We can convert if we don't reinterpret the value...
//
return Ty->isLosslesslyConvertibleTo(V->getType());
return Ty->canLosslesslyBitCastTo(V->getType());
}
}
return false;
@ -718,19 +704,8 @@ static void ConvertOperandToType(User *U, Value *OldVal, Value *NewVal,
Constant::getNullValue(NewTy) : 0;
switch (I->getOpcode()) {
case Instruction::Cast:
if (VMC.NewCasts.count(ValueHandle(VMC, I))) {
// This cast has already had it's value converted, causing a new cast to
// be created. We don't want to create YET ANOTHER cast instruction
// representing the original one, so just modify the operand of this cast
// instruction, which we know is newly created.
I->setOperand(0, NewVal);
I->setName(Name); // give I its name back
return;
} else {
Res = new CastInst(NewVal, I->getType(), Name);
}
case Instruction::BitCast:
Res = CastInst::createInferredCast(NewVal, I->getType(), Name);
break;
case Instruction::Add:
@ -895,9 +870,9 @@ static void ConvertOperandToType(User *U, Value *OldVal, Value *NewVal,
for (unsigned i = 0; i != NewTy->getNumParams(); ++i)
if (Params[i]->getType() != NewTy->getParamType(i)) {
// Create a cast to convert it to the right type, we know that this
// is a lossless cast...
// is a no-op cast...
//
Params[i] = new CastInst(Params[i], NewTy->getParamType(i),
Params[i] = new BitCastInst(Params[i], NewTy->getParamType(i),
"callarg.cast." +
Params[i]->getName(), It);
}

View File

@ -329,7 +329,7 @@ static bool CleanupConstantGlobalUsers(Value *V, Constant *Init) {
if (Init)
SubInit = ConstantFoldLoadThroughGEPConstantExpr(Init, CE);
Changed |= CleanupConstantGlobalUsers(CE, SubInit);
} else if (CE->getOpcode() == Instruction::Cast &&
} else if (CE->getOpcode() == Instruction::BitCast &&
isa<PointerType>(CE->getType())) {
// Pointer cast, delete any stores and memsets to the global.
Changed |= CleanupConstantGlobalUsers(CE, 0);
@ -1174,7 +1174,7 @@ static void ShrinkGlobalToBoolean(GlobalVariable *GV, Constant *OtherVal) {
LoadInst *NLI = new LoadInst(NewGV, Name+".b", LI);
Value *NSI;
if (IsOneZero)
NSI = new CastInst(NLI, LI->getType(), Name, LI);
NSI = CastInst::createInferredCast(NLI, LI->getType(), Name, LI);
else
NSI = new SelectInst(NLI, OtherVal, InitVal, Name, LI);
LI->replaceAllUsesWith(NSI);

View File

@ -74,7 +74,8 @@ bool IndMemRemPass::runOnModule(Module &M) {
GlobalValue::LinkOnceLinkage,
"malloc_llvm_bounce", &M);
BasicBlock* bb = new BasicBlock("entry",FN);
Instruction* c = new CastInst(FN->arg_begin(), Type::UIntTy, "c", bb);
Instruction* c =
CastInst::createInferredCast(FN->arg_begin(), Type::UIntTy, "c", bb);
Instruction* a = new MallocInst(Type::SByteTy, c, "m", bb);
new ReturnInst(a, bb);
++NumBounce;

View File

@ -141,14 +141,11 @@ void FunctionInfo::analyzeFunction(Function *F) {
II != E; ++II) {
if (isa<DbgInfoIntrinsic>(II)) continue; // Debug intrinsics don't count.
// Noop casts don't count.
// Noop casts, including ptr <-> int, don't count.
if (const CastInst *CI = dyn_cast<CastInst>(II)) {
const Type *OpTy = CI->getOperand(0)->getType();
if (CI->getType()->isLosslesslyConvertibleTo(OpTy))
if (CI->isLosslessCast() || isa<IntToPtrInst>(CI) ||
isa<PtrToIntInst>(CI))
continue;
if ((isa<PointerType>(CI->getType()) && OpTy->isInteger()) ||
(isa<PointerType>(OpTy) && CI->getType()->isInteger()))
continue; // ptr <-> int is *probably* noop cast.
} else if (const GetElementPtrInst *GEPI =
dyn_cast<GetElementPtrInst>(II)) {
// If a GEP has all constant indices, it will probably be folded with

View File

@ -259,7 +259,8 @@ void LowerSetJmp::TransformLongJmpCall(CallInst* Inst)
// same parameters as "longjmp", except that the buffer is cast to a
// char*. It returns "void", so it doesn't need to replace any of
// Inst's uses and doesn't get a name.
CastInst* CI = new CastInst(Inst->getOperand(1), SBPTy, "LJBuf", Inst);
CastInst* CI =
new BitCastInst(Inst->getOperand(1), SBPTy, "LJBuf", Inst);
new CallInst(ThrowLongJmp, make_vector<Value*>(CI, Inst->getOperand(2), 0),
"", Inst);
@ -375,7 +376,8 @@ void LowerSetJmp::TransformSetJmpCall(CallInst* Inst)
// Add this setjmp to the setjmp map.
const Type* SBPTy = PointerType::get(Type::SByteTy);
CastInst* BufPtr = new CastInst(Inst->getOperand(1), SBPTy, "SBJmpBuf", Inst);
CastInst* BufPtr =
new BitCastInst(Inst->getOperand(1), SBPTy, "SBJmpBuf", Inst);
new CallInst(AddSJToMap,
make_vector<Value*>(GetSetJmpMap(Func), BufPtr,
ConstantInt::get(Type::UIntTy,

View File

@ -140,7 +140,9 @@ bool RaiseAllocations::runOnModule(Module &M) {
// If no prototype was provided for malloc, we may need to cast the
// source size.
if (Source->getType() != Type::UIntTy)
Source = new CastInst(Source, Type::UIntTy, "MallocAmtCast", I);
Source =
CastInst::createInferredCast(Source, Type::UIntTy,
"MallocAmtCast", I);
std::string Name(I->getName()); I->setName("");
MallocInst *MI = new MallocInst(Type::SByteTy, Source, Name, I);
@ -160,7 +162,7 @@ bool RaiseAllocations::runOnModule(Module &M) {
Users.insert(Users.end(), GV->use_begin(), GV->use_end());
EqPointers.push_back(GV);
} else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(U)) {
if (CE->getOpcode() == Instruction::Cast) {
if (CE->isCast()) {
Users.insert(Users.end(), CE->use_begin(), CE->use_end());
EqPointers.push_back(CE);
}
@ -191,8 +193,8 @@ bool RaiseAllocations::runOnModule(Module &M) {
//
Value *Source = *CS.arg_begin();
if (!isa<PointerType>(Source->getType()))
Source = new CastInst(Source, PointerType::get(Type::SByteTy),
"FreePtrCast", I);
Source = CastInst::createInferredCast(
Source, PointerType::get(Type::SByteTy), "FreePtrCast", I);
new FreeInst(Source, I);
// If the old instruction was an invoke, add an unconditional branch
@ -211,7 +213,7 @@ bool RaiseAllocations::runOnModule(Module &M) {
Users.insert(Users.end(), GV->use_begin(), GV->use_end());
EqPointers.push_back(GV);
} else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(U)) {
if (CE->getOpcode() == Instruction::Cast) {
if (CE->isCast()) {
Users.insert(Users.end(), CE->use_begin(), CE->use_end());
EqPointers.push_back(CE);
}

View File

@ -650,7 +650,8 @@ public:
LoadInst* load =
new LoadInst(CastToCStr(s2,*ci), ci->getName()+".load",ci);
CastInst* cast =
new CastInst(load,Type::IntTy,ci->getName()+".int",ci);
CastInst::create(Instruction::SExt, load, Type::IntTy,
ci->getName()+".int", ci);
ci->replaceAllUsesWith(cast);
ci->eraseFromParent();
return true;
@ -667,7 +668,8 @@ public:
LoadInst* load =
new LoadInst(CastToCStr(s1,*ci),ci->getName()+".val",ci);
CastInst* cast =
new CastInst(load,Type::IntTy,ci->getName()+".int",ci);
CastInst::create(Instruction::SExt, load, Type::IntTy,
ci->getName()+".int", ci);
ci->replaceAllUsesWith(cast);
ci->eraseFromParent();
return true;
@ -741,7 +743,8 @@ public:
// strncmp("",x) -> *x
LoadInst* load = new LoadInst(s1,ci->getName()+".load",ci);
CastInst* cast =
new CastInst(load,Type::IntTy,ci->getName()+".int",ci);
CastInst::create(Instruction::SExt, load, Type::IntTy,
ci->getName()+".int", ci);
ci->replaceAllUsesWith(cast);
ci->eraseFromParent();
return true;
@ -757,7 +760,8 @@ public:
// strncmp(x,"") -> *x
LoadInst* load = new LoadInst(s2,ci->getName()+".val",ci);
CastInst* cast =
new CastInst(load,Type::IntTy,ci->getName()+".int",ci);
CastInst::create(Instruction::SExt, load, Type::IntTy,
ci->getName()+".int", ci);
ci->replaceAllUsesWith(cast);
ci->eraseFromParent();
return true;
@ -997,13 +1001,15 @@ struct memcmpOptimization : public LibCallOptimization {
case 1: {
// memcmp(S1,S2,1) -> *(ubyte*)S1 - *(ubyte*)S2
const Type *UCharPtr = PointerType::get(Type::UByteTy);
CastInst *Op1Cast = new CastInst(LHS, UCharPtr, LHS->getName(), CI);
CastInst *Op2Cast = new CastInst(RHS, UCharPtr, RHS->getName(), CI);
CastInst *Op1Cast = CastInst::create(
Instruction::BitCast, LHS, UCharPtr, LHS->getName(), CI);
CastInst *Op2Cast = CastInst::create(
Instruction::BitCast, RHS, UCharPtr, RHS->getName(), CI);
Value *S1V = new LoadInst(Op1Cast, LHS->getName()+".val", CI);
Value *S2V = new LoadInst(Op2Cast, RHS->getName()+".val", CI);
Value *RV = BinaryOperator::createSub(S1V, S2V, CI->getName()+".diff",CI);
if (RV->getType() != CI->getType())
RV = new CastInst(RV, CI->getType(), RV->getName(), CI);
RV = CastInst::createInferredCast(RV, CI->getType(), RV->getName(), CI);
CI->replaceAllUsesWith(RV);
CI->eraseFromParent();
return true;
@ -1014,8 +1020,10 @@ struct memcmpOptimization : public LibCallOptimization {
// memcmp(S1,S2,2) -> S1[0]-S2[0] | S1[1]-S2[1] iff only ==/!= 0 matters
const Type *UCharPtr = PointerType::get(Type::UByteTy);
CastInst *Op1Cast = new CastInst(LHS, UCharPtr, LHS->getName(), CI);
CastInst *Op2Cast = new CastInst(RHS, UCharPtr, RHS->getName(), CI);
CastInst *Op1Cast = CastInst::create(
Instruction::BitCast, LHS, UCharPtr, LHS->getName(), CI);
CastInst *Op2Cast = CastInst::create(
Instruction::BitCast, RHS, UCharPtr, RHS->getName(), CI);
Value *S1V1 = new LoadInst(Op1Cast, LHS->getName()+".val1", CI);
Value *S2V1 = new LoadInst(Op2Cast, RHS->getName()+".val1", CI);
Value *D1 = BinaryOperator::createSub(S1V1, S2V1,
@ -1029,7 +1037,8 @@ struct memcmpOptimization : public LibCallOptimization {
CI->getName()+".d1", CI);
Value *Or = BinaryOperator::createOr(D1, D2, CI->getName()+".res", CI);
if (Or->getType() != CI->getType())
Or = new CastInst(Or, CI->getType(), Or->getName(), CI);
Or = CastInst::createInferredCast(Or, CI->getType(), Or->getName(),
CI);
CI->replaceAllUsesWith(Or);
CI->eraseFromParent();
return true;
@ -1101,10 +1110,10 @@ struct LLVMMemCpyMoveOptzn : public LibCallOptimization {
}
// Cast source and dest to the right sized primitive and then load/store
CastInst* SrcCast =
new CastInst(src,PointerType::get(castType),src->getName()+".cast",ci);
CastInst* DestCast =
new CastInst(dest,PointerType::get(castType),dest->getName()+".cast",ci);
CastInst* SrcCast = CastInst::create(Instruction::BitCast,
src, PointerType::get(castType), src->getName()+".cast", ci);
CastInst* DestCast = CastInst::create(Instruction::BitCast,
dest, PointerType::get(castType),dest->getName()+".cast", ci);
LoadInst* LI = new LoadInst(SrcCast,SrcCast->getName()+".val",ci);
new StoreInst(LI, DestCast, ci);
ci->eraseFromParent();
@ -1213,8 +1222,8 @@ struct LLVMMemSetOptimization : public LibCallOptimization {
}
// Cast dest to the right sized primitive and then load/store
CastInst* DestCast =
new CastInst(dest,PointerType::get(castType),dest->getName()+".cast",ci);
CastInst* DestCast = CastInst::createInferredCast(
dest, PointerType::get(castType), dest->getName()+".cast", ci);
new StoreInst(ConstantInt::get(castType,fill_value),DestCast, ci);
ci->eraseFromParent();
return true;
@ -1356,8 +1365,8 @@ public:
Function* putchar_func = SLC.get_putchar();
if (!putchar_func)
return false;
CastInst* cast = new CastInst(ci->getOperand(2), Type::IntTy,
CI->getName()+".int", ci);
CastInst* cast = CastInst::createInferredCast(
ci->getOperand(2), Type::IntTy, CI->getName()+".int", ci);
new CallInst(putchar_func, cast, "", ci);
ci->replaceAllUsesWith(ConstantInt::get(Type::IntTy, 1));
break;
@ -1490,8 +1499,8 @@ public:
Function* fputc_func = SLC.get_fputc(FILEptr_type);
if (!fputc_func)
return false;
CastInst* cast = new CastInst(ci->getOperand(3), Type::IntTy,
CI->getName()+".int", ci);
CastInst* cast = CastInst::createInferredCast(
ci->getOperand(3), Type::IntTy, CI->getName()+".int", ci);
new CallInst(fputc_func,cast,ci->getOperand(1),"",ci);
ci->replaceAllUsesWith(ConstantInt::get(Type::IntTy,1));
break;
@ -1597,7 +1606,8 @@ public:
ConstantInt::get(Len->getType(), 1),
Len->getName()+"1", ci);
if (Len1->getType() != SLC.getIntPtrType())
Len1 = new CastInst(Len1, SLC.getIntPtrType(), Len1->getName(), ci);
Len1 = CastInst::createInferredCast(
Len1, SLC.getIntPtrType(), Len1->getName(), ci);
std::vector<Value*> args;
args.push_back(CastToCStr(ci->getOperand(1), *ci));
args.push_back(CastToCStr(ci->getOperand(3), *ci));
@ -1608,7 +1618,8 @@ public:
// The strlen result is the unincremented number of bytes in the string.
if (!ci->use_empty()) {
if (Len->getType() != ci->getType())
Len = new CastInst(Len, ci->getType(), Len->getName(), ci);
Len = CastInst::createInferredCast(
Len, ci->getType(), Len->getName(), ci);
ci->replaceAllUsesWith(Len);
}
ci->eraseFromParent();
@ -1616,7 +1627,8 @@ public:
}
case 'c': {
// sprintf(dest,"%c",chr) -> store chr, dest
CastInst* cast = new CastInst(ci->getOperand(3),Type::SByteTy,"char",ci);
CastInst* cast = CastInst::createInferredCast(
ci->getOperand(3), Type::SByteTy, "char", ci);
new StoreInst(cast, ci->getOperand(1), ci);
GetElementPtrInst* gep = new GetElementPtrInst(ci->getOperand(1),
ConstantInt::get(Type::UIntTy,1),ci->getOperand(1)->getName()+".end",
@ -1672,8 +1684,8 @@ public:
return false;
LoadInst* loadi = new LoadInst(ci->getOperand(1),
ci->getOperand(1)->getName()+".byte",ci);
CastInst* casti = new CastInst(loadi,Type::IntTy,
loadi->getName()+".int",ci);
CastInst* casti = CastInst::createInferredCast(
loadi, Type::IntTy, loadi->getName()+".int", ci);
new CallInst(fputc_func,casti,ci->getOperand(2),"",ci);
break;
}
@ -1726,18 +1738,16 @@ public:
}
// isdigit(c) -> (unsigned)c - '0' <= 9
CastInst* cast =
new CastInst(ci->getOperand(1),Type::UIntTy,
ci->getOperand(1)->getName()+".uint",ci);
CastInst* cast = CastInst::createInferredCast(ci->getOperand(1),
Type::UIntTy, ci->getOperand(1)->getName()+".uint", ci);
BinaryOperator* sub_inst = BinaryOperator::createSub(cast,
ConstantInt::get(Type::UIntTy,0x30),
ci->getOperand(1)->getName()+".sub",ci);
SetCondInst* setcond_inst = new SetCondInst(Instruction::SetLE,sub_inst,
ConstantInt::get(Type::UIntTy,9),
ci->getOperand(1)->getName()+".cmp",ci);
CastInst* c2 =
new CastInst(setcond_inst,Type::IntTy,
ci->getOperand(1)->getName()+".isdigit",ci);
CastInst* c2 = CastInst::createInferredCast(
setcond_inst, Type::IntTy, ci->getOperand(1)->getName()+".isdigit", ci);
ci->replaceAllUsesWith(c2);
ci->eraseFromParent();
return true;
@ -1759,12 +1769,14 @@ public:
// isascii(c) -> (unsigned)c < 128
Value *V = CI->getOperand(1);
if (V->getType()->isSigned())
V = new CastInst(V, V->getType()->getUnsignedVersion(), V->getName(), CI);
V = CastInst::createInferredCast(V, V->getType()->getUnsignedVersion(),
V->getName(), CI);
Value *Cmp = BinaryOperator::createSetLT(V, ConstantInt::get(V->getType(),
128),
V->getName()+".isascii", CI);
if (Cmp->getType() != CI->getType())
Cmp = new CastInst(Cmp, CI->getType(), Cmp->getName(), CI);
Cmp = CastInst::createInferredCast(
Cmp, CI->getType(), Cmp->getName(), CI);
CI->replaceAllUsesWith(Cmp);
CI->eraseFromParent();
return true;
@ -1858,9 +1870,10 @@ public:
Function *F = SLC.getModule()->getOrInsertFunction(CTTZName, ArgType,
ArgType, NULL);
Value *V = new CastInst(TheCall->getOperand(1), ArgType, "tmp", TheCall);
Value *V = CastInst::createInferredCast(
TheCall->getOperand(1), ArgType, "tmp", TheCall);
Value *V2 = new CallInst(F, V, "tmp", TheCall);
V2 = new CastInst(V2, Type::IntTy, "tmp", TheCall);
V2 = CastInst::createInferredCast(V2, Type::IntTy, "tmp", TheCall);
V2 = BinaryOperator::createAdd(V2, ConstantInt::get(Type::IntTy, 1),
"tmp", TheCall);
Value *Cond =
@ -1920,7 +1933,7 @@ struct UnaryDoubleFPOptimizer : public LibCallOptimization {
if (Cast->getOperand(0)->getType() == Type::FloatTy) {
Value *New = new CallInst((SLC.*FP)(), Cast->getOperand(0),
CI->getName(), CI);
New = new CastInst(New, Type::DoubleTy, CI->getName(), CI);
New = new FPExtInst(New, Type::DoubleTy, CI->getName(), CI);
CI->replaceAllUsesWith(New);
CI->eraseFromParent();
if (Cast->use_empty())
@ -2105,7 +2118,7 @@ bool getConstantStringLength(Value *V, uint64_t &len, ConstantArray **CA) {
Value *CastToCStr(Value *V, Instruction &IP) {
const Type *SBPTy = PointerType::get(Type::SByteTy);
if (V->getType() != SBPTy)
return new CastInst(V, SBPTy, V->getName(), &IP);
return CastInst::createInferredCast(V, SBPTy, V->getName(), &IP);
return V;
}

View File

@ -62,7 +62,8 @@ void llvm::InsertProfilingInitCall(Function *MainFn, const char *FnName,
case 2:
AI = MainFn->arg_begin(); ++AI;
if (AI->getType() != ArgVTy) {
InitCall->setOperand(2, new CastInst(AI, ArgVTy, "argv.cast", InitCall));
InitCall->setOperand(2,
CastInst::createInferredCast(AI, ArgVTy, "argv.cast", InitCall));
} else {
InitCall->setOperand(2, AI);
}
@ -73,10 +74,10 @@ void llvm::InsertProfilingInitCall(Function *MainFn, const char *FnName,
// init call instead.
if (AI->getType() != Type::IntTy) {
if (!AI->use_empty())
AI->replaceAllUsesWith(new CastInst(InitCall, AI->getType(), "",
InsertPos));
InitCall->setOperand(1, new CastInst(AI, Type::IntTy, "argc.cast",
InitCall));
AI->replaceAllUsesWith(
CastInst::createInferredCast(InitCall, AI->getType(), "", InsertPos));
InitCall->setOperand(1,
CastInst::createInferredCast(AI, Type::IntTy, "argc.cast", InitCall));
} else {
AI->replaceAllUsesWith(InitCall);
InitCall->setOperand(1, AI);

View File

@ -190,8 +190,7 @@ static inline bool TraceThisOpCode(unsigned opCode) {
//
return (opCode < Instruction::OtherOpsBegin &&
opCode != Instruction::Alloca &&
opCode != Instruction::PHI &&
opCode != Instruction::Cast);
opCode != Instruction::PHI && ! Instruction::isCast(opCode));
}
@ -251,7 +250,7 @@ static void InsertPrintInst(Value *V, BasicBlock *BB, Instruction *InsertBefore,
if (V && isa<PointerType>(V->getType()) && !DisablePtrHashing) {
const Type *SBP = PointerType::get(Type::SByteTy);
if (V->getType() != SBP) // Cast pointer to be sbyte*
V = new CastInst(V, SBP, "Hash_cast", InsertBefore);
V = new BitCastInst(V, SBP, "Hash_cast", InsertBefore);
std::vector<Value*> HashArgs(1, V);
V = new CallInst(HashPtrToSeqNum, HashArgs, "ptrSeqNum", InsertBefore);
@ -282,7 +281,7 @@ InsertReleaseInst(Value *V, BasicBlock *BB,
const Type *SBP = PointerType::get(Type::SByteTy);
if (V->getType() != SBP) // Cast pointer to be sbyte*
V = new CastInst(V, SBP, "RPSN_cast", InsertBefore);
V = CastInst::createInferredCast(V, SBP, "RPSN_cast", InsertBefore);
std::vector<Value*> releaseArgs(1, V);
new CallInst(ReleasePtrFunc, releaseArgs, "", InsertBefore);
@ -294,7 +293,7 @@ InsertRecordInst(Value *V, BasicBlock *BB,
Function* RecordPtrFunc) {
const Type *SBP = PointerType::get(Type::SByteTy);
if (V->getType() != SBP) // Cast pointer to be sbyte*
V = new CastInst(V, SBP, "RP_cast", InsertBefore);
V = CastInst::createInferredCast(V, SBP, "RP_cast", InsertBefore);
std::vector<Value*> releaseArgs(1, V);
new CallInst(RecordPtrFunc, releaseArgs, "", InsertBefore);

View File

@ -87,15 +87,6 @@ FunctionPass *llvm::createRaisePointerReferencesPass() {
return new RPR();
}
// isReinterpretingCast - Return true if the cast instruction specified will
// cause the operand to be "reinterpreted". A value is reinterpreted if the
// cast instruction would cause the underlying bits to change.
//
static inline bool isReinterpretingCast(const CastInst *CI) {
return!CI->getOperand(0)->getType()->isLosslesslyConvertibleTo(CI->getType());
}
bool RPR::PeepholeOptimize(BasicBlock *BB, BasicBlock::iterator &BI) {
Instruction *I = BI;
const TargetData &TD = getAnalysis<TargetData>();
@ -129,7 +120,7 @@ bool RPR::PeepholeOptimize(BasicBlock *BB, BasicBlock::iterator &BI) {
// Check to see if it's a cast of an instruction that does not depend on the
// specific type of the operands to do it's job.
if (!isReinterpretingCast(CI)) {
if (CI->isLosslessCast()) {
ValueTypeCache ConvertedTypes;
// Check to see if we can convert the source of the cast to match the
@ -238,7 +229,7 @@ bool RPR::PeepholeOptimize(BasicBlock *BB, BasicBlock::iterator &BI) {
Indices.push_back(Constant::getNullValue(Type::UIntTy));
// Did we find what we're looking for?
if (ElTy->isLosslesslyConvertibleTo(DestPointedTy)) break;
if (ElTy->canLosslesslyBitCastTo(DestPointedTy)) break;
// Nope, go a level deeper.
++Depth;
@ -257,9 +248,23 @@ bool RPR::PeepholeOptimize(BasicBlock *BB, BasicBlock::iterator &BI) {
Name, BI);
// Make the old cast instruction reference the new GEP instead of
// the old src value.
//
CI->setOperand(0, GEP);
// the old src value.
if (CI->getOperand(0)->getType() == GEP->getType()) {
// If the source types are the same we can safely replace the
// first operand of the CastInst because the opcode won't
// change as a result.
CI->setOperand(0, GEP);
} else {
// The existing and new operand 0 types are different so we must
// replace CI with a new CastInst so that we are assured to
// get the correct cast opcode.
CastInst *NewCI = CastInst::createInferredCast(
GEP, CI->getType(), CI->getName(), CI);
CI->replaceAllUsesWith(NewCI);
CI->eraseFromParent();
CI = NewCI;
BI = NewCI; // Don't let the iterator invalidate
}
PRINT_PEEPHOLE2("cast-for-first:out", *GEP, *CI);
++NumGEPInstFormed;
@ -273,7 +278,7 @@ bool RPR::PeepholeOptimize(BasicBlock *BB, BasicBlock::iterator &BI) {
Value *Pointer = SI->getPointerOperand();
// Peephole optimize the following instructions:
// %t = cast <T1>* %P to <T2> * ;; If T1 is losslessly convertible to T2
// %t = cast <T1>* %P to <T2> * ;; If T1 is losslessly castable to T2
// store <T2> %V, <T2>* %t
//
// Into:
@ -289,13 +294,14 @@ bool RPR::PeepholeOptimize(BasicBlock *BB, BasicBlock::iterator &BI) {
if (Value *CastSrc = CI->getOperand(0)) // CSPT = CastSrcPointerType
if (const PointerType *CSPT = dyn_cast<PointerType>(CastSrc->getType()))
// convertible types?
if (Val->getType()->isLosslesslyConvertibleTo(CSPT->getElementType())) {
if (Val->getType()->canLosslesslyBitCastTo(CSPT->getElementType()))
{
PRINT_PEEPHOLE3("st-src-cast:in ", *Pointer, *Val, *SI);
// Insert the new T cast instruction... stealing old T's name
std::string Name(CI->getName()); CI->setName("");
CastInst *NCI = new CastInst(Val, CSPT->getElementType(),
Name, BI);
CastInst *NCI = CastInst::create(Instruction::BitCast, Val,
CSPT->getElementType(), Name, BI);
// Replace the old store with a new one!
ReplaceInstWithInst(BB->getInstList(), BI,
@ -327,14 +333,16 @@ bool RPR::PeepholeOptimize(BasicBlock *BB, BasicBlock::iterator &BI) {
if (Value *CastSrc = CI->getOperand(0)) // CSPT = CastSrcPointerType
if (const PointerType *CSPT = dyn_cast<PointerType>(CastSrc->getType()))
// convertible types?
if (PtrElType->isLosslesslyConvertibleTo(CSPT->getElementType())) {
if (PtrElType->canLosslesslyBitCastTo(CSPT->getElementType())) {
PRINT_PEEPHOLE2("load-src-cast:in ", *Pointer, *LI);
// Create the new load instruction... loading the pre-casted value
LoadInst *NewLI = new LoadInst(CastSrc, LI->getName(), BI);
// Insert the new T cast instruction... stealing old T's name
CastInst *NCI = new CastInst(NewLI, LI->getType(), CI->getName());
CastInst *NCI =
CastInst::create(Instruction::BitCast, NewLI, LI->getType(),
CI->getName());
// Replace the old store with a new one!
ReplaceInstWithInst(BB->getInstList(), BI, NCI);
@ -366,15 +374,12 @@ bool RPR::PeepholeOptimize(BasicBlock *BB, BasicBlock::iterator &BI) {
// Create a new cast, inserting it right before the function call...
Value *NewCast;
Constant *ConstantCallSrc = 0;
if (Constant *CS = dyn_cast<Constant>(CI->getCalledValue()))
ConstantCallSrc = CS;
if (ConstantCallSrc)
NewCast = ConstantExpr::getCast(ConstantCallSrc, NewPFunTy);
NewCast = ConstantExpr::getBitCast(CS, NewPFunTy);
else
NewCast = new CastInst(CI->getCalledValue(), NewPFunTy,
CI->getCalledValue()->getName()+"_c",CI);
NewCast = CastInst::create(Instruction::BitCast, CI->getCalledValue(),
NewPFunTy,
CI->getCalledValue()->getName()+"_c", CI);
// Create a new call instruction...
CallInst *NewCall = new CallInst(NewCast,

View File

@ -523,9 +523,8 @@ void IndVarSimplify::runOnLoop(Loop *L) {
if (!InsertedSizes[IndVars[i].first->getType()->getPrimitiveSize()]) {
PHINode *PN = IndVars[i].first;
InsertedSizes[PN->getType()->getPrimitiveSize()] = true;
Instruction *New = new CastInst(IndVar,
PN->getType()->getUnsignedVersion(),
"indvar", InsertPt);
Instruction *New = CastInst::create(Instruction::Trunc, IndVar,
PN->getType()->getUnsignedVersion(), "indvar", InsertPt);
Rewriter.addInsertedValue(New, SE->getSCEV(New));
}
}

File diff suppressed because it is too large Load Diff

View File

@ -384,6 +384,7 @@ bool LICM::canSinkOrHoistInst(Instruction &I) {
return false;
}
// Otherwise these instructions are hoistable/sinkable
return isa<BinaryOperator>(I) || isa<ShiftInst>(I) || isa<CastInst>(I) ||
isa<SelectInst>(I) || isa<GetElementPtrInst>(I);
}

View File

@ -627,10 +627,9 @@ static bool isTargetConstant(const SCEVHandle &V, const TargetLowering *TLI) {
if (SCEVUnknown *SU = dyn_cast<SCEVUnknown>(V))
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(SU->getValue()))
if (CE->getOpcode() == Instruction::Cast) {
if (CE->getOpcode() == Instruction::PtrToInt) {
Constant *Op0 = CE->getOperand(0);
if (isa<GlobalValue>(Op0) &&
TLI &&
if (isa<GlobalValue>(Op0) && TLI &&
TLI->isLegalAddressImmediate(cast<GlobalValue>(Op0)))
return true;
}
@ -899,7 +898,7 @@ unsigned LoopStrengthReduce::CheckForIVReuse(const SCEVHandle &Stride,
// FIXME: Only handle base == 0 for now.
// Only reuse previous IV if it would not require a type conversion.
if (isZero(II->Base) &&
II->Base->getType()->isLosslesslyConvertibleTo(Ty)) {
II->Base->getType()->canLosslesslyBitCastTo(Ty)) {
IV = *II;
return Scale;
}
@ -1044,9 +1043,10 @@ void LoopStrengthReduce::StrengthReduceStridedIVUsers(const SCEVHandle &Stride,
if (!C ||
(!C->isNullValue() &&
!isTargetConstant(SCEVUnknown::get(CommonBaseV), TLI)))
// We want the common base emitted into the preheader!
CommonBaseV = new CastInst(CommonBaseV, CommonBaseV->getType(),
"commonbase", PreInsertPt);
// We want the common base emitted into the preheader! This is just
// using cast as a copy so BitCast (no-op cast) is appropriate
CommonBaseV = new BitCastInst(CommonBaseV, CommonBaseV->getType(),
"commonbase", PreInsertPt);
}
// We want to emit code for users inside the loop first. To do this, we
@ -1092,12 +1092,13 @@ void LoopStrengthReduce::StrengthReduceStridedIVUsers(const SCEVHandle &Stride,
// If BaseV is a constant other than 0, make sure that it gets inserted into
// the preheader, instead of being forward substituted into the uses. We do
// this by forcing a noop cast to be inserted into the preheader in this
// case.
// this by forcing a BitCast (noop cast) to be inserted into the preheader
// in this case.
if (Constant *C = dyn_cast<Constant>(BaseV)) {
if (!C->isNullValue() && !isTargetConstant(Base, TLI)) {
// We want this constant emitted into the preheader!
BaseV = new CastInst(BaseV, BaseV->getType(), "preheaderinsert",
// We want this constant emitted into the preheader! This is just
// using cast as a copy so BitCast (no-op cast) is appropriate
BaseV = new BitCastInst(BaseV, BaseV->getType(), "preheaderinsert",
PreInsertPt);
}
}

View File

@ -139,13 +139,15 @@ bool LowerGC::doInitialization(Module &M) {
}
/// Coerce - If the specified operand number of the specified instruction does
/// not have the specified type, insert a cast.
/// not have the specified type, insert a cast. Note that this only uses BitCast
/// because the types involved are all pointers.
static void Coerce(Instruction *I, unsigned OpNum, Type *Ty) {
if (I->getOperand(OpNum)->getType() != Ty) {
if (Constant *C = dyn_cast<Constant>(I->getOperand(OpNum)))
I->setOperand(OpNum, ConstantExpr::getCast(C, Ty));
I->setOperand(OpNum, ConstantExpr::getBitCast(C, Ty));
else {
CastInst *CI = new CastInst(I->getOperand(OpNum), Ty, "", I);
CastInst *CI =
CastInst::createInferredCast(I->getOperand(OpNum), Ty, "", I);
I->setOperand(OpNum, CI);
}
}
@ -196,7 +198,9 @@ bool LowerGC::runOnFunction(Function &F) {
CallInst *NC = new CallInst(GCRead, CI->getOperand(1),
CI->getOperand(2),
CI->getName(), CI);
Value *NV = new CastInst(NC, CI->getType(), "", CI);
// These functions only deal with ptr type results so BitCast
// is the correct kind of cast (no-op cast).
Value *NV = new BitCastInst(NC, CI->getType(), "", CI);
CI->replaceAllUsesWith(NV);
BB->getInstList().erase(CI);
CI = NC;
@ -273,7 +277,7 @@ bool LowerGC::runOnFunction(Function &F) {
// Now that the record is all initialized, store the pointer into the global
// pointer.
Value *C = new CastInst(AI, PointerType::get(MainRootRecordType), "", IP);
Value *C = new BitCastInst(AI, PointerType::get(MainRootRecordType), "", IP);
new StoreInst(C, RootChain, IP);
// On exit from the function we have to remove the entry from the GC root

View File

@ -212,11 +212,9 @@ void LowerPacked::visitLoadInst(LoadInst& LI)
PKT->getNumElements());
PointerType* APT = PointerType::get(AT);
// Cast the packed type to an array
Value* array = new CastInst(LI.getPointerOperand(),
APT,
LI.getName() + ".a",
&LI);
// Cast the pointer to packed type to an equivalent array
Value* array = new BitCastInst(LI.getPointerOperand(), APT,
LI.getName() + ".a", &LI);
// Convert this load into num elements number of loads
std::vector<Value*> values;
@ -234,10 +232,8 @@ void LowerPacked::visitLoadInst(LoadInst& LI)
&LI);
// generate the new load and save the result in packedToScalar map
values.push_back(new LoadInst(val,
LI.getName()+"."+utostr(i),
LI.isVolatile(),
&LI));
values.push_back(new LoadInst(val, LI.getName()+"."+utostr(i),
LI.isVolatile(), &LI));
}
setValues(&LI,values);
@ -286,11 +282,10 @@ void LowerPacked::visitStoreInst(StoreInst& SI)
PKT->getNumElements());
PointerType* APT = PointerType::get(AT);
// cast the packed to an array type
Value* array = new CastInst(SI.getPointerOperand(),
APT,
"store.ge.a.",
&SI);
// Cast the pointer to packed to an array of equivalent type
Value* array = new BitCastInst(SI.getPointerOperand(), APT,
"store.ge.a.", &SI);
std::vector<Value*>& values = getValues(SI.getOperand(0));
assert((values.size() == PKT->getNumElements()) &&

View File

@ -624,7 +624,8 @@ void SROA::ConvertUsesToScalar(Value *Ptr, AllocaInst *NewAI, unsigned Offset) {
assert((NV->getType()->isInteger() ||
isa<PointerType>(NV->getType())) && "Unknown promotion!");
}
NV = new CastInst(NV, LI->getType(), LI->getName(), LI);
NV = CastInst::createInferredCast(NV, LI->getType(), LI->getName(),
LI);
}
}
LI->replaceAllUsesWith(NV);
@ -646,12 +647,12 @@ void SROA::ConvertUsesToScalar(Value *Ptr, AllocaInst *NewAI, unsigned Offset) {
ConstantInt::get(Type::UIntTy, Elt),
"tmp", SI);
} else {
// If SV is signed, convert it to unsigned, so that the next cast zero
// extends the value.
// Always zero extend the value.
if (SV->getType()->isSigned())
SV = new CastInst(SV, SV->getType()->getUnsignedVersion(),
SV->getName(), SI);
SV = new CastInst(SV, Old->getType(), SV->getName(), SI);
SV = CastInst::createInferredCast(SV,
SV->getType()->getUnsignedVersion(), SV->getName(), SI);
SV = CastInst::createInferredCast(SV, Old->getType(), SV->getName(),
SI);
if (Offset && Offset < TD.getTypeSize(SV->getType())*8)
SV = new ShiftInst(Instruction::Shl, SV,
ConstantInt::get(Type::UByteTy, Offset),

View File

@ -122,8 +122,19 @@ Constant *llvm::ConstantFoldInstOperands(unsigned Opc, const Type *DestTy,
case Instruction::LShr:
case Instruction::AShr:
return ConstantExpr::get(Opc, Ops[0], Ops[1]);
case Instruction::Cast:
return ConstantExpr::getCast(Ops[0], DestTy);
case Instruction::Trunc:
case Instruction::ZExt:
case Instruction::SExt:
case Instruction::FPTrunc:
case Instruction::FPExt:
case Instruction::UIToFP:
case Instruction::SIToFP:
case Instruction::FPToUI:
case Instruction::FPToSI:
case Instruction::PtrToInt:
case Instruction::IntToPtr:
case Instruction::BitCast:
return ConstantExpr::getCast(Opc, Ops[0], DestTy);
case Instruction::Select:
return ConstantExpr::getSelect(Ops[0], Ops[1], Ops[2]);
case Instruction::ExtractElement:

View File

@ -134,7 +134,7 @@ bool LowerAllocations::runOnBasicBlock(BasicBlock &BB) {
} else {
Value *Scale = MI->getOperand(0);
if (Scale->getType() != IntPtrTy)
Scale = new CastInst(Scale, IntPtrTy, "", I);
Scale = CastInst::createInferredCast(Scale, IntPtrTy, "", I);
// Multiply it by the array size if necessary...
MallocArg = BinaryOperator::create(Instruction::Mul, Scale,
@ -148,10 +148,13 @@ bool LowerAllocations::runOnBasicBlock(BasicBlock &BB) {
if (MallocFTy->getNumParams() > 0 || MallocFTy->isVarArg()) {
if (MallocFTy->isVarArg()) {
if (MallocArg->getType() != IntPtrTy)
MallocArg = new CastInst(MallocArg, IntPtrTy, "", I);
MallocArg = CastInst::createInferredCast(MallocArg, IntPtrTy, "",
I);
} else if (MallocFTy->getNumParams() > 0 &&
MallocFTy->getParamType(0) != Type::UIntTy)
MallocArg = new CastInst(MallocArg, MallocFTy->getParamType(0), "",I);
MallocArg =
CastInst::createInferredCast(MallocArg, MallocFTy->getParamType(0),
"",I);
MallocArgs.push_back(MallocArg);
}
@ -166,7 +169,7 @@ bool LowerAllocations::runOnBasicBlock(BasicBlock &BB) {
// Create a cast instruction to convert to the right type...
Value *MCast;
if (MCall->getType() != Type::VoidTy)
MCast = new CastInst(MCall, MI->getType(), "", I);
MCast = CastInst::createInferredCast(MCall, MI->getType(), "", I);
else
MCast = Constant::getNullValue(MI->getType());
@ -183,7 +186,8 @@ bool LowerAllocations::runOnBasicBlock(BasicBlock &BB) {
Value *MCast = FI->getOperand(0);
if (FreeFTy->getNumParams() > 0 &&
FreeFTy->getParamType(0) != MCast->getType())
MCast = new CastInst(MCast, FreeFTy->getParamType(0), "", I);
MCast = CastInst::createInferredCast(MCast, FreeFTy->getParamType(0),
"", I);
FreeArgs.push_back(MCast);
}

View File

@ -326,7 +326,7 @@ splitLiveRangesLiveAcrossInvokes(std::vector<InvokeInst*> &Invokes) {
Function *F = Invokes.back()->getParent()->getParent();
// To avoid having to handle incoming arguments specially, we lower each arg
// to a copy instruction in the entry block. This ensure that the argument
// to a copy instruction in the entry block. This ensures that the argument
// value itself cannot be live across the entry block.
BasicBlock::iterator AfterAllocaInsertPt = F->begin()->begin();
while (isa<AllocaInst>(AfterAllocaInsertPt) &&
@ -334,10 +334,16 @@ splitLiveRangesLiveAcrossInvokes(std::vector<InvokeInst*> &Invokes) {
++AfterAllocaInsertPt;
for (Function::arg_iterator AI = F->arg_begin(), E = F->arg_end();
AI != E; ++AI) {
CastInst *NC = new CastInst(AI, AI->getType(), AI->getName()+".tmp",
AfterAllocaInsertPt);
// This is always a no-op cast because we're casting AI to AI->getType() so
// src and destination types are identical. BitCast is the only possibility.
CastInst *NC = new BitCastInst(
AI, AI->getType(), AI->getName()+".tmp", AfterAllocaInsertPt);
AI->replaceAllUsesWith(NC);
NC->setOperand(0, AI);
// Normally its is forbidden to replace a CastInst's operand because it
// could cause the opcode to reflect an illegal conversion. However, we're
// replacing it here with the same value it was constructed with to simply
// make NC its user.
NC->setOperand(0, AI);
}
// Finally, scan the code looking for instructions with bad live ranges.

View File

@ -425,11 +425,6 @@ static Value *GatherConstantSetNEs(Value *V, std::vector<ConstantInt*> &Values){
Values.push_back(C);
return Inst->getOperand(1);
}
} else if (Inst->getOpcode() == Instruction::Cast) {
// Cast of X to bool is really a comparison against zero.
assert(Inst->getType() == Type::BoolTy && "Can only handle bool values!");
Values.push_back(ConstantInt::get(Inst->getOperand(0)->getType(), 0));
return Inst->getOperand(0);
} else if (Inst->getOpcode() == Instruction::And) {
if (Value *LHS = GatherConstantSetNEs(Inst->getOperand(0), Values))
if (Value *RHS = GatherConstantSetNEs(Inst->getOperand(1), Values))

View File

@ -541,10 +541,11 @@ static void WriteConstantInt(std::ostream &Out, const Constant *CV,
Out << ", ";
}
if (CE->getOpcode() == Instruction::Cast) {
if (CE->isCast()) {
Out << " to ";
printTypeInt(Out, CE->getType(), TypeTable);
}
Out << ')';
} else {

View File

@ -206,8 +206,8 @@ static Value *CastArg(Value *Arg, const Type *Ty, Instruction *InsertBefore) {
if (Constant *C = dyn_cast<Constant>(Arg)) {
return ConstantExpr::getCast(C, Ty);
} else {
Value *Cast = new CastInst(Arg, Ty, "autoupgrade_cast", InsertBefore);
return Cast;
return CastInst::createInferredCast(Arg, Ty, "autoupgrade_cast",
InsertBefore);
}
}
@ -261,8 +261,8 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
Instruction *RetVal = NewCI;
if (F->getReturnType() != NewFn->getReturnType()) {
RetVal = new CastInst(NewCI, F->getReturnType(),
NewCI->getName(), CI);
RetVal =
new BitCastInst(NewCI, F->getReturnType(), NewCI->getName(), CI);
NewCI->moveBefore(RetVal);
}

View File

@ -507,7 +507,7 @@ struct VISIBILITY_HIDDEN DirectIntRules
// Casting operators. ick
#define DEF_CAST(TYPE, CLASS, CTYPE) \
static Constant *CastTo##TYPE (const ConstantInt *V) { \
return CLASS::get(Type::TYPE##Ty, (CTYPE)(BuiltinType)V->getZExtValue()); \
return CLASS::get(Type::TYPE##Ty, (CTYPE)((BuiltinType)V->getZExtValue()));\
}
DEF_CAST(Bool , ConstantBool, bool)
@ -721,15 +721,6 @@ ConstRules &ConstRules::get(const Constant *V1, const Constant *V2) {
//===----------------------------------------------------------------------===//
// ConstantFold*Instruction Implementations
//===----------------------------------------------------------------------===//
//
// These methods contain the special case hackery required to symbolically
// evaluate some constant expression cases, and use the ConstantRules class to
// evaluate normal constants.
//
static unsigned getSize(const Type *Ty) {
unsigned S = Ty->getPrimitiveSize();
return S ? S : 8; // Treat pointers at 8 bytes
}
/// CastConstantPacked - Convert the specified ConstantPacked node to the
/// specified packed type. At this point, we know that the elements of the
@ -746,17 +737,20 @@ static Constant *CastConstantPacked(ConstantPacked *CP,
if (SrcNumElts == DstNumElts) {
std::vector<Constant*> Result;
// If the src and dest elements are both integers, just cast each one
// which will do the appropriate bit-convert.
if (SrcEltTy->isIntegral() && DstEltTy->isIntegral()) {
// If the src and dest elements are both integers, or both floats, we can
// just BitCast each element because the elements are the same size.
if ((SrcEltTy->isIntegral() && DstEltTy->isIntegral()) ||
(SrcEltTy->isFloatingPoint() && DstEltTy->isFloatingPoint())) {
for (unsigned i = 0; i != SrcNumElts; ++i)
Result.push_back(ConstantExpr::getCast(CP->getOperand(i),
DstEltTy));
Result.push_back(
ConstantExpr::getCast(Instruction::BitCast, CP->getOperand(1),
DstEltTy));
return ConstantPacked::get(Result);
}
// If this is an int-to-fp cast ..
if (SrcEltTy->isIntegral()) {
// Otherwise, this is an int-to-fp cast.
// Ensure that it is int-to-fp cast
assert(DstEltTy->isFloatingPoint());
if (DstEltTy->getTypeID() == Type::DoubleTyID) {
for (unsigned i = 0; i != SrcNumElts; ++i) {
@ -805,34 +799,50 @@ static Constant *CastConstantPacked(ConstantPacked *CP,
return 0;
}
/// This function determines which opcode to use to fold two constant cast
/// expressions together. It uses CastInst::isEliminableCastPair to determine
/// the opcode. Consequently its just a wrapper around that function.
/// @Determine if it is valid to fold a cast of a cast
static unsigned
foldConstantCastPair(
unsigned opc, ///< opcode of the second cast constant expression
const ConstantExpr*Op, ///< the first cast constant expression
const Type *DstTy ///< desintation type of the first cast
) {
assert(Op && Op->isCast() && "Can't fold cast of cast without a cast!");
assert(DstTy && DstTy->isFirstClassType() && "Invalid cast destination type");
assert(CastInst::isCast(opc) && "Invalid cast opcode");
// The the types and opcodes for the two Cast constant expressions
const Type *SrcTy = Op->getOperand(0)->getType();
const Type *MidTy = Op->getType();
Instruction::CastOps firstOp = Instruction::CastOps(Op->getOpcode());
Instruction::CastOps secondOp = Instruction::CastOps(opc);
Constant *llvm::ConstantFoldCastInstruction(const Constant *V,
// Let CastInst::isEliminableCastPair do the heavy lifting.
return CastInst::isEliminableCastPair(firstOp, secondOp, SrcTy, MidTy, DstTy,
Type::ULongTy);
}
Constant *llvm::ConstantFoldCastInstruction(unsigned opc, const Constant *V,
const Type *DestTy) {
if (V->getType() == DestTy) return (Constant*)V;
const Type *SrcTy = V->getType();
// Cast of a global address to boolean is always true.
if (isa<GlobalValue>(V)) {
if (DestTy == Type::BoolTy)
// FIXME: When we support 'external weak' references, we have to prevent
// this transformation from happening. This code will need to be updated
// to ignore external weak symbols when we support it.
return ConstantBool::getTrue();
} else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
if (CE->getOpcode() == Instruction::Cast) {
Constant *Op = const_cast<Constant*>(CE->getOperand(0));
// Try to not produce a cast of a cast, which is almost always redundant.
if (!Op->getType()->isFloatingPoint() &&
!CE->getType()->isFloatingPoint() &&
!DestTy->isFloatingPoint()) {
unsigned S1 = getSize(Op->getType()), S2 = getSize(CE->getType());
unsigned S3 = getSize(DestTy);
if (Op->getType() == DestTy && S3 >= S2)
return Op;
if (S1 >= S2 && S2 >= S3)
return ConstantExpr::getCast(Op, DestTy);
if (S1 <= S2 && S2 >= S3 && S1 <= S3)
return ConstantExpr::getCast(Op, DestTy);
}
// Handle some simple cases
if (SrcTy == DestTy)
return (Constant*)V; // no-op cast
if (isa<UndefValue>(V))
return UndefValue::get(DestTy);
// If the cast operand is a constant expression, there's a few things we can
// do to try to simplify it.
if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
if (CE->isCast()) {
// Try hard to fold cast of cast because they are almost always
// eliminable.
if (unsigned newOpc = foldConstantCastPair(opc, CE, DestTy))
return ConstantExpr::getCast(newOpc, CE->getOperand(0), DestTy);
} else if (CE->getOpcode() == Instruction::GetElementPtr) {
// If all of the indexes in the GEP are null values, there is no pointer
// adjustment going on. We might as well cast the source pointer.
@ -845,69 +855,132 @@ Constant *llvm::ConstantFoldCastInstruction(const Constant *V,
if (isAllNull)
return ConstantExpr::getCast(CE->getOperand(0), DestTy);
}
} else if (isa<UndefValue>(V)) {
return UndefValue::get(DestTy);
}
// Check to see if we are casting an pointer to an aggregate to a pointer to
// the first element. If so, return the appropriate GEP instruction.
if (const PointerType *PTy = dyn_cast<PointerType>(V->getType()))
if (const PointerType *DPTy = dyn_cast<PointerType>(DestTy)) {
std::vector<Value*> IdxList;
IdxList.push_back(Constant::getNullValue(Type::IntTy));
const Type *ElTy = PTy->getElementType();
while (ElTy != DPTy->getElementType()) {
if (const StructType *STy = dyn_cast<StructType>(ElTy)) {
if (STy->getNumElements() == 0) break;
ElTy = STy->getElementType(0);
IdxList.push_back(Constant::getNullValue(Type::UIntTy));
} else if (const SequentialType *STy = dyn_cast<SequentialType>(ElTy)) {
if (isa<PointerType>(ElTy)) break; // Can't index into pointers!
ElTy = STy->getElementType();
IdxList.push_back(IdxList[0]);
} else {
break;
}
}
// We actually have to do a cast now, but first, we might need to fix up
// the value of the operand.
switch (opc) {
case Instruction::FPTrunc:
case Instruction::Trunc:
case Instruction::FPExt:
break; // floating point input & output, no fixup needed
case Instruction::FPToUI: {
ConstRules &Rules = ConstRules::get(V, V);
V = Rules.castToULong(V); // make sure we get an unsigned value first
break;
}
case Instruction::FPToSI: {
ConstRules &Rules = ConstRules::get(V, V);
V = Rules.castToLong(V); // make sure we get a signed value first
break;
}
case Instruction::IntToPtr: //always treated as unsigned
case Instruction::UIToFP:
case Instruction::ZExt:
// A ZExt always produces an unsigned value so we need to cast the value
// now before we try to cast it to the destination type
if (isa<ConstantInt>(V))
V = ConstantInt::get(SrcTy->getUnsignedVersion(),
cast<ConstantIntegral>(V)->getZExtValue());
break;
case Instruction::SIToFP:
case Instruction::SExt:
// A SExt always produces a signed value so we need to cast the value
// now before we try to cast it to the destiniation type.
if (isa<ConstantInt>(V))
V = ConstantInt::get(SrcTy->getSignedVersion(),
cast<ConstantIntegral>(V)->getSExtValue());
break;
if (ElTy == DPTy->getElementType())
return ConstantExpr::getGetElementPtr(const_cast<Constant*>(V),IdxList);
case Instruction::PtrToInt:
// Cast of a global address to boolean is always true.
if (isa<GlobalValue>(V)) {
if (DestTy == Type::BoolTy)
// FIXME: When we support 'external weak' references, we have to
// prevent this transformation from happening. This code will need
// to be updated to ignore external weak symbols when we support it.
return ConstantBool::getTrue();
}
// Handle casts from one packed constant to another. We know that the src and
// dest type have the same size.
if (const PackedType *DestPTy = dyn_cast<PackedType>(DestTy)) {
if (const PackedType *SrcTy = dyn_cast<PackedType>(V->getType())) {
assert(DestPTy->getElementType()->getPrimitiveSizeInBits() *
DestPTy->getNumElements() ==
SrcTy->getElementType()->getPrimitiveSizeInBits() *
SrcTy->getNumElements() && "Not cast between same sized vectors!");
if (isa<ConstantAggregateZero>(V))
return Constant::getNullValue(DestTy);
if (isa<UndefValue>(V))
return UndefValue::get(DestTy);
if (const ConstantPacked *CP = dyn_cast<ConstantPacked>(V)) {
// This is a cast from a ConstantPacked of one type to a ConstantPacked
// of another type. Check to see if all elements of the input are
// simple.
bool AllSimpleConstants = true;
for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i) {
if (!isa<ConstantInt>(CP->getOperand(i)) &&
!isa<ConstantFP>(CP->getOperand(i))) {
AllSimpleConstants = false;
break;
case Instruction::BitCast:
// Check to see if we are casting a pointer to an aggregate to a pointer to
// the first element. If so, return the appropriate GEP instruction.
if (const PointerType *PTy = dyn_cast<PointerType>(V->getType()))
if (const PointerType *DPTy = dyn_cast<PointerType>(DestTy)) {
std::vector<Value*> IdxList;
IdxList.push_back(Constant::getNullValue(Type::IntTy));
const Type *ElTy = PTy->getElementType();
while (ElTy != DPTy->getElementType()) {
if (const StructType *STy = dyn_cast<StructType>(ElTy)) {
if (STy->getNumElements() == 0) break;
ElTy = STy->getElementType(0);
IdxList.push_back(Constant::getNullValue(Type::UIntTy));
} else if (const SequentialType *STy =
dyn_cast<SequentialType>(ElTy)) {
if (isa<PointerType>(ElTy)) break; // Can't index into pointers!
ElTy = STy->getElementType();
IdxList.push_back(IdxList[0]);
} else {
break;
}
}
// If all of the elements are simple constants, we can fold this.
if (AllSimpleConstants)
return CastConstantPacked(const_cast<ConstantPacked*>(CP), DestPTy);
if (ElTy == DPTy->getElementType())
return ConstantExpr::getGetElementPtr(
const_cast<Constant*>(V),IdxList);
}
// Handle casts from one packed constant to another. We know that the src
// and dest type have the same size (otherwise its an illegal cast).
if (const PackedType *DestPTy = dyn_cast<PackedType>(DestTy)) {
if (const PackedType *SrcTy = dyn_cast<PackedType>(V->getType())) {
assert(DestPTy->getBitWidth() == SrcTy->getBitWidth() &&
"Not cast between same sized vectors!");
// First, check for null and undef
if (isa<ConstantAggregateZero>(V))
return Constant::getNullValue(DestTy);
if (isa<UndefValue>(V))
return UndefValue::get(DestTy);
if (const ConstantPacked *CP = dyn_cast<ConstantPacked>(V)) {
// This is a cast from a ConstantPacked of one type to a
// ConstantPacked of another type. Check to see if all elements of
// the input are simple.
bool AllSimpleConstants = true;
for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i) {
if (!isa<ConstantInt>(CP->getOperand(i)) &&
!isa<ConstantFP>(CP->getOperand(i))) {
AllSimpleConstants = false;
break;
}
}
// If all of the elements are simple constants, we can fold this.
if (AllSimpleConstants)
return CastConstantPacked(const_cast<ConstantPacked*>(CP), DestPTy);
}
}
}
// Handle sign conversion for integer no-op casts. We need to cast the
// value to the correct signedness before we try to cast it to the
// destination type. Be careful to do this only for integer types.
if (isa<ConstantIntegral>(V) && SrcTy->isInteger()) {
if (SrcTy->isSigned())
V = ConstantInt::get(SrcTy->getUnsignedVersion(),
cast<ConstantIntegral>(V)->getZExtValue());
else
V = ConstantInt::get(SrcTy->getSignedVersion(),
cast<ConstantIntegral>(V)->getSExtValue());
}
break;
default:
assert(!"Invalid CE CastInst opcode");
break;
}
// Okay, no more folding possible, time to cast
ConstRules &Rules = ConstRules::get(V, V);
switch (DestTy->getTypeID()) {
case Type::BoolTyID: return Rules.castToBool(V);
case Type::UByteTyID: return Rules.castToUByte(V);
@ -922,6 +995,7 @@ Constant *llvm::ConstantFoldCastInstruction(const Constant *V,
case Type::DoubleTyID: return Rules.castToDouble(V);
case Type::PointerTyID:
return Rules.castToPointer(V, cast<PointerType>(DestTy));
// what about packed ?
default: return 0;
}
}
@ -1049,15 +1123,22 @@ static bool isMaybeZeroSizedType(const Type *Ty) {
static int IdxCompare(Constant *C1, Constant *C2, const Type *ElTy) {
if (C1 == C2) return 0;
// Ok, we found a different index. Are either of the operands
// ConstantExprs? If so, we can't do anything with them.
// Ok, we found a different index. Are either of the operands ConstantExprs?
// If so, we can't do anything with them.
if (!isa<ConstantInt>(C1) || !isa<ConstantInt>(C2))
return -2; // don't know!
// Ok, we have two differing integer indices. Sign extend them to be the same
// type. Long is always big enough, so we use it.
C1 = ConstantExpr::getSignExtend(C1, Type::LongTy);
C2 = ConstantExpr::getSignExtend(C2, Type::LongTy);
if (C1->getType() != Type::LongTy && C1->getType() != Type::ULongTy)
C1 = ConstantExpr::getSignExtend(C1, Type::LongTy);
else
C1 = ConstantExpr::getBitCast(C1, Type::LongTy);
if (C2->getType() != Type::LongTy && C1->getType() != Type::ULongTy)
C2 = ConstantExpr::getSignExtend(C2, Type::LongTy);
else
C2 = ConstantExpr::getBitCast(C2, Type::LongTy);
if (C1 == C2) return 0; // Are they just differing types?
// If the type being indexed over is really just a zero sized type, there is
@ -1141,7 +1222,19 @@ static Instruction::BinaryOps evaluateRelation(Constant *V1, Constant *V2) {
Constant *CE1Op0 = CE1->getOperand(0);
switch (CE1->getOpcode()) {
case Instruction::Cast:
case Instruction::Trunc:
case Instruction::FPTrunc:
case Instruction::FPExt:
case Instruction::FPToUI:
case Instruction::FPToSI:
break; // We don't do anything with floating point.
case Instruction::ZExt:
case Instruction::SExt:
case Instruction::UIToFP:
case Instruction::SIToFP:
case Instruction::PtrToInt:
case Instruction::IntToPtr:
case Instruction::BitCast:
// If the cast is not actually changing bits, and the second operand is a
// null pointer, do the comparison with the pre-casted value.
if (V2->isNullValue() &&
@ -1154,8 +1247,7 @@ static Instruction::BinaryOps evaluateRelation(Constant *V1, Constant *V2) {
// important for things like "seteq (cast 4 to int*), (cast 5 to int*)",
// which happens a lot in compilers with tagged integers.
if (ConstantExpr *CE2 = dyn_cast<ConstantExpr>(V2))
if (isa<PointerType>(CE1->getType()) &&
CE2->getOpcode() == Instruction::Cast &&
if (isa<PointerType>(CE1->getType()) && CE2->isCast() &&
CE1->getOperand(0)->getType() == CE2->getOperand(0)->getType() &&
CE1->getOperand(0)->getType()->isIntegral()) {
return evaluateRelation(CE1->getOperand(0), CE2->getOperand(0));
@ -1423,8 +1515,7 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
if (cast<ConstantIntegral>(V2)->isAllOnesValue())
return const_cast<Constant*>(V1); // X & -1 == X
if (V2->isNullValue()) return const_cast<Constant*>(V2); // X & 0 == 0
if (CE1->getOpcode() == Instruction::Cast &&
isa<GlobalValue>(CE1->getOperand(0))) {
if (CE1->isCast() && isa<GlobalValue>(CE1->getOperand(0))) {
GlobalValue *CPR = cast<GlobalValue>(CE1->getOperand(0));
// Functions are at least 4-byte aligned. If and'ing the address of a
@ -1566,8 +1657,7 @@ Constant *llvm::ConstantFoldGetElementPtr(const Constant *C,
// long 0, long 0)
// To: int* getelementptr ([3 x int]* %X, long 0, long 0)
//
if (CE->getOpcode() == Instruction::Cast && IdxList.size() > 1 &&
Idx0->isNullValue())
if (CE->isCast() && IdxList.size() > 1 && Idx0->isNullValue())
if (const PointerType *SPT =
dyn_cast<PointerType>(CE->getOperand(0)->getType()))
if (const ArrayType *SAT = dyn_cast<ArrayType>(SPT->getElementType()))

View File

@ -27,7 +27,11 @@ namespace llvm {
class Type;
// Constant fold various types of instruction...
Constant *ConstantFoldCastInstruction(const Constant *V, const Type *DestTy);
Constant *ConstantFoldCastInstruction(
unsigned opcode, ///< The opcode of the cast
const Constant *V, ///< The source constant
const Type *DestTy ///< The destination type
);
Constant *ConstantFoldSelectInstruction(const Constant *Cond,
const Constant *V1,
const Constant *V2);

View File

@ -27,7 +27,11 @@ namespace llvm {
class Type;
// Constant fold various types of instruction...
Constant *ConstantFoldCastInstruction(const Constant *V, const Type *DestTy);
Constant *ConstantFoldCastInstruction(
unsigned opcode, ///< The opcode of the cast
const Constant *V, ///< The source constant
const Type *DestTy ///< The destination type
);
Constant *ConstantFoldSelectInstruction(const Constant *Cond,
const Constant *V1,
const Constant *V2);

View File

@ -427,6 +427,14 @@ struct VISIBILITY_HIDDEN GetElementPtrConstantExpr : public ConstantExpr {
};
}
// Utility function for determining if a ConstantExpr is a CastOp or not. This
// can't be inline because we don't want to #include Instruction.h into
// Constant.h
bool ConstantExpr::isCast() const {
return Instruction::isCast(getOpcode());
}
/// ConstantExpr::get* - Return some common constants without having to
/// specify the full Instruction::OPCODE identifier.
///
@ -507,8 +515,8 @@ Constant *ConstantExpr::getAShr(Constant *C1, Constant *C2) {
/// getWithOperandReplaced - Return a constant expression identical to this
/// one, but with the specified operand set to the specified value.
Constant *ConstantExpr::getWithOperandReplaced(unsigned OpNo,
Constant *Op) const {
Constant *
ConstantExpr::getWithOperandReplaced(unsigned OpNo, Constant *Op) const {
assert(OpNo < getNumOperands() && "Operand num is out of range!");
assert(Op->getType() == getOperand(OpNo)->getType() &&
"Replacing operand with value of different type!");
@ -517,8 +525,19 @@ Constant *ConstantExpr::getWithOperandReplaced(unsigned OpNo,
Constant *Op0, *Op1, *Op2;
switch (getOpcode()) {
case Instruction::Cast:
return ConstantExpr::getCast(Op, getType());
case Instruction::Trunc:
case Instruction::ZExt:
case Instruction::SExt:
case Instruction::FPTrunc:
case Instruction::FPExt:
case Instruction::UIToFP:
case Instruction::SIToFP:
case Instruction::FPToUI:
case Instruction::FPToSI:
case Instruction::PtrToInt:
case Instruction::IntToPtr:
case Instruction::BitCast:
return ConstantExpr::getCast(getOpcode(), Op, getType());
case Instruction::Select:
Op0 = (OpNo == 0) ? Op : getOperand(0);
Op1 = (OpNo == 1) ? Op : getOperand(1);
@ -571,8 +590,19 @@ getWithOperands(const std::vector<Constant*> &Ops) const {
return const_cast<ConstantExpr*>(this);
switch (getOpcode()) {
case Instruction::Cast:
return ConstantExpr::getCast(Ops[0], getType());
case Instruction::Trunc:
case Instruction::ZExt:
case Instruction::SExt:
case Instruction::FPTrunc:
case Instruction::FPExt:
case Instruction::UIToFP:
case Instruction::SIToFP:
case Instruction::FPToUI:
case Instruction::FPToSI:
case Instruction::PtrToInt:
case Instruction::IntToPtr:
case Instruction::BitCast:
return ConstantExpr::getCast(getOpcode(), Ops[0], getType());
case Instruction::Select:
return ConstantExpr::getSelect(Ops[0], Ops[1], Ops[2]);
case Instruction::InsertElement:
@ -1317,8 +1347,8 @@ namespace llvm {
template<>
struct ConstantCreator<ConstantExpr, Type, ExprMapKeyType> {
static ConstantExpr *create(const Type *Ty, const ExprMapKeyType &V) {
if (V.first == Instruction::Cast)
return new UnaryConstantExpr(Instruction::Cast, V.second[0], Ty);
if (Instruction::isCast(V.first))
return new UnaryConstantExpr(V.first, V.second[0], Ty);
if ((V.first >= Instruction::BinaryOpsBegin &&
V.first < Instruction::BinaryOpsEnd) ||
V.first == Instruction::Shl ||
@ -1348,8 +1378,20 @@ namespace llvm {
static void convert(ConstantExpr *OldC, const Type *NewTy) {
Constant *New;
switch (OldC->getOpcode()) {
case Instruction::Cast:
New = ConstantExpr::getCast(OldC->getOperand(0), NewTy);
case Instruction::Trunc:
case Instruction::ZExt:
case Instruction::SExt:
case Instruction::FPTrunc:
case Instruction::FPExt:
case Instruction::UIToFP:
case Instruction::SIToFP:
case Instruction::FPToUI:
case Instruction::FPToSI:
case Instruction::PtrToInt:
case Instruction::IntToPtr:
case Instruction::BitCast:
New = ConstantExpr::getCast(
OldC->getOpcode(), OldC->getOperand(0), NewTy);
break;
case Instruction::Select:
New = ConstantExpr::getSelectTy(NewTy, OldC->getOperand(0),
@ -1394,40 +1436,143 @@ static ExprMapKeyType getValType(ConstantExpr *CE) {
static ManagedStatic<ValueMap<ExprMapKeyType, Type,
ConstantExpr> > ExprConstants;
Constant *ConstantExpr::getCast(Constant *C, const Type *Ty) {
/// This is a utility function to handle folding of casts and lookup of the
/// cast in the ExprConstants map. It is usedby the various get* methods below.
static inline Constant *getFoldedCast(
Instruction::CastOps opc, Constant *C, const Type *Ty) {
assert(Ty->isFirstClassType() && "Cannot cast to an aggregate type!");
if (Constant *FC = ConstantFoldCastInstruction(C, Ty))
return FC; // Fold a few common cases...
// Fold a few common cases
if (Constant *FC = ConstantFoldCastInstruction(opc, C, Ty))
return FC;
// Look up the constant in the table first to ensure uniqueness
std::vector<Constant*> argVec(1, C);
ExprMapKeyType Key = std::make_pair(Instruction::Cast, argVec);
ExprMapKeyType Key = std::make_pair(opc, argVec);
return ExprConstants->getOrCreate(Ty, Key);
}
Constant *ConstantExpr::getSignExtend(Constant *C, const Type *Ty) {
assert(C->getType()->isIntegral() && Ty->isIntegral() &&
C->getType()->getPrimitiveSize() <= Ty->getPrimitiveSize() &&
"This is an illegal sign extension!");
if (C->getType() != Type::BoolTy) {
C = ConstantExpr::getCast(C, C->getType()->getSignedVersion());
return ConstantExpr::getCast(C, Ty);
} else {
if (C == ConstantBool::getTrue())
return ConstantIntegral::getAllOnesValue(Ty);
else
return ConstantIntegral::getNullValue(Ty);
Constant *ConstantExpr::getCast( Constant *C, const Type *Ty ) {
// Note: we can't inline this because it requires the Instructions.h header
return getCast(CastInst::getCastOpcode(C, Ty), C, Ty);
}
Constant *ConstantExpr::getCast(unsigned oc, Constant *C, const Type *Ty) {
Instruction::CastOps opc = Instruction::CastOps(oc);
assert(Instruction::isCast(opc) && "opcode out of range");
assert(C && Ty && "Null arguments to getCast");
assert(Ty->isFirstClassType() && "Cannot cast to an aggregate type!");
switch (opc) {
default:
assert(0 && "Invalid cast opcode");
break;
case Instruction::Trunc: return getTrunc(C, Ty);
case Instruction::ZExt: return getZeroExtend(C, Ty);
case Instruction::SExt: return getSignExtend(C, Ty);
case Instruction::FPTrunc: return getFPTrunc(C, Ty);
case Instruction::FPExt: return getFPExtend(C, Ty);
case Instruction::UIToFP: return getUIToFP(C, Ty);
case Instruction::SIToFP: return getSIToFP(C, Ty);
case Instruction::FPToUI: return getFPToUI(C, Ty);
case Instruction::FPToSI: return getFPToSI(C, Ty);
case Instruction::PtrToInt: return getPtrToInt(C, Ty);
case Instruction::IntToPtr: return getIntToPtr(C, Ty);
case Instruction::BitCast: return getBitCast(C, Ty);
}
return 0;
}
Constant *ConstantExpr::getTrunc(Constant *C, const Type *Ty) {
assert(C->getType()->isInteger() && "Trunc operand must be integer");
assert(Ty->isIntegral() && "Trunc produces only integral");
assert(C->getType()->getPrimitiveSizeInBits() > Ty->getPrimitiveSizeInBits()&&
"SrcTy must be larger than DestTy for Trunc!");
return getFoldedCast(Instruction::Trunc, C, Ty);
}
Constant *ConstantExpr::getSignExtend(Constant *C, const Type *Ty) {
assert(C->getType()->isIntegral() && "SEXt operand must be integral");
assert(Ty->isInteger() && "SExt produces only integer");
assert(C->getType()->getPrimitiveSizeInBits() < Ty->getPrimitiveSizeInBits()&&
"SrcTy must be smaller than DestTy for SExt!");
return getFoldedCast(Instruction::SExt, C, Ty);
}
Constant *ConstantExpr::getZeroExtend(Constant *C, const Type *Ty) {
assert(C->getType()->isIntegral() && Ty->isIntegral() &&
C->getType()->getPrimitiveSize() <= Ty->getPrimitiveSize() &&
"This is an illegal zero extension!");
if (C->getType() != Type::BoolTy)
C = ConstantExpr::getCast(C, C->getType()->getUnsignedVersion());
return ConstantExpr::getCast(C, Ty);
assert(C->getType()->isIntegral() && "ZEXt operand must be integral");
assert(Ty->isInteger() && "ZExt produces only integer");
assert(C->getType()->getPrimitiveSizeInBits() < Ty->getPrimitiveSizeInBits()&&
"SrcTy must be smaller than DestTy for ZExt!");
return getFoldedCast(Instruction::ZExt, C, Ty);
}
Constant *ConstantExpr::getFPTrunc(Constant *C, const Type *Ty) {
assert(C->getType()->isFloatingPoint() && Ty->isFloatingPoint() &&
C->getType()->getPrimitiveSizeInBits() > Ty->getPrimitiveSizeInBits()&&
"This is an illegal floating point truncation!");
return getFoldedCast(Instruction::FPTrunc, C, Ty);
}
Constant *ConstantExpr::getFPExtend(Constant *C, const Type *Ty) {
assert(C->getType()->isFloatingPoint() && Ty->isFloatingPoint() &&
C->getType()->getPrimitiveSizeInBits() < Ty->getPrimitiveSizeInBits()&&
"This is an illegal floating point extension!");
return getFoldedCast(Instruction::FPExt, C, Ty);
}
Constant *ConstantExpr::getUIToFP(Constant *C, const Type *Ty) {
assert(C->getType()->isIntegral() && Ty->isFloatingPoint() &&
"This is an illegal uint to floating point cast!");
return getFoldedCast(Instruction::UIToFP, C, Ty);
}
Constant *ConstantExpr::getSIToFP(Constant *C, const Type *Ty) {
assert(C->getType()->isIntegral() && Ty->isFloatingPoint() &&
"This is an illegal sint to floating point cast!");
return getFoldedCast(Instruction::SIToFP, C, Ty);
}
Constant *ConstantExpr::getFPToUI(Constant *C, const Type *Ty) {
assert(C->getType()->isFloatingPoint() && Ty->isIntegral() &&
"This is an illegal floating point to uint cast!");
return getFoldedCast(Instruction::FPToUI, C, Ty);
}
Constant *ConstantExpr::getFPToSI(Constant *C, const Type *Ty) {
assert(C->getType()->isFloatingPoint() && Ty->isIntegral() &&
"This is an illegal floating point to sint cast!");
return getFoldedCast(Instruction::FPToSI, C, Ty);
}
Constant *ConstantExpr::getPtrToInt(Constant *C, const Type *DstTy) {
assert(isa<PointerType>(C->getType()) && "PtrToInt source must be pointer");
assert(DstTy->isIntegral() && "PtrToInt destination must be integral");
return getFoldedCast(Instruction::PtrToInt, C, DstTy);
}
Constant *ConstantExpr::getIntToPtr(Constant *C, const Type *DstTy) {
assert(C->getType()->isIntegral() && "IntToPtr source must be integral");
assert(isa<PointerType>(DstTy) && "IntToPtr destination must be a pointer");
return getFoldedCast(Instruction::IntToPtr, C, DstTy);
}
Constant *ConstantExpr::getBitCast(Constant *C, const Type *DstTy) {
// BitCast implies a no-op cast of type only. No bits change. However, you
// can't cast pointers to anything but pointers.
const Type *SrcTy = C->getType();
assert((isa<PointerType>(SrcTy) == isa<PointerType>(DstTy)) &&
"Bitcast cannot cast pointer to non-pointer and vice versa");
// Now we know we're not dealing with mismatched pointer casts (ptr->nonptr
// or nonptr->ptr). For all the other types, the cast is okay if source and
// destination bit widths are identical.
unsigned SrcBitSize = SrcTy->getPrimitiveSizeInBits();
unsigned DstBitSize = DstTy->getPrimitiveSizeInBits();
assert(SrcBitSize == DstBitSize && "Bitcast requies types of same width");
return getFoldedCast(Instruction::BitCast, C, DstTy);
}
Constant *ConstantExpr::getSizeOf(const Type *Ty) {
@ -1858,9 +2003,9 @@ void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV,
Indices.push_back(Val);
}
Replacement = ConstantExpr::getGetElementPtr(Pointer, Indices);
} else if (getOpcode() == Instruction::Cast) {
} else if (isCast()) {
assert(getOperand(0) == From && "Cast only has one use!");
Replacement = ConstantExpr::getCast(To, getType());
Replacement = ConstantExpr::getCast(getOpcode(), To, getType());
} else if (getOpcode() == Instruction::Select) {
Constant *C1 = getOperand(0);
Constant *C2 = getOperand(1);

View File

@ -226,7 +226,7 @@ const char *Intrinsic::getName(ID id) {
Value *IntrinsicInst::StripPointerCasts(Value *Ptr) {
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Ptr)) {
if (CE->getOpcode() == Instruction::Cast) {
if (CE->getOpcode() == Instruction::BitCast) {
if (isa<PointerType>(CE->getOperand(0)->getType()))
return StripPointerCasts(CE->getOperand(0));
} else if (CE->getOpcode() == Instruction::GetElementPtr) {
@ -238,7 +238,7 @@ Value *IntrinsicInst::StripPointerCasts(Value *Ptr) {
return Ptr;
}
if (CastInst *CI = dyn_cast<CastInst>(Ptr)) {
if (BitCastInst *CI = dyn_cast<BitCastInst>(Ptr)) {
if (isa<PointerType>(CI->getOperand(0)->getType()))
return StripPointerCasts(CI->getOperand(0));
} else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Ptr)) {

View File

@ -122,18 +122,31 @@ const char *Instruction::getOpcodeName(unsigned OpCode) {
case Store: return "store";
case GetElementPtr: return "getelementptr";
// Convert instructions...
case Trunc: return "trunc";
case ZExt: return "zext";
case SExt: return "sext";
case FPTrunc: return "fptrunc";
case FPExt: return "fpext";
case FPToUI: return "fptoui";
case FPToSI: return "fptosi";
case UIToFP: return "uitofp";
case SIToFP: return "sitofp";
case IntToPtr: return "inttoptr";
case PtrToInt: return "ptrtoint";
case BitCast: return "bitcast";
// Other instructions...
case PHI: return "phi";
case Cast: return "cast";
case Select: return "select";
case Call: return "call";
case Shl: return "shl";
case LShr: return "lshr";
case AShr: return "ashr";
case VAArg: return "va_arg";
case PHI: return "phi";
case Select: return "select";
case Call: return "call";
case Shl: return "shl";
case LShr: return "lshr";
case AShr: return "ashr";
case VAArg: return "va_arg";
case ExtractElement: return "extractelement";
case InsertElement: return "insertelement";
case ShuffleVector: return "shufflevector";
case InsertElement: return "insertelement";
case ShuffleVector: return "shufflevector";
default: return "<Invalid operator> ";
}

View File

@ -1226,18 +1226,571 @@ bool BinaryOperator::swapOperands() {
// CastInst Class
//===----------------------------------------------------------------------===//
/// isTruncIntCast - Return true if this is a truncating integer cast
/// instruction, e.g. a cast from long to uint.
bool CastInst::isTruncIntCast() const {
// The dest type has to be integral, the input has to be integer.
if (!getType()->isIntegral() || !getOperand(0)->getType()->isInteger())
return false;
// Has to be large to smaller.
return getOperand(0)->getType()->getPrimitiveSizeInBits() >
getType()->getPrimitiveSizeInBits();
// Just determine if this cast only deals with integral->integral conversion.
bool CastInst::isIntegerCast() const {
switch (getOpcode()) {
default: return false;
case Instruction::ZExt:
case Instruction::SExt:
case Instruction::Trunc:
return true;
case Instruction::BitCast:
return getOperand(0)->getType()->isIntegral() && getType()->isIntegral();
}
}
bool CastInst::isLosslessCast() const {
// Only BitCast can be lossless, exit fast if we're not BitCast
if (getOpcode() != Instruction::BitCast)
return false;
// Identity cast is always lossless
const Type* SrcTy = getOperand(0)->getType();
const Type* DstTy = getType();
if (SrcTy == DstTy)
return true;
// The remaining possibilities are lossless if the typeID of the source type
// matches the type ID of the destination in size and fundamental type. This
// prevents things like int -> ptr, int -> float, packed -> int, mismatched
// packed types of the same size, and etc.
switch (SrcTy->getTypeID()) {
case Type::UByteTyID: return DstTy == Type::SByteTy;
case Type::SByteTyID: return DstTy == Type::UByteTy;
case Type::UShortTyID: return DstTy == Type::ShortTy;
case Type::ShortTyID: return DstTy == Type::UShortTy;
case Type::UIntTyID: return DstTy == Type::IntTy;
case Type::IntTyID: return DstTy == Type::UIntTy;
case Type::ULongTyID: return DstTy == Type::LongTy;
case Type::LongTyID: return DstTy == Type::ULongTy;
case Type::PointerTyID: return isa<PointerType>(DstTy);
default:
break;
}
return false; // Other types have no identity values
}
/// This function determines if the CastInst does not require any bits to be
/// changed in order to effect the cast. Essentially, it identifies cases where
/// no code gen is necessary for the cast, hence the name no-op cast. For
/// example, the following are all no-op casts:
/// # bitcast uint %X, int
/// # bitcast uint* %x, sbyte*
/// # bitcast packed< 2 x int > %x, packed< 4 x short>
/// # ptrtoint uint* %x, uint ; on 32-bit plaforms only
/// @brief Determine if a cast is a no-op.
bool CastInst::isNoopCast(const Type *IntPtrTy) const {
switch (getOpcode()) {
default:
assert(!"Invalid CastOp");
case Instruction::Trunc:
case Instruction::ZExt:
case Instruction::SExt:
case Instruction::FPTrunc:
case Instruction::FPExt:
case Instruction::UIToFP:
case Instruction::SIToFP:
case Instruction::FPToUI:
case Instruction::FPToSI:
return false; // These always modify bits
case Instruction::BitCast:
return true; // BitCast never modifies bits.
case Instruction::PtrToInt:
return IntPtrTy->getPrimitiveSizeInBits() ==
getType()->getPrimitiveSizeInBits();
case Instruction::IntToPtr:
return IntPtrTy->getPrimitiveSizeInBits() ==
getOperand(0)->getType()->getPrimitiveSizeInBits();
}
}
/// This function determines if a pair of casts can be eliminated and what
/// opcode should be used in the elimination. This assumes that there are two
/// instructions like this:
/// * %F = firstOpcode SrcTy %x to MidTy
/// * %S = secondOpcode MidTy %F to DstTy
/// The function returns a resultOpcode so these two casts can be replaced with:
/// * %Replacement = resultOpcode %SrcTy %x to DstTy
/// If no such cast is permited, the function returns 0.
unsigned CastInst::isEliminableCastPair(
Instruction::CastOps firstOp, Instruction::CastOps secondOp,
const Type *SrcTy, const Type *MidTy, const Type *DstTy, const Type *IntPtrTy)
{
// Define the 144 possibilities for these two cast instructions. The values
// in this matrix determine what to do in a given situation and select the
// case in the switch below. The rows correspond to firstOp, the columns
// correspond to secondOp. In looking at the table below, keep in mind
// the following cast properties:
//
// Size Compare Source Destination
// Operator Src ? Size Type Sign Type Sign
// -------- ------------ ------------------- ---------------------
// TRUNC > Integer Any Integral Any
// ZEXT < Integral Unsigned Integer Any
// SEXT < Integral Signed Integer Any
// FPTOUI n/a FloatPt n/a Integral Unsigned
// FPTOSI n/a FloatPt n/a Integral Signed
// UITOFP n/a Integral Unsigned FloatPt n/a
// SITOFP n/a Integral Signed FloatPt n/a
// FPTRUNC > FloatPt n/a FloatPt n/a
// FPEXT < FloatPt n/a FloatPt n/a
// PTRTOINT n/a Pointer n/a Integral Unsigned
// INTTOPTR n/a Integral Unsigned Pointer n/a
// BITCONVERT = FirstClass n/a FirstClass n/a
//
const unsigned numCastOps =
Instruction::CastOpsEnd - Instruction::CastOpsBegin;
static const uint8_t CastResults[numCastOps][numCastOps] = {
// T F F U S F F P I B -+
// R Z S P P I I T P 2 N T |
// U E E 2 2 2 2 R E I T C +- secondOp
// N X X U S F F N X N 2 V |
// C T T I I P P C T T P T -+
{ 1, 0, 0,99,99, 0, 0,99,99,99, 0, 3 }, // Trunc -+
{ 8, 1, 9,99,99, 2, 0,99,99,99, 2, 3 }, // ZExt |
{ 8, 0, 1,99,99, 0, 2,99,99,99, 0, 3 }, // SExt |
{ 0, 1, 0,99,99, 0, 0,99,99,99, 0, 3 }, // FPToUI |
{ 0, 0, 1,99,99, 0, 0,99,99,99, 0, 3 }, // FPToSI |
{ 99,99,99, 0, 0,99,99, 0, 0,99,99, 4 }, // UIToFP +- firstOp
{ 99,99,99, 0, 0,99,99, 0, 0,99,99, 4 }, // SIToFP |
{ 99,99,99, 0, 0,99,99, 1, 0,99,99, 4 }, // FPTrunc |
{ 99,99,99, 2, 2,99,99,10, 2,99,99, 4 }, // FPExt |
{ 1, 0, 0,99,99, 0, 0,99,99,99, 7, 3 }, // PtrToInt |
{ 99,99,99,99,99,99,99,99,99,13,99,12 }, // IntToPtr |
{ 5, 5, 5, 6, 6, 5, 5, 6, 6,11, 5, 1 }, // BitCast -+
};
int ElimCase = CastResults[firstOp-Instruction::CastOpsBegin]
[secondOp-Instruction::CastOpsBegin];
switch (ElimCase) {
case 0:
// categorically disallowed
return 0;
case 1:
// allowed, use first cast's opcode
return firstOp;
case 2:
// allowed, use second cast's opcode
return secondOp;
case 3:
// no-op cast in second op implies firstOp as long as the DestTy
// is integer
if (DstTy->isInteger())
return firstOp;
return 0;
case 4:
// no-op cast in second op implies firstOp as long as the DestTy
// is floating point
if (DstTy->isFloatingPoint())
return firstOp;
return 0;
case 5:
// no-op cast in first op implies secondOp as long as the SrcTy
// is an integer
if (SrcTy->isInteger())
return secondOp;
return 0;
case 6:
// no-op cast in first op implies secondOp as long as the SrcTy
// is a floating point
if (SrcTy->isFloatingPoint())
return secondOp;
return 0;
case 7: {
// ptrtoint, inttoptr -> bitcast (ptr -> ptr) if int size is >= ptr size
unsigned PtrSize = IntPtrTy->getPrimitiveSizeInBits();
unsigned MidSize = MidTy->getPrimitiveSizeInBits();
if (MidSize >= PtrSize)
return Instruction::BitCast;
return 0;
}
case 8: {
// ext, trunc -> bitcast, if the SrcTy and DstTy are same size
// ext, trunc -> ext, if sizeof(SrcTy) < sizeof(DstTy)
// ext, trunc -> trunc, if sizeof(SrcTy) > sizeof(DstTy)
unsigned SrcSize = SrcTy->getPrimitiveSizeInBits();
unsigned DstSize = DstTy->getPrimitiveSizeInBits();
if (SrcSize == DstSize)
return Instruction::BitCast;
else if (SrcSize < DstSize)
return firstOp;
return secondOp;
}
case 9: // zext, sext -> zext, because sext can't sign extend after zext
return Instruction::ZExt;
case 10:
// fpext followed by ftrunc is allowed if the bit size returned to is
// the same as the original, in which case its just a bitcast
if (SrcTy == DstTy)
return Instruction::BitCast;
return 0; // If the types are not the same we can't eliminate it.
case 11:
// bitcast followed by ptrtoint is allowed as long as the bitcast
// is a pointer to pointer cast.
if (isa<PointerType>(SrcTy) && isa<PointerType>(MidTy))
return secondOp;
return 0;
case 12:
// inttoptr, bitcast -> intptr if bitcast is a ptr to ptr cast
if (isa<PointerType>(MidTy) && isa<PointerType>(DstTy))
return firstOp;
return 0;
case 13: {
// inttoptr, ptrtoint -> bitcast if SrcSize<=PtrSize and SrcSize==DstSize
unsigned PtrSize = IntPtrTy->getPrimitiveSizeInBits();
unsigned SrcSize = SrcTy->getPrimitiveSizeInBits();
unsigned DstSize = DstTy->getPrimitiveSizeInBits();
if (SrcSize <= PtrSize && SrcSize == DstSize)
return Instruction::BitCast;
return 0;
}
case 99:
// cast combination can't happen (error in input). This is for all cases
// where the MidTy is not the same for the two cast instructions.
assert(!"Invalid Cast Combination");
return 0;
default:
assert(!"Error in CastResults table!!!");
return 0;
}
return 0;
}
CastInst *CastInst::create(Instruction::CastOps op, Value *S, const Type *Ty,
const std::string &Name, Instruction *InsertBefore) {
// Construct and return the appropriate CastInst subclass
switch (op) {
case Trunc: return new TruncInst (S, Ty, Name, InsertBefore);
case ZExt: return new ZExtInst (S, Ty, Name, InsertBefore);
case SExt: return new SExtInst (S, Ty, Name, InsertBefore);
case FPTrunc: return new FPTruncInst (S, Ty, Name, InsertBefore);
case FPExt: return new FPExtInst (S, Ty, Name, InsertBefore);
case UIToFP: return new UIToFPInst (S, Ty, Name, InsertBefore);
case SIToFP: return new SIToFPInst (S, Ty, Name, InsertBefore);
case FPToUI: return new FPToUIInst (S, Ty, Name, InsertBefore);
case FPToSI: return new FPToSIInst (S, Ty, Name, InsertBefore);
case PtrToInt: return new PtrToIntInst (S, Ty, Name, InsertBefore);
case IntToPtr: return new IntToPtrInst (S, Ty, Name, InsertBefore);
case BitCast: return new BitCastInst (S, Ty, Name, InsertBefore);
default:
assert(!"Invalid opcode provided");
}
return 0;
}
CastInst *CastInst::create(Instruction::CastOps op, Value *S, const Type *Ty,
const std::string &Name, BasicBlock *InsertAtEnd) {
// Construct and return the appropriate CastInst subclass
switch (op) {
case Trunc: return new TruncInst (S, Ty, Name, InsertAtEnd);
case ZExt: return new ZExtInst (S, Ty, Name, InsertAtEnd);
case SExt: return new SExtInst (S, Ty, Name, InsertAtEnd);
case FPTrunc: return new FPTruncInst (S, Ty, Name, InsertAtEnd);
case FPExt: return new FPExtInst (S, Ty, Name, InsertAtEnd);
case UIToFP: return new UIToFPInst (S, Ty, Name, InsertAtEnd);
case SIToFP: return new SIToFPInst (S, Ty, Name, InsertAtEnd);
case FPToUI: return new FPToUIInst (S, Ty, Name, InsertAtEnd);
case FPToSI: return new FPToSIInst (S, Ty, Name, InsertAtEnd);
case PtrToInt: return new PtrToIntInst (S, Ty, Name, InsertAtEnd);
case IntToPtr: return new IntToPtrInst (S, Ty, Name, InsertAtEnd);
case BitCast: return new BitCastInst (S, Ty, Name, InsertAtEnd);
default:
assert(!"Invalid opcode provided");
}
return 0;
}
// Provide a way to get a "cast" where the cast opcode is inferred from the
// types and size of the operand. This, basically, is a parallel of the
// logic in the checkCast function below. This axiom should hold:
// checkCast( getCastOpcode(Val, Ty), Val, Ty)
// should not assert in checkCast. In other words, this produces a "correct"
// casting opcode for the arguments passed to it.
Instruction::CastOps
CastInst::getCastOpcode(const Value *Src, const Type *DestTy) {
// Get the bit sizes, we'll need these
const Type *SrcTy = Src->getType();
unsigned SrcBits = SrcTy->getPrimitiveSizeInBits(); // 0 for ptr/packed
unsigned DestBits = DestTy->getPrimitiveSizeInBits(); // 0 for ptr/packed
// Run through the possibilities ...
if (DestTy->isIntegral()) { // Casting to integral
if (SrcTy->isIntegral()) { // Casting from integral
if (DestBits < SrcBits)
return Trunc; // int -> smaller int
else if (DestBits > SrcBits) { // its an extension
if (SrcTy->isSigned())
return SExt; // signed -> SEXT
else
return ZExt; // unsigned -> ZEXT
} else {
return BitCast; // Same size, No-op cast
}
} else if (SrcTy->isFloatingPoint()) { // Casting from floating pt
if (DestTy->isSigned())
return FPToSI; // FP -> sint
else
return FPToUI; // FP -> uint
} else if (const PackedType *PTy = dyn_cast<PackedType>(SrcTy)) {
assert(DestBits == PTy->getBitWidth() &&
"Casting packed to integer of different width");
return BitCast; // Same size, no-op cast
} else {
assert(isa<PointerType>(SrcTy) &&
"Casting from a value that is not first-class type");
return PtrToInt; // ptr -> int
}
} else if (DestTy->isFloatingPoint()) { // Casting to floating pt
if (SrcTy->isIntegral()) { // Casting from integral
if (SrcTy->isSigned())
return SIToFP; // sint -> FP
else
return UIToFP; // uint -> FP
} else if (SrcTy->isFloatingPoint()) { // Casting from floating pt
if (DestBits < SrcBits) {
return FPTrunc; // FP -> smaller FP
} else if (DestBits > SrcBits) {
return FPExt; // FP -> larger FP
} else {
return BitCast; // same size, no-op cast
}
} else if (const PackedType *PTy = dyn_cast<PackedType>(SrcTy)) {
assert(DestBits == PTy->getBitWidth() &&
"Casting packed to floating point of different width");
return BitCast; // same size, no-op cast
} else {
assert(0 && "Casting pointer or non-first class to float");
}
} else if (const PackedType *DestPTy = dyn_cast<PackedType>(DestTy)) {
if (const PackedType *SrcPTy = dyn_cast<PackedType>(SrcTy)) {
assert(DestPTy->getBitWidth() == SrcPTy->getBitWidth() &&
"Casting packed to packed of different widths");
return BitCast; // packed -> packed
} else if (DestPTy->getBitWidth() == SrcBits) {
return BitCast; // float/int -> packed
} else {
assert(!"Illegal cast to packed (wrong type or size)");
}
} else if (isa<PointerType>(DestTy)) {
if (isa<PointerType>(SrcTy)) {
return BitCast; // ptr -> ptr
} else if (SrcTy->isIntegral()) {
return IntToPtr; // int -> ptr
} else {
assert(!"Casting pointer to other than pointer or int");
}
} else {
assert(!"Casting to type that is not first-class");
}
// If we fall through to here we probably hit an assertion cast above
// and assertions are not turned on. Anything we return is an error, so
// BitCast is as good a choice as any.
return BitCast;
}
//===----------------------------------------------------------------------===//
// CastInst SubClass Constructors
//===----------------------------------------------------------------------===//
/// Check that the construction parameters for a CastInst are correct. This
/// could be broken out into the separate constructors but it is useful to have
/// it in one place and to eliminate the redundant code for getting the sizes
/// of the types involved.
static bool
checkCast(Instruction::CastOps op, Value *S, const Type *DstTy) {
// Check for type sanity on the arguments
const Type *SrcTy = S->getType();
if (!SrcTy->isFirstClassType() || !DstTy->isFirstClassType())
return false;
// Get the size of the types in bits, we'll need this later
unsigned SrcBitSize = SrcTy->getPrimitiveSizeInBits();
unsigned DstBitSize = DstTy->getPrimitiveSizeInBits();
// Switch on the opcode provided
switch (op) {
default: return false; // This is an input error
case Instruction::Trunc:
return SrcTy->isInteger() && DstTy->isIntegral() && SrcBitSize > DstBitSize;
case Instruction::ZExt:
return SrcTy->isIntegral() && DstTy->isInteger() && SrcBitSize < DstBitSize;
case Instruction::SExt:
return SrcTy->isIntegral() && DstTy->isInteger() && SrcBitSize < DstBitSize;
case Instruction::FPTrunc:
return SrcTy->isFloatingPoint() && DstTy->isFloatingPoint() &&
SrcBitSize > DstBitSize;
case Instruction::FPExt:
return SrcTy->isFloatingPoint() && DstTy->isFloatingPoint() &&
SrcBitSize < DstBitSize;
case Instruction::UIToFP:
return SrcTy->isIntegral() && DstTy->isFloatingPoint();
case Instruction::SIToFP:
return SrcTy->isIntegral() && DstTy->isFloatingPoint();
case Instruction::FPToUI:
return SrcTy->isFloatingPoint() && DstTy->isIntegral();
case Instruction::FPToSI:
return SrcTy->isFloatingPoint() && DstTy->isIntegral();
case Instruction::PtrToInt:
return isa<PointerType>(SrcTy) && DstTy->isIntegral();
case Instruction::IntToPtr:
return SrcTy->isIntegral() && isa<PointerType>(DstTy);
case Instruction::BitCast:
// BitCast implies a no-op cast of type only. No bits change.
// However, you can't cast pointers to anything but pointers.
if (isa<PointerType>(SrcTy) != isa<PointerType>(DstTy))
return false;
// Now we know we're not dealing with a pointer/non-poiner mismatch. In all
// these cases, the cast is okay if the source and destination bit widths
// are identical.
return SrcBitSize == DstBitSize;
}
}
TruncInst::TruncInst(
Value *S, const Type *Ty, const std::string &Name, Instruction *InsertBefore
) : CastInst(Ty, Trunc, S, Name, InsertBefore) {
assert(checkCast(getOpcode(), S, Ty) && "Illegal Trunc");
}
TruncInst::TruncInst(
Value *S, const Type *Ty, const std::string &Name, BasicBlock *InsertAtEnd
) : CastInst(Ty, Trunc, S, Name, InsertAtEnd) {
assert(checkCast(getOpcode(), S, Ty) && "Illegal Trunc");
}
ZExtInst::ZExtInst(
Value *S, const Type *Ty, const std::string &Name, Instruction *InsertBefore
) : CastInst(Ty, ZExt, S, Name, InsertBefore) {
assert(checkCast(getOpcode(), S, Ty) && "Illegal ZExt");
}
ZExtInst::ZExtInst(
Value *S, const Type *Ty, const std::string &Name, BasicBlock *InsertAtEnd
) : CastInst(Ty, ZExt, S, Name, InsertAtEnd) {
assert(checkCast(getOpcode(), S, Ty) && "Illegal ZExt");
}
SExtInst::SExtInst(
Value *S, const Type *Ty, const std::string &Name, Instruction *InsertBefore
) : CastInst(Ty, SExt, S, Name, InsertBefore) {
assert(checkCast(getOpcode(), S, Ty) && "Illegal SExt");
}
SExtInst::SExtInst::SExtInst(
Value *S, const Type *Ty, const std::string &Name, BasicBlock *InsertAtEnd
) : CastInst(Ty, SExt, S, Name, InsertAtEnd) {
assert(checkCast(getOpcode(), S, Ty) && "Illegal SExt");
}
FPTruncInst::FPTruncInst(
Value *S, const Type *Ty, const std::string &Name, Instruction *InsertBefore
) : CastInst(Ty, FPTrunc, S, Name, InsertBefore) {
assert(checkCast(getOpcode(), S, Ty) && "Illegal FPTrunc");
}
FPTruncInst::FPTruncInst(
Value *S, const Type *Ty, const std::string &Name, BasicBlock *InsertAtEnd
) : CastInst(Ty, FPTrunc, S, Name, InsertAtEnd) {
assert(checkCast(getOpcode(), S, Ty) && "Illegal FPTrunc");
}
FPExtInst::FPExtInst(
Value *S, const Type *Ty, const std::string &Name, Instruction *InsertBefore
) : CastInst(Ty, FPExt, S, Name, InsertBefore) {
assert(checkCast(getOpcode(), S, Ty) && "Illegal FPExt");
}
FPExtInst::FPExtInst(
Value *S, const Type *Ty, const std::string &Name, BasicBlock *InsertAtEnd
) : CastInst(Ty, FPExt, S, Name, InsertAtEnd) {
assert(checkCast(getOpcode(), S, Ty) && "Illegal FPExt");
}
UIToFPInst::UIToFPInst(
Value *S, const Type *Ty, const std::string &Name, Instruction *InsertBefore
) : CastInst(Ty, UIToFP, S, Name, InsertBefore) {
assert(checkCast(getOpcode(), S, Ty) && "Illegal UIToFP");
}
UIToFPInst::UIToFPInst(
Value *S, const Type *Ty, const std::string &Name, BasicBlock *InsertAtEnd
) : CastInst(Ty, UIToFP, S, Name, InsertAtEnd) {
assert(checkCast(getOpcode(), S, Ty) && "Illegal UIToFP");
}
SIToFPInst::SIToFPInst(
Value *S, const Type *Ty, const std::string &Name, Instruction *InsertBefore
) : CastInst(Ty, SIToFP, S, Name, InsertBefore) {
assert(checkCast(getOpcode(), S, Ty) && "Illegal SIToFP");
}
SIToFPInst::SIToFPInst(
Value *S, const Type *Ty, const std::string &Name, BasicBlock *InsertAtEnd
) : CastInst(Ty, SIToFP, S, Name, InsertAtEnd) {
assert(checkCast(getOpcode(), S, Ty) && "Illegal SIToFP");
}
FPToUIInst::FPToUIInst(
Value *S, const Type *Ty, const std::string &Name, Instruction *InsertBefore
) : CastInst(Ty, FPToUI, S, Name, InsertBefore) {
assert(checkCast(getOpcode(), S, Ty) && "Illegal FPToUI");
}
FPToUIInst::FPToUIInst(
Value *S, const Type *Ty, const std::string &Name, BasicBlock *InsertAtEnd
) : CastInst(Ty, FPToUI, S, Name, InsertAtEnd) {
assert(checkCast(getOpcode(), S, Ty) && "Illegal FPToUI");
}
FPToSIInst::FPToSIInst(
Value *S, const Type *Ty, const std::string &Name, Instruction *InsertBefore
) : CastInst(Ty, FPToSI, S, Name, InsertBefore) {
assert(checkCast(getOpcode(), S, Ty) && "Illegal FPToSI");
}
FPToSIInst::FPToSIInst(
Value *S, const Type *Ty, const std::string &Name, BasicBlock *InsertAtEnd
) : CastInst(Ty, FPToSI, S, Name, InsertAtEnd) {
assert(checkCast(getOpcode(), S, Ty) && "Illegal FPToSI");
}
PtrToIntInst::PtrToIntInst(
Value *S, const Type *Ty, const std::string &Name, Instruction *InsertBefore
) : CastInst(Ty, PtrToInt, S, Name, InsertBefore) {
assert(checkCast(getOpcode(), S, Ty) && "Illegal PtrToInt");
}
PtrToIntInst::PtrToIntInst(
Value *S, const Type *Ty, const std::string &Name, BasicBlock *InsertAtEnd
) : CastInst(Ty, PtrToInt, S, Name, InsertAtEnd) {
assert(checkCast(getOpcode(), S, Ty) && "Illegal PtrToInt");
}
IntToPtrInst::IntToPtrInst(
Value *S, const Type *Ty, const std::string &Name, Instruction *InsertBefore
) : CastInst(Ty, IntToPtr, S, Name, InsertBefore) {
assert(checkCast(getOpcode(), S, Ty) && "Illegal IntToPtr");
}
IntToPtrInst::IntToPtrInst(
Value *S, const Type *Ty, const std::string &Name, BasicBlock *InsertAtEnd
) : CastInst(Ty, IntToPtr, S, Name, InsertAtEnd) {
assert(checkCast(getOpcode(), S, Ty) && "Illegal IntToPtr");
}
BitCastInst::BitCastInst(
Value *S, const Type *Ty, const std::string &Name, Instruction *InsertBefore
) : CastInst(Ty, BitCast, S, Name, InsertBefore) {
assert(checkCast(getOpcode(), S, Ty) && "Illegal BitCast");
}
BitCastInst::BitCastInst(
Value *S, const Type *Ty, const std::string &Name, BasicBlock *InsertAtEnd
) : CastInst(Ty, BitCast, S, Name, InsertAtEnd) {
assert(checkCast(getOpcode(), S, Ty) && "Illegal BitCast");
}
//===----------------------------------------------------------------------===//
// SetCondInst Class
@ -1608,16 +2161,28 @@ CmpInst* CmpInst::clone() const {
Ops[0], Ops[1]);
}
MallocInst *MallocInst::clone() const { return new MallocInst(*this); }
AllocaInst *AllocaInst::clone() const { return new AllocaInst(*this); }
FreeInst *FreeInst::clone() const { return new FreeInst(getOperand(0)); }
LoadInst *LoadInst::clone() const { return new LoadInst(*this); }
StoreInst *StoreInst::clone() const { return new StoreInst(*this); }
CastInst *CastInst::clone() const { return new CastInst(*this); }
CallInst *CallInst::clone() const { return new CallInst(*this); }
ShiftInst *ShiftInst::clone() const { return new ShiftInst(*this); }
SelectInst *SelectInst::clone() const { return new SelectInst(*this); }
VAArgInst *VAArgInst::clone() const { return new VAArgInst(*this); }
MallocInst *MallocInst::clone() const { return new MallocInst(*this); }
AllocaInst *AllocaInst::clone() const { return new AllocaInst(*this); }
FreeInst *FreeInst::clone() const { return new FreeInst(getOperand(0)); }
LoadInst *LoadInst::clone() const { return new LoadInst(*this); }
StoreInst *StoreInst::clone() const { return new StoreInst(*this); }
CastInst *TruncInst::clone() const { return new TruncInst(*this); }
CastInst *ZExtInst::clone() const { return new ZExtInst(*this); }
CastInst *SExtInst::clone() const { return new SExtInst(*this); }
CastInst *FPTruncInst::clone() const { return new FPTruncInst(*this); }
CastInst *FPExtInst::clone() const { return new FPExtInst(*this); }
CastInst *UIToFPInst::clone() const { return new UIToFPInst(*this); }
CastInst *SIToFPInst::clone() const { return new SIToFPInst(*this); }
CastInst *FPToUIInst::clone() const { return new FPToUIInst(*this); }
CastInst *FPToSIInst::clone() const { return new FPToSIInst(*this); }
CastInst *PtrToIntInst::clone() const { return new PtrToIntInst(*this); }
CastInst *IntToPtrInst::clone() const { return new IntToPtrInst(*this); }
CastInst *BitCastInst::clone() const { return new BitCastInst(*this); }
CallInst *CallInst::clone() const { return new CallInst(*this); }
ShiftInst *ShiftInst::clone() const { return new ShiftInst(*this); }
SelectInst *SelectInst::clone() const { return new SelectInst(*this); }
VAArgInst *VAArgInst::clone() const { return new VAArgInst(*this); }
ExtractElementInst *ExtractElementInst::clone() const {
return new ExtractElementInst(*this);
}

View File

@ -37,7 +37,7 @@ using namespace llvm;
static Value *CastOperand(Value *C) {
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C))
if (CE->getOpcode() == Instruction::Cast)
if (CE->isCast())
return CE->getOperand(0);
return NULL;
}

View File

@ -98,24 +98,27 @@ bool Type::isFPOrFPVector() const {
return cast<PackedType>(this)->getElementType()->isFloatingPoint();
}
// isLosslesslyConvertibleTo - Return true if this type can be converted to
// canLosslesllyBitCastTo - Return true if this type can be converted to
// 'Ty' without any reinterpretation of bits. For example, uint to int.
//
bool Type::isLosslesslyConvertibleTo(const Type *Ty) const {
if (this == Ty) return true;
// Packed type conversions are always bitwise.
if (isa<PackedType>(this) && isa<PackedType>(Ty))
bool Type::canLosslesslyBitCastTo(const Type *Ty) const {
// Identity cast means no change so return true
if (this == Ty)
return true;
if ((!isPrimitiveType() && !isa<PointerType>(this)) ||
(!isa<PointerType>(Ty) && !Ty->isPrimitiveType())) return false;
// They are not convertible unless they are at least first class types
if (!this->isFirstClassType() || !Ty->isFirstClassType())
return false;
if (getTypeID() == Ty->getTypeID())
return true; // Handles identity cast, and cast of differing pointer types
// Packed -> Packed conversions are always lossless if the two packed types
// have the same size, otherwise not.
if (const PackedType *thisPTy = dyn_cast<PackedType>(this))
if (const PackedType *thatPTy = dyn_cast<PackedType>(Ty))
return thisPTy->getBitWidth() == thatPTy->getBitWidth();
// Now we know that they are two differing primitive or pointer types
// At this point we have only various mismatches of the first class types
// remaining and ptr->ptr. Just select the lossless conversions. Everything
// else is not lossless.
switch (getTypeID()) {
case Type::UByteTyID: return Ty == Type::SByteTy;
case Type::SByteTyID: return Ty == Type::UByteTy;
@ -127,8 +130,9 @@ bool Type::isLosslesslyConvertibleTo(const Type *Ty) const {
case Type::LongTyID: return Ty == Type::ULongTy;
case Type::PointerTyID: return isa<PointerType>(Ty);
default:
return false; // Other types have no identity values
break;
}
return false; // Other types have no identity values
}
/// getUnsignedVersion - If this is an integer type, return the unsigned
@ -200,6 +204,10 @@ unsigned Type::getPrimitiveSizeInBits() const {
case Type::LongTyID:
case Type::ULongTyID:
case Type::DoubleTyID: return 64;
case Type::PackedTyID: {
const PackedType *PTy = cast<PackedType>(this);
return PTy->getBitWidth();
}
default: return 0;
}
}

View File

@ -177,6 +177,18 @@ namespace { // Anonymous namespace for class
void visitGlobalVariable(GlobalVariable &GV);
void visitFunction(Function &F);
void visitBasicBlock(BasicBlock &BB);
void visitTruncInst(TruncInst &I);
void visitZExtInst(ZExtInst &I);
void visitSExtInst(SExtInst &I);
void visitFPTruncInst(FPTruncInst &I);
void visitFPExtInst(FPExtInst &I);
void visitFPToUIInst(FPToUIInst &I);
void visitFPToSIInst(FPToSIInst &I);
void visitUIToFPInst(UIToFPInst &I);
void visitSIToFPInst(SIToFPInst &I);
void visitIntToPtrInst(IntToPtrInst &I);
void visitPtrToIntInst(PtrToIntInst &I);
void visitBitCastInst(BitCastInst &I);
void visitPHINode(PHINode &PN);
void visitBinaryOperator(BinaryOperator &B);
void visitICmpInst(ICmpInst &IC);
@ -467,6 +479,169 @@ void Verifier::visitUserOp1(Instruction &I) {
Assert1(0, "User-defined operators should not live outside of a pass!", &I);
}
void Verifier::visitTruncInst(TruncInst &I) {
// Get the source and destination types
const Type *SrcTy = I.getOperand(0)->getType();
const Type *DestTy = I.getType();
// Get the size of the types in bits, we'll need this later
unsigned SrcBitSize = SrcTy->getPrimitiveSizeInBits();
unsigned DestBitSize = DestTy->getPrimitiveSizeInBits();
Assert1(SrcTy->isIntegral(), "Trunc only operates on integer", &I);
Assert1(DestTy->isIntegral(),"Trunc only produces integral", &I);
Assert1(SrcBitSize > DestBitSize,"DestTy too big for Trunc", &I);
visitInstruction(I);
}
void Verifier::visitZExtInst(ZExtInst &I) {
// Get the source and destination types
const Type *SrcTy = I.getOperand(0)->getType();
const Type *DestTy = I.getType();
// Get the size of the types in bits, we'll need this later
unsigned SrcBitSize = SrcTy->getPrimitiveSizeInBits();
unsigned DestBitSize = DestTy->getPrimitiveSizeInBits();
Assert1(SrcTy->isIntegral(),"ZExt only operates on integral", &I);
Assert1(DestTy->isInteger(),"ZExt only produces an integer", &I);
Assert1(SrcBitSize < DestBitSize,"Type too small for ZExt", &I);
visitInstruction(I);
}
void Verifier::visitSExtInst(SExtInst &I) {
// Get the source and destination types
const Type *SrcTy = I.getOperand(0)->getType();
const Type *DestTy = I.getType();
// Get the size of the types in bits, we'll need this later
unsigned SrcBitSize = SrcTy->getPrimitiveSizeInBits();
unsigned DestBitSize = DestTy->getPrimitiveSizeInBits();
Assert1(SrcTy->isIntegral(),"SExt only operates on integral", &I);
Assert1(DestTy->isInteger(),"SExt only produces an integer", &I);
Assert1(SrcBitSize < DestBitSize,"Type too small for SExt", &I);
visitInstruction(I);
}
void Verifier::visitFPTruncInst(FPTruncInst &I) {
// Get the source and destination types
const Type *SrcTy = I.getOperand(0)->getType();
const Type *DestTy = I.getType();
// Get the size of the types in bits, we'll need this later
unsigned SrcBitSize = SrcTy->getPrimitiveSizeInBits();
unsigned DestBitSize = DestTy->getPrimitiveSizeInBits();
Assert1(SrcTy->isFloatingPoint(),"FPTrunc only operates on FP", &I);
Assert1(DestTy->isFloatingPoint(),"FPTrunc only produces an FP", &I);
Assert1(SrcBitSize > DestBitSize,"DestTy too big for FPTrunc", &I);
visitInstruction(I);
}
void Verifier::visitFPExtInst(FPExtInst &I) {
// Get the source and destination types
const Type *SrcTy = I.getOperand(0)->getType();
const Type *DestTy = I.getType();
// Get the size of the types in bits, we'll need this later
unsigned SrcBitSize = SrcTy->getPrimitiveSizeInBits();
unsigned DestBitSize = DestTy->getPrimitiveSizeInBits();
Assert1(SrcTy->isFloatingPoint(),"FPExt only operates on FP", &I);
Assert1(DestTy->isFloatingPoint(),"FPExt only produces an FP", &I);
Assert1(SrcBitSize < DestBitSize,"DestTy too small for FPExt", &I);
visitInstruction(I);
}
void Verifier::visitUIToFPInst(UIToFPInst &I) {
// Get the source and destination types
const Type *SrcTy = I.getOperand(0)->getType();
const Type *DestTy = I.getType();
Assert1(SrcTy->isIntegral(),"UInt2FP source must be integral", &I);
Assert1(DestTy->isFloatingPoint(),"UInt2FP result must be FP", &I);
visitInstruction(I);
}
void Verifier::visitSIToFPInst(SIToFPInst &I) {
// Get the source and destination types
const Type *SrcTy = I.getOperand(0)->getType();
const Type *DestTy = I.getType();
Assert1(SrcTy->isIntegral(),"SInt2FP source must be integral", &I);
Assert1(DestTy->isFloatingPoint(),"SInt2FP result must be FP", &I);
visitInstruction(I);
}
void Verifier::visitFPToUIInst(FPToUIInst &I) {
// Get the source and destination types
const Type *SrcTy = I.getOperand(0)->getType();
const Type *DestTy = I.getType();
Assert1(SrcTy->isFloatingPoint(),"FP2UInt source must be FP", &I);
Assert1(DestTy->isIntegral(),"FP2UInt result must be integral", &I);
visitInstruction(I);
}
void Verifier::visitFPToSIInst(FPToSIInst &I) {
// Get the source and destination types
const Type *SrcTy = I.getOperand(0)->getType();
const Type *DestTy = I.getType();
Assert1(SrcTy->isFloatingPoint(),"FPToSI source must be FP", &I);
Assert1(DestTy->isIntegral(),"FP2ToI result must be integral", &I);
visitInstruction(I);
}
void Verifier::visitPtrToIntInst(PtrToIntInst &I) {
// Get the source and destination types
const Type *SrcTy = I.getOperand(0)->getType();
const Type *DestTy = I.getType();
Assert1(isa<PointerType>(SrcTy), "PtrToInt source must be pointer", &I);
Assert1(DestTy->isIntegral(), "PtrToInt result must be integral", &I);
visitInstruction(I);
}
void Verifier::visitIntToPtrInst(IntToPtrInst &I) {
// Get the source and destination types
const Type *SrcTy = I.getOperand(0)->getType();
const Type *DestTy = I.getType();
Assert1(SrcTy->isIntegral(), "IntToPtr source must be an integral", &I);
Assert1(isa<PointerType>(DestTy), "IntToPtr result must be a pointer",&I);
visitInstruction(I);
}
void Verifier::visitBitCastInst(BitCastInst &I) {
// Get the source and destination types
const Type *SrcTy = I.getOperand(0)->getType();
const Type *DestTy = I.getType();
// Get the size of the types in bits, we'll need this later
unsigned SrcBitSize = SrcTy->getPrimitiveSizeInBits();
unsigned DestBitSize = DestTy->getPrimitiveSizeInBits();
// BitCast implies a no-op cast of type only. No bits change.
// However, you can't cast pointers to anything but pointers.
Assert1(isa<PointerType>(DestTy) == isa<PointerType>(DestTy),
"Bitcast requires both operands to be pointer or neither", &I);
Assert1(SrcBitSize == DestBitSize, "Bitcast requies types of same width", &I);
visitInstruction(I);
}
/// visitPHINode - Ensure that a PHI node is well formed.
///
void Verifier::visitPHINode(PHINode &PN) {

View File

@ -367,7 +367,7 @@ StackerCompiler::incr_stack_index( BasicBlock* bb, Value* ival = 0 )
// Increment the loaded index value
if ( ival == 0 ) ival = One;
CastInst* caster = new CastInst( ival, Type::LongTy );
CastInst* caster = CastInst::createInferredCast( ival, Type::LongTy );
bb->getInstList().push_back( caster );
BinaryOperator* addop = BinaryOperator::create( Instruction::Add,
loadop, caster);
@ -388,7 +388,7 @@ StackerCompiler::decr_stack_index( BasicBlock* bb, Value* ival = 0 )
// Decrement the loaded index value
if ( ival == 0 ) ival = One;
CastInst* caster = new CastInst( ival, Type::LongTy );
CastInst* caster = CastInst::createInferredCast( ival, Type::LongTy );
bb->getInstList().push_back( caster );
BinaryOperator* subop = BinaryOperator::create( Instruction::Sub,
loadop, caster);
@ -422,7 +422,7 @@ StackerCompiler::get_stack_pointer( BasicBlock* bb, Value* index = 0 )
}
else
{
CastInst* caster = new CastInst( index, Type::LongTy );
CastInst* caster = CastInst::createInferredCast( index, Type::LongTy );
bb->getInstList().push_back( caster );
BinaryOperator* subop = BinaryOperator::create(
Instruction::Sub, loadop, caster );
@ -448,7 +448,7 @@ StackerCompiler::push_value( BasicBlock* bb, Value* val )
get_stack_pointer( bb ) );
// Cast the value to a long .. hopefully it works
CastInst* cast_inst = new CastInst( val, Type::LongTy );
CastInst* cast_inst = CastInst::createInferredCast( val, Type::LongTy );
bb->getInstList().push_back( cast_inst );
// Store the value
@ -522,7 +522,8 @@ StackerCompiler::pop_string( BasicBlock* bb )
bb->getInstList().push_back( loader );
// Cast the integer to a sbyte*
CastInst* caster = new CastInst( loader, PointerType::get(Type::SByteTy) );
CastInst* caster =
CastInst::createInferredCast( loader, PointerType::get(Type::SByteTy) );
bb->getInstList().push_back( caster );
// Decrement stack index
@ -574,7 +575,8 @@ StackerCompiler::stack_top_string( BasicBlock* bb, Value* index = 0 )
bb->getInstList().push_back( loader );
// Cast the integer to a sbyte*
CastInst* caster = new CastInst( loader, PointerType::get(Type::SByteTy) );
CastInst* caster =
CastInst::createInferredCast( loader, PointerType::get(Type::SByteTy) );
bb->getInstList().push_back( caster );
// Return the value
@ -1243,7 +1245,7 @@ StackerCompiler::handle_word( int tkn )
if (echo) bb->setName("SHL");
LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
CastInst* castop = new CastInst( op1, Type::UByteTy );
CastInst* castop = CastInst::createInferredCast( op1, Type::UByteTy );
bb->getInstList().push_back( castop );
ShiftInst* shlop = new ShiftInst( Instruction::Shl, op2, castop );
bb->getInstList().push_back( shlop );
@ -1255,7 +1257,7 @@ StackerCompiler::handle_word( int tkn )
if (echo) bb->setName("SHR");
LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
LoadInst* op2 = cast<LoadInst>(pop_integer(bb));
CastInst* castop = new CastInst( op1, Type::UByteTy );
CastInst* castop = CastInst::createInferredCast( op1, Type::UByteTy );
bb->getInstList().push_back( castop );
ShiftInst* shrop = new ShiftInst( Instruction::AShr, op2, castop );
bb->getInstList().push_back( shrop );
@ -1477,7 +1479,7 @@ StackerCompiler::handle_word( int tkn )
LoadInst* op1 = cast<LoadInst>( pop_integer(bb) );
// Make sure its a UIntTy
CastInst* caster = new CastInst( op1, Type::UIntTy );
CastInst* caster = CastInst::createInferredCast( op1, Type::UIntTy );
bb->getInstList().push_back( caster );
// Allocate the bytes
@ -1505,7 +1507,7 @@ StackerCompiler::handle_word( int tkn )
if (echo) bb->setName("GET");
// Get the character index
LoadInst* op1 = cast<LoadInst>( stack_top(bb) );
CastInst* chr_idx = new CastInst( op1, Type::LongTy );
CastInst* chr_idx = CastInst::createInferredCast( op1, Type::LongTy );
bb->getInstList().push_back( chr_idx );
// Get the String pointer
@ -1520,7 +1522,7 @@ StackerCompiler::handle_word( int tkn )
// Get the value and push it
LoadInst* loader = new LoadInst( gep );
bb->getInstList().push_back( loader );
CastInst* caster = new CastInst( loader, Type::IntTy );
CastInst* caster = CastInst::createInferredCast( loader, Type::IntTy );
bb->getInstList().push_back( caster );
// Push the result back on stack
@ -1537,7 +1539,7 @@ StackerCompiler::handle_word( int tkn )
// Get the character index
LoadInst* w2 = cast<LoadInst>( pop_integer(bb) );
CastInst* chr_idx = new CastInst( w2, Type::LongTy );
CastInst* chr_idx = CastInst::createInferredCast( w2, Type::LongTy );
bb->getInstList().push_back( chr_idx );
// Get the String pointer
@ -1550,7 +1552,7 @@ StackerCompiler::handle_word( int tkn )
bb->getInstList().push_back( gep );
// Cast the value and put it
CastInst* caster = new CastInst( w1, Type::SByteTy );
CastInst* caster = CastInst::createInferredCast( w1, Type::SByteTy );
bb->getInstList().push_back( caster );
StoreInst* storer = new StoreInst( caster, gep );
bb->getInstList().push_back( storer );
@ -1578,7 +1580,7 @@ StackerCompiler::handle_word( int tkn )
LoadInst* op1 = cast<LoadInst>(pop_integer(bb));
// Cast down to an integer
CastInst* caster = new CastInst( op1, Type::IntTy );
CastInst* caster = CastInst::createInferredCast( op1, Type::IntTy );
bb->getInstList().push_back( caster );
// Call exit(3)
@ -1660,9 +1662,9 @@ StackerCompiler::handle_word( int tkn )
// Make room for the value result
incr_stack_index(bb);
GetElementPtrInst* gep_value =
cast<GetElementPtrInst>(get_stack_pointer(bb));
CastInst* caster =
new CastInst( gep_value, PointerType::get( Type::SByteTy ) );
cast<GetElementPtrInst>(get_stack_pointer(bb));
CastInst* caster =
new BitCastInst(gep_value, PointerType::get(Type::SByteTy));
// Make room for the count result
incr_stack_index(bb);

View File

@ -0,0 +1,12 @@
; Check to make sure that Value Numbering doesn't merge casts of different
; flavors.
; RUN: llvm-as < %s | opt -load-vn -gcse | llvm-dis | grep '[sz]ext' | wc -l | grep 2
declare void %external(int)
int %test_casts(short %x) {
%a = sext short %x to int
%b = zext short %x to int
call void %external(int %a)
ret int %b
}

View File

@ -1,4 +1,4 @@
; RUN: llvm-as < %s | llvm-dis | grep ' cast ('
; RUN: llvm-as < %s | llvm-dis | grep ' bitcast ('
%.Base64_1 = external constant [4 x sbyte]

View File

@ -0,0 +1,16 @@
// RUN: %llvmgcc -S %s -o - | grep 'trunc.*to bool'
// RUN: %llvmgcc -S %s -o - | llvm-as | llc -march=x86 | grep and
int
main ( int argc, char** argv)
{
int i;
int result = 1;
for (i = 2; i <= 3; i++)
{
if ((i & 1) == 0)
{
result = result + 17;
}
}
return result;
}

View File

@ -5,7 +5,7 @@
bool %doTest(ubyte %x) {
%dec.0 = add ubyte %x, 255
%tmp.1001 = cast ubyte %dec.0 to bool
%tmp.1001 = trunc ubyte %dec.0 to bool
ret bool %tmp.1001
}

View File

@ -0,0 +1,32 @@
; An integer truncation to bool should be done with an and instruction to make
; sure only the LSBit survives. Test that this is the case both for a returned
; value and as the operand of a branch.
; RUN: llvm-as < %s | llc -march=x86 &&
; RUN: llvm-as < %s | llc -march=x86 | grep '\(and\)\|\(test.*1\)' | wc -l | grep 3
bool %test1(int %X) {
%Y = trunc int %X to bool
ret bool %Y
}
bool %test2(int %val, int %mask) {
entry:
%mask = trunc int %mask to ubyte
%shifted = ashr int %val, ubyte %mask
%anded = and int %shifted, 1
%trunced = trunc int %anded to bool
br bool %trunced, label %ret_true, label %ret_false
ret_true:
ret bool true
ret_false:
ret bool false
}
int %test3(sbyte* %ptr) {
%val = load sbyte* %ptr
%tmp = trunc sbyte %val to bool ; %<bool> [#uses=1]
br bool %tmp, label %cond_true, label %cond_false
cond_true:
ret int 21
cond_false:
ret int 42
}

View File

@ -2,7 +2,21 @@
; RUN: llvm-as %t1.ll -o - | llvm-dis > %t2.ll
; RUN: diff %t1.ll %t2.ll
implementation
void "NewCasts" (short %x) {
%a = zext short %x to int
%b = sext short %x to uint
%c = trunc short %x to ubyte
%d = uitofp short %x to float
%e = sitofp short %x to double
%f = fptoui float %d to short
%g = fptosi double %e to short
%i = fpext float %d to double
%j = fptrunc double %i to float
%k = bitcast int %a to float
%l = inttoptr short %x to int*
%m = ptrtoint int* %l to long
ret void
}
short "FunFunc"(long %x, sbyte %z)
begin

View File

@ -11,6 +11,6 @@ F:
bool %caller(bool %C) {
%X = call int %foo(bool %C)
%Y = cast int %X to bool
%Y = trunc int %X to bool
ret bool %Y
}

View File

@ -0,0 +1,20 @@
; RUN: llvm-as < %s | opt -inline | llvm-dis | grep 'ret int 1'
; ModuleID = 'short.opt.bc'
implementation ; Functions:
int %testBool(bool %X) {
%tmp = zext bool %X to int ; <int> [#uses=1]
ret int %tmp
}
int %testByte(sbyte %X) {
%tmp = setne sbyte %X, 0 ; <bool> [#uses=1]
%tmp.i = zext bool %tmp to int ; <int> [#uses=1]
ret int %tmp.i
}
int %main() {
%rslt = call int %testByte( sbyte 123)
ret int %rslt
}

View File

@ -1,5 +1,5 @@
; The cast in this testcase is not eliminatable on a 32-bit target!
; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep cast
; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep inttoptr
target endian = little
target pointersize = 32

View File

@ -1,5 +1,5 @@
; The optimizer should be able to remove cast operation here.
; RUN: llvm-as %s -o - | opt -instcombine | llvm-dis | not grep 'cast.*int'
; RUN: llvm-as %s -o - | opt -instcombine | llvm-dis | not grep 'sext.*int'
bool %eq_signed_to_small_unsigned(sbyte %SB) {
%Y = cast sbyte %SB to uint ; <uint> [#uses=1]

View File

@ -1,8 +1,9 @@
; This test case is reduced from llvmAsmParser.cpp
; The optimizer should not remove the cast here.
; RUN: llvm-as %s -o - | opt -instcombine | llvm-dis | grep 'cast.*int'
; RUN: llvm-as %s -o - | opt -instcombine | llvm-dis | grep 'sext.*int'
bool %test(short %X) {
%A = cast short %X to uint
%B = setgt uint %A, 1330
ret bool %B
%A = cast short %X to uint
%B = setgt uint %A, 1330
ret bool %B
}

View File

@ -0,0 +1,7 @@
; RUN: llvm-as < %s | opt -instcombine | llvm-dis | notcast
uint %testAdd(int %X, int %Y) {
%tmp = add int %X, %Y
%tmp.l = sext int %tmp to uint
ret uint %tmp.l
}

View File

@ -1,4 +1,4 @@
; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep call | not grep cast
; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep call | not grep bitcast
target endian = little
target pointersize = 32

View File

@ -0,0 +1,8 @@
; test that casted mallocs get converted to malloc of the right type
; RUN: llvm-as < %s | opt -instcombine | llvm-dis | not grep bitcast
int* %test(uint %size) {
%X = malloc long, uint %size
%ret = bitcast long* %X to int*
ret int* %ret
}

View File

@ -1,6 +1,6 @@
; Tests to make sure elimination of casts is working correctly
; RUN: llvm-as < %s | opt -instcombine -disable-output &&
; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep '%c' | not grep cast
; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep '%c' | notcast
%inbuf = external global [32832 x ubyte]
@ -104,7 +104,6 @@ bool %test16(int* %P) {
ret bool %c
}
short %test17(bool %tmp3) {
%c = cast bool %tmp3 to int
%t86 = cast int %c to short
@ -207,3 +206,8 @@ void %test32(double** %tmp) {
ret void
}
uint %test33(uint %c1) {
%x = bitcast uint %c1 to float
%y = bitcast float %x to uint
ret uint %y
}

View File

@ -1,6 +1,6 @@
; Tests to make sure elimination of casts is working correctly
; RUN: llvm-as < %s | opt -instcombine -disable-output &&
; RUN: llvm-as < %s | opt -instcombine | llvm-dis | not grep cast
; RUN: llvm-as < %s | opt -instcombine | llvm-dis | not grep '\([sz]ext\)\|\(trunc\)'
target pointersize = 32

View File

@ -0,0 +1,14 @@
; Test some floating point casting cases
; RUN: llvm-as %s -o - | opt -instcombine | llvm-dis | notcast
; RUN: llvm-as %s -o - | opt -instcombine | llvm-dis | \
; RUN: grep 'ret [us]byte \(-1\)\|\(255\)'
sbyte %test() {
%x = fptoui float 255.0 to sbyte
ret sbyte %x
}
ubyte %test() {
%x = fptosi float -1.0 to ubyte
ret ubyte %x
}

View File

@ -1,9 +1,9 @@
; RUN: llvm-as < %s | opt -instcombine | llvm-dis | not grep 'getelementptr.*cast'
; RUN: llvm-as < %s | opt -instcombine | llvm-dis | notcast '' 'getelementptr.*'
%G = external global [3 x sbyte]
implementation
ubyte *%foo(uint %Idx) {
%tmp = getelementptr ubyte* cast ([3 x sbyte]* %G to ubyte*), uint %Idx
ret ubyte* %tmp
%tmp = getelementptr ubyte* cast ([3 x sbyte]* %G to ubyte*), uint %Idx
ret ubyte* %tmp
}

View File

@ -1,4 +1,4 @@
; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep cast
; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep trunc
target endian = little
target pointersize = 32

View File

@ -8,10 +8,10 @@
;
bool %test1(int %A, int %B) {
%C1 = setlt int %A, %B
%ELIM1 = cast bool %C1 to uint
%ELIM1 = zext bool %C1 to uint
%C2 = setgt int %A, %B
%ELIM2 = cast bool %C2 to uint
%ELIM2 = zext bool %C2 to uint
%C3 = and uint %ELIM1, %ELIM2
%ELIM3 = cast uint %C3 to bool
%ELIM3 = trunc uint %C3 to bool
ret bool %ELIM3
}

View File

@ -0,0 +1,42 @@
; This test case was reduced from MultiSource/Applications/hbd. It makes sure
; that folding doesn't happen in case a zext is applied where a sext should have
; been when a setcc is used with two casts.
; RUN: llvm-as < %s | llc -instcombine | llvm-dis | not grep 'br bool false'
int %bug(ubyte %inbuff) {
entry:
%tmp = bitcast ubyte %inbuff to sbyte ; <sbyte> [#uses=1]
%tmp = sext sbyte %tmp to int ; <int> [#uses=3]
%tmp = seteq int %tmp, 1 ; <bool> [#uses=1]
br bool %tmp, label %cond_true, label %cond_next
cond_true: ; preds = %entry
br label %bb
cond_next: ; preds = %entry
%tmp3 = seteq int %tmp, -1 ; <bool> [#uses=1]
br bool %tmp3, label %cond_true4, label %cond_next5
cond_true4: ; preds = %cond_next
br label %bb
cond_next5: ; preds = %cond_next
%tmp7 = setgt int %tmp, 1 ; <bool> [#uses=1]
br bool %tmp7, label %cond_true8, label %cond_false
cond_true8: ; preds = %cond_next5
br label %cond_next9
cond_false: ; preds = %cond_next5
br label %cond_next9
cond_next9: ; preds = %cond_false, %cond_true8
%iftmp.1.0 = phi int [ 42, %cond_true8 ], [ 23, %cond_false ] ; <int> [#uses=1]
br label %return
bb: ; preds = %cond_true4, %cond_true
br label %return
return: ; preds = %bb, %cond_next9
%retval.0 = phi int [ 17, %bb ], [ %iftmp.1.0, %cond_next9 ] ; <int> [#uses=1]
ret int %retval.0
}

View File

@ -0,0 +1,9 @@
; Tests to make sure elimination of casts is working correctly
; RUN: llvm-as < %s | opt -instcombine -disable-output &&
; RUN: llvm-as < %s | opt -instcombine | llvm-dis | notcast '' '%c1.*'
long %test_sext_zext(short %A) {
%c1 = zext short %A to uint
%c2 = sext uint %c1 to long
ret long %c2
}

View File

@ -1,8 +1,8 @@
; This example should be raised to return a Hash directly without casting. To
; successful, all cast instructions should be eliminated from this testcase.
; This example should be raised to return a Hash directly without casting.
; LevelRaise should eliminate all cast instructions from this testcase.
;
; XFAIL: *
; RUN: llvm-as < %s | opt -raise | llvm-dis | not grep cast
; RUN: llvm-as < %s | opt -raise | llvm-dis | notcast
%Hash = type { { uint, sbyte *, \2 } * *, int (uint) *, int } *
%hash = type { { uint, sbyte *, \2 } * *, int (uint) *, int }

View File

@ -3,7 +3,7 @@
; prevented reg115 from being able to change.
;
; XFAIL: *
; RUN: llvm-as < %s | opt -raise | llvm-dis | grep '= cast' | not grep \*
; RUN: llvm-as < %s | opt -raise | llvm-dis | not grep bitcast
%Hash = type { { uint, sbyte *, \2 } * *, int (uint) *, int } *
%HashEntry = type { uint, sbyte *, \2 } *

View File

@ -1,5 +1,5 @@
; XFAIL: *
; RUN: llvm-as < %s | opt -raise | llvm-dis | grep '= cast' | not grep \*
; RUN: llvm-as < %s | opt -raise | llvm-dis | not grep bitcast
%Hash = type { { uint, sbyte *, \2 } * *, int (uint) *, int } *
%HashEntry = type { uint, sbyte *, \2 } *

View File

@ -6,7 +6,7 @@
; return (int*)malloc(i+j);
; }
; RUN: llvm-as < %s | opt -raise | llvm-dis | grep ' cast ' | not grep '*'
; RUN: llvm-as < %s | opt -raise | llvm-dis | not grep bitcast
implementation

View File

@ -1,6 +1,6 @@
; This testcase is not level raised properly...
; XFAIL: *
; RUN: llvm-as < %s | opt -raise | llvm-dis | grep ' cast ' | not grep '*'
; RUN: llvm-as < %s | opt -raise | llvm-dis | not grep bitcast
%List = type { int, %List* }

View File

@ -1,7 +1,7 @@
; This testcase should have the cast propogated through the load
; just like a store does...
;
; RUN: llvm-as < %s | opt -raise | llvm-dis | grep ' cast ' | not grep '*'
; RUN: llvm-as < %s | opt -raise | llvm-dis | not grep 'bitcast uint \*'
int "test"(uint * %Ptr) {
%P2 = cast uint *%Ptr to int *

View File

@ -1,5 +1,5 @@
; XFAIL: *
; RUN: llvm-as < %s | opt -raise | llvm-dis | grep '= cast' | not grep \*
; RUN: llvm-as < %s | opt -raise | llvm-dis | not grep bitcast
%FILE = type { int, ubyte*, ubyte*, ubyte, ubyte, uint, uint, uint }

Some files were not shown because too many files have changed in this diff Show More