mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-26 23:32:58 +00:00
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:
parent
5fed9b9044
commit
3da59db637
@ -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) {
|
||||
|
@ -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
|
||||
///
|
||||
|
@ -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
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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); }
|
||||
|
||||
|
@ -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
|
||||
//
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -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];
|
||||
|
@ -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) {
|
||||
|
@ -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
@ -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); }
|
||||
|
@ -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); }
|
||||
|
@ -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
@ -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
|
||||
|
@ -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
@ -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) {
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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();
|
||||
|
@ -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) \
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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()) &&
|
||||
|
@ -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),
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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))
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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()))
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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)) {
|
||||
|
@ -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> ";
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
12
test/Analysis/LoadVN/casts.ll
Normal file
12
test/Analysis/LoadVN/casts.ll
Normal 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
|
||||
}
|
@ -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]
|
||||
|
||||
|
16
test/CFrontend/cast-to-bool.c
Normal file
16
test/CFrontend/cast-to-bool.c
Normal 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;
|
||||
}
|
@ -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
|
||||
}
|
||||
|
||||
|
32
test/CodeGen/X86/trunc-to-bool.ll
Normal file
32
test/CodeGen/X86/trunc-to-bool.ll
Normal 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
|
||||
}
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
20
test/Transforms/Inline/casts.ll
Normal file
20
test/Transforms/Inline/casts.ll
Normal 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
|
||||
}
|
@ -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
|
||||
|
@ -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]
|
||||
|
@ -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
|
||||
}
|
||||
|
7
test/Transforms/InstCombine/binop-cast.ll
Normal file
7
test/Transforms/InstCombine/binop-cast.ll
Normal 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
|
||||
}
|
@ -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
|
||||
|
8
test/Transforms/InstCombine/cast-malloc.ll
Normal file
8
test/Transforms/InstCombine/cast-malloc.ll
Normal 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
|
||||
}
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
14
test/Transforms/InstCombine/fpcast.ll
Normal file
14
test/Transforms/InstCombine/fpcast.ll
Normal 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
|
||||
}
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
42
test/Transforms/InstCombine/setcc-cast-cast.ll
Normal file
42
test/Transforms/InstCombine/setcc-cast-cast.ll
Normal 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
|
||||
}
|
9
test/Transforms/InstCombine/zext.ll
Normal file
9
test/Transforms/InstCombine/zext.ll
Normal 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
|
||||
}
|
@ -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 }
|
||||
|
@ -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 } *
|
||||
|
@ -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 } *
|
||||
|
@ -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
|
||||
|
||||
|
@ -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* }
|
||||
|
||||
|
@ -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 *
|
||||
|
@ -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
Loading…
x
Reference in New Issue
Block a user