+//===----------------------------------------------------------------------===//
+// CastInst Class
+//===----------------------------------------------------------------------===//
+
+// 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()->isInteger() && getType()->isInteger();
+ }
+}
+
+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;
+
+ // Pointer to pointer is always lossless.
+ if (isa<PointerType>(SrcTy))
+ return isa<PointerType>(DstTy);
+ 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 vector< 2 x int > %x, vector< 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
+ //
+ // NOTE: some transforms are safe, but we consider them to be non-profitable.
+ // For example, we could merge "fptoui double to uint" + "zext uint to ulong",
+ // into "fptoui double to ulong", but this loses information about the range
+ // of the produced value (we no longer know the top-part is all zeros).
+ // Further this conversion is often much more expensive for typical hardware,
+ // and causes issues when building libgcc. We disallow fptosi+sext for the
+ // same reason.
+ 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, 0, 0,99,99, 0, 0,99,99,99, 0, 3 }, // FPToUI |
+ { 0, 0, 0,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;
+}
+
+CastInst *CastInst::createZExtOrBitCast(Value *S, const Type *Ty,
+ const std::string &Name,
+ Instruction *InsertBefore) {
+ if (S->getType()->getPrimitiveSizeInBits() == Ty->getPrimitiveSizeInBits())
+ return create(Instruction::BitCast, S, Ty, Name, InsertBefore);
+ return create(Instruction::ZExt, S, Ty, Name, InsertBefore);
+}
+
+CastInst *CastInst::createZExtOrBitCast(Value *S, const Type *Ty,
+ const std::string &Name,
+ BasicBlock *InsertAtEnd) {
+ if (S->getType()->getPrimitiveSizeInBits() == Ty->getPrimitiveSizeInBits())
+ return create(Instruction::BitCast, S, Ty, Name, InsertAtEnd);
+ return create(Instruction::ZExt, S, Ty, Name, InsertAtEnd);
+}
+
+CastInst *CastInst::createSExtOrBitCast(Value *S, const Type *Ty,
+ const std::string &Name,
+ Instruction *InsertBefore) {
+ if (S->getType()->getPrimitiveSizeInBits() == Ty->getPrimitiveSizeInBits())
+ return create(Instruction::BitCast, S, Ty, Name, InsertBefore);
+ return create(Instruction::SExt, S, Ty, Name, InsertBefore);
+}
+
+CastInst *CastInst::createSExtOrBitCast(Value *S, const Type *Ty,
+ const std::string &Name,
+ BasicBlock *InsertAtEnd) {
+ if (S->getType()->getPrimitiveSizeInBits() == Ty->getPrimitiveSizeInBits())
+ return create(Instruction::BitCast, S, Ty, Name, InsertAtEnd);
+ return create(Instruction::SExt, S, Ty, Name, InsertAtEnd);
+}
+
+CastInst *CastInst::createTruncOrBitCast(Value *S, const Type *Ty,
+ const std::string &Name,
+ Instruction *InsertBefore) {
+ if (S->getType()->getPrimitiveSizeInBits() == Ty->getPrimitiveSizeInBits())
+ return create(Instruction::BitCast, S, Ty, Name, InsertBefore);
+ return create(Instruction::Trunc, S, Ty, Name, InsertBefore);
+}
+
+CastInst *CastInst::createTruncOrBitCast(Value *S, const Type *Ty,
+ const std::string &Name,
+ BasicBlock *InsertAtEnd) {
+ if (S->getType()->getPrimitiveSizeInBits() == Ty->getPrimitiveSizeInBits())
+ return create(Instruction::BitCast, S, Ty, Name, InsertAtEnd);
+ return create(Instruction::Trunc, S, Ty, Name, InsertAtEnd);
+}
+
+CastInst *CastInst::createPointerCast(Value *S, const Type *Ty,
+ const std::string &Name,
+ BasicBlock *InsertAtEnd) {
+ assert(isa<PointerType>(S->getType()) && "Invalid cast");
+ assert((Ty->isInteger() || isa<PointerType>(Ty)) &&
+ "Invalid cast");
+
+ if (Ty->isInteger())
+ return create(Instruction::PtrToInt, S, Ty, Name, InsertAtEnd);
+ return create(Instruction::BitCast, S, Ty, Name, InsertAtEnd);
+}
+
+/// @brief Create a BitCast or a PtrToInt cast instruction
+CastInst *CastInst::createPointerCast(Value *S, const Type *Ty,
+ const std::string &Name,
+ Instruction *InsertBefore) {
+ assert(isa<PointerType>(S->getType()) && "Invalid cast");
+ assert((Ty->isInteger() || isa<PointerType>(Ty)) &&
+ "Invalid cast");
+
+ if (Ty->isInteger())
+ return create(Instruction::PtrToInt, S, Ty, Name, InsertBefore);
+ return create(Instruction::BitCast, S, Ty, Name, InsertBefore);
+}
+
+CastInst *CastInst::createIntegerCast(Value *C, const Type *Ty,
+ bool isSigned, const std::string &Name,
+ Instruction *InsertBefore) {
+ assert(C->getType()->isInteger() && Ty->isInteger() && "Invalid cast");
+ unsigned SrcBits = C->getType()->getPrimitiveSizeInBits();
+ unsigned DstBits = Ty->getPrimitiveSizeInBits();
+ Instruction::CastOps opcode =
+ (SrcBits == DstBits ? Instruction::BitCast :
+ (SrcBits > DstBits ? Instruction::Trunc :
+ (isSigned ? Instruction::SExt : Instruction::ZExt)));
+ return create(opcode, C, Ty, Name, InsertBefore);
+}
+
+CastInst *CastInst::createIntegerCast(Value *C, const Type *Ty,
+ bool isSigned, const std::string &Name,
+ BasicBlock *InsertAtEnd) {
+ assert(C->getType()->isInteger() && Ty->isInteger() && "Invalid cast");
+ unsigned SrcBits = C->getType()->getPrimitiveSizeInBits();
+ unsigned DstBits = Ty->getPrimitiveSizeInBits();
+ Instruction::CastOps opcode =
+ (SrcBits == DstBits ? Instruction::BitCast :
+ (SrcBits > DstBits ? Instruction::Trunc :
+ (isSigned ? Instruction::SExt : Instruction::ZExt)));
+ return create(opcode, C, Ty, Name, InsertAtEnd);
+}
+
+CastInst *CastInst::createFPCast(Value *C, const Type *Ty,
+ const std::string &Name,
+ Instruction *InsertBefore) {
+ assert(C->getType()->isFloatingPoint() && Ty->isFloatingPoint() &&
+ "Invalid cast");
+ unsigned SrcBits = C->getType()->getPrimitiveSizeInBits();
+ unsigned DstBits = Ty->getPrimitiveSizeInBits();
+ Instruction::CastOps opcode =
+ (SrcBits == DstBits ? Instruction::BitCast :
+ (SrcBits > DstBits ? Instruction::FPTrunc : Instruction::FPExt));
+ return create(opcode, C, Ty, Name, InsertBefore);
+}
+
+CastInst *CastInst::createFPCast(Value *C, const Type *Ty,
+ const std::string &Name,
+ BasicBlock *InsertAtEnd) {
+ assert(C->getType()->isFloatingPoint() && Ty->isFloatingPoint() &&
+ "Invalid cast");
+ unsigned SrcBits = C->getType()->getPrimitiveSizeInBits();
+ unsigned DstBits = Ty->getPrimitiveSizeInBits();
+ Instruction::CastOps opcode =
+ (SrcBits == DstBits ? Instruction::BitCast :
+ (SrcBits > DstBits ? Instruction::FPTrunc : Instruction::FPExt));
+ return create(opcode, C, Ty, Name, InsertAtEnd);
+}
+
+// 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 castIsValid function below. This axiom should hold:
+// castIsValid( getCastOpcode(Val, Ty), Val, Ty)
+// should not assert in castIsValid. In other words, this produces a "correct"
+// casting opcode for the arguments passed to it.
+Instruction::CastOps
+CastInst::getCastOpcode(
+ const Value *Src, bool SrcIsSigned, const Type *DestTy, bool DestIsSigned) {
+ // Get the bit sizes, we'll need these
+ const Type *SrcTy = Src->getType();
+ unsigned SrcBits = SrcTy->getPrimitiveSizeInBits(); // 0 for ptr/vector
+ unsigned DestBits = DestTy->getPrimitiveSizeInBits(); // 0 for ptr/vector
+
+ // Run through the possibilities ...
+ if (DestTy->isInteger()) { // Casting to integral
+ if (SrcTy->isInteger()) { // Casting from integral
+ if (DestBits < SrcBits)
+ return Trunc; // int -> smaller int
+ else if (DestBits > SrcBits) { // its an extension
+ if (SrcIsSigned)
+ 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 (DestIsSigned)
+ return FPToSI; // FP -> sint
+ else
+ return FPToUI; // FP -> uint
+ } else if (const VectorType *PTy = dyn_cast<VectorType>(SrcTy)) {
+ assert(DestBits == PTy->getBitWidth() &&
+ "Casting vector 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->isInteger()) { // Casting from integral
+ if (SrcIsSigned)
+ 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 VectorType *PTy = dyn_cast<VectorType>(SrcTy)) {
+ assert(DestBits == PTy->getBitWidth() &&
+ "Casting vector 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 VectorType *DestPTy = dyn_cast<VectorType>(DestTy)) {
+ if (const VectorType *SrcPTy = dyn_cast<VectorType>(SrcTy)) {
+ assert(DestPTy->getBitWidth() == SrcPTy->getBitWidth() &&
+ "Casting vector to vector of different widths");
+ return BitCast; // vector -> vector
+ } else if (DestPTy->getBitWidth() == SrcBits) {
+ return BitCast; // float/int -> vector
+ } else {
+ assert(!"Illegal cast to vector (wrong type or size)");
+ }
+ } else if (isa<PointerType>(DestTy)) {
+ if (isa<PointerType>(SrcTy)) {
+ return BitCast; // ptr -> ptr
+ } else if (SrcTy->isInteger()) {
+ 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;
+}