diff options
author | Reid Spencer <rspencer@reidspencer.com> | 2006-11-27 01:05:10 +0000 |
---|---|---|
committer | Reid Spencer <rspencer@reidspencer.com> | 2006-11-27 01:05:10 +0000 |
commit | 3da59db637a887474c1b1346c1f3ccf53b6c4663 (patch) | |
tree | b061e2133efdb9ea9bb334c1b15ceea881bb88f8 | |
parent | 5fed9b90447a9a95a1f670ccd9c23aea8c937451 (diff) |
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
105 files changed, 6683 insertions, 3646 deletions
diff --git a/include/llvm/Analysis/ScalarEvolutionExpander.h b/include/llvm/Analysis/ScalarEvolutionExpander.h index 391c12b2ba..163d35761c 100644 --- a/include/llvm/Analysis/ScalarEvolutionExpander.h +++ b/include/llvm/Analysis/ScalarEvolutionExpander.h @@ -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) { diff --git a/include/llvm/Constants.h b/include/llvm/Constants.h index 20f36438b1..f78ace36f8 100644 --- a/include/llvm/Constants.h +++ b/include/llvm/Constants.h @@ -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 /// diff --git a/include/llvm/InstrTypes.h b/include/llvm/InstrTypes.h index 627aad4304..0a489f3d08 100644 --- a/include/llvm/InstrTypes.h +++ b/include/llvm/InstrTypes.h @@ -244,6 +244,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.< |