aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Transforms
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2001-11-04 23:24:20 +0000
committerChris Lattner <sabre@nondot.org>2001-11-04 23:24:20 +0000
commit901216d527ca4f73f603963c0f779a72e0fd93f4 (patch)
tree845ea004096ac87ced95c7bc8ea0885dfa30c124 /lib/Transforms
parent59cd9f1e9fcad6b40fc522010512f60ec10151d0 (diff)
downloadexternal_llvm-901216d527ca4f73f603963c0f779a72e0fd93f4.zip
external_llvm-901216d527ca4f73f603963c0f779a72e0fd93f4.tar.gz
external_llvm-901216d527ca4f73f603963c0f779a72e0fd93f4.tar.bz2
New file for expression tree conversion
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@1128 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms')
-rw-r--r--lib/Transforms/ExprTypeConvert.cpp494
1 files changed, 494 insertions, 0 deletions
diff --git a/lib/Transforms/ExprTypeConvert.cpp b/lib/Transforms/ExprTypeConvert.cpp
new file mode 100644
index 0000000..d7b1b77
--- /dev/null
+++ b/lib/Transforms/ExprTypeConvert.cpp
@@ -0,0 +1,494 @@
+//===- ExprTypeConvert.cpp - Code to change an LLVM Expr Type ---------------=//
+//
+// This file implements the part of level raising that checks to see if it is
+// possible to coerce an entire expression tree into a different type. If
+// convertable, other routines from this file will do the conversion.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TransformInternals.h"
+#include "llvm/Method.h"
+#include "llvm/Support/STLExtras.h"
+#include "llvm/iOther.h"
+#include "llvm/iMemory.h"
+#include "llvm/ConstPoolVals.h"
+#include "llvm/Optimizations/ConstantHandling.h"
+#include "llvm/Optimizations/DCE.h"
+#include <map>
+#include <algorithm>
+
+#include "llvm/Assembly/Writer.h"
+
+// ExpressionConvertableToType - Return true if it is possible
+static bool ExpressionConvertableToType(Value *V, const Type *Ty,
+ ValueTypeCache &CTMap) {
+ ValueTypeCache::iterator CTMI = CTMap.find(V);
+ if (CTMI != CTMap.end()) return CTMI->second == Ty;
+ CTMap[V] = Ty;
+
+ Instruction *I = dyn_cast<Instruction>(V);
+ if (I == 0) {
+ // It's not an instruction, check to see if it's a constant... all constants
+ // can be converted to an equivalent value (except pointers, they can't be
+ // const prop'd in general).
+ //
+ if (isa<ConstPoolVal>(V) &&
+ !isa<PointerType>(V->getType()) && !isa<PointerType>(Ty)) return true;
+
+ return false; // Otherwise, we can't convert!
+ }
+ if (I->getType() == Ty) return false; // Expression already correct type!
+
+ switch (I->getOpcode()) {
+ case Instruction::Cast:
+ // We can convert the expr if the cast destination type is losslessly
+ // convertable to the requested type.
+ return losslessCastableTypes(Ty, I->getType());
+
+ case Instruction::Add:
+ case Instruction::Sub:
+ return ExpressionConvertableToType(I->getOperand(0), Ty, CTMap) &&
+ ExpressionConvertableToType(I->getOperand(1), Ty, CTMap);
+ case Instruction::Shr:
+ if (Ty->isSigned() != V->getType()->isSigned()) return false;
+ // FALL THROUGH
+ case Instruction::Shl:
+ return ExpressionConvertableToType(I->getOperand(0), Ty, CTMap);
+
+ case Instruction::Load: {
+ LoadInst *LI = cast<LoadInst>(I);
+ if (LI->hasIndices()) return false;
+ return ExpressionConvertableToType(LI->getPtrOperand(),
+ PointerType::get(Ty), CTMap);
+ }
+ case Instruction::GetElementPtr: {
+ // GetElementPtr's are directly convertable to a pointer type if they have
+ // a number of zeros at the end. Because removing these values does not
+ // change the logical offset of the GEP, it is okay and fair to remove them.
+ // This can change this:
+ // %t1 = getelementptr %Hosp * %hosp, ubyte 4, ubyte 0 ; <%List **>
+ // %t2 = cast %List * * %t1 to %List *
+ // into
+ // %t2 = getelementptr %Hosp * %hosp, ubyte 4 ; <%List *>
+ //
+ GetElementPtrInst *GEP = cast<GetElementPtrInst>(I);
+ const PointerType *PTy = dyn_cast<PointerType>(Ty);
+ if (!PTy) return false;
+
+ // Check to see if there are zero elements that we can remove from the
+ // index array. If there are, check to see if removing them causes us to
+ // get to the right type...
+ //
+ vector<ConstPoolVal*> Indices = GEP->getIndices();
+ const Type *BaseType = GEP->getPtrOperand()->getType();
+
+ while (Indices.size() &&
+ cast<ConstPoolUInt>(Indices.back())->getValue() == 0) {
+ Indices.pop_back();
+ const Type *ElTy = GetElementPtrInst::getIndexedType(BaseType, Indices,
+ true);
+ if (ElTy == PTy->getValueType())
+ return true; // Found a match!!
+ }
+ break; // No match, maybe next time.
+ }
+ }
+ return false;
+}
+
+
+
+
+static Value *ConvertExpressionToType(Value *V, const Type *Ty,
+ ValueMapCache &VMC) {
+ Instruction *I = dyn_cast<Instruction>(V);
+ if (I == 0)
+ if (ConstPoolVal *CPV = cast<ConstPoolVal>(V)) {
+ // Constants are converted by constant folding the cast that is required.
+ // We assume here that all casts are implemented for constant prop.
+ Value *Result = opt::ConstantFoldCastInstruction(CPV, Ty);
+ if (!Result) cerr << "Couldn't fold " << CPV << " to " << Ty << endl;
+ assert(Result && "ConstantFoldCastInstruction Failed!!!");
+ return Result;
+ }
+
+
+ BasicBlock *BB = I->getParent();
+ BasicBlock::InstListType &BIL = BB->getInstList();
+ string Name = I->getName(); if (!Name.empty()) I->setName("");
+ Instruction *Res; // Result of conversion
+
+ //cerr << endl << endl << "Type:\t" << Ty << "\nInst: " << I << "BB Before: " << BB << endl;
+
+ switch (I->getOpcode()) {
+ case Instruction::Cast:
+ Res = new CastInst(I->getOperand(0), Ty, Name);
+ break;
+
+ case Instruction::Add:
+ case Instruction::Sub:
+ Res = BinaryOperator::create(cast<BinaryOperator>(I)->getOpcode(),
+ ConvertExpressionToType(I->getOperand(0), Ty, VMC),
+ ConvertExpressionToType(I->getOperand(1), Ty, VMC),
+ Name);
+ break;
+
+ case Instruction::Shl:
+ case Instruction::Shr:
+ Res = new ShiftInst(cast<ShiftInst>(I)->getOpcode(),
+ ConvertExpressionToType(I->getOperand(0), Ty, VMC),
+ I->getOperand(1), Name);
+ break;
+
+ case Instruction::Load: {
+ LoadInst *LI = cast<LoadInst>(I);
+ assert(!LI->hasIndices());
+ Res = new LoadInst(ConvertExpressionToType(LI->getPtrOperand(),
+ PointerType::get(Ty), VMC),
+ Name);
+ break;
+ }
+
+ case Instruction::GetElementPtr: {
+ // GetElementPtr's are directly convertable to a pointer type if they have
+ // a number of zeros at the end. Because removing these values does not
+ // change the logical offset of the GEP, it is okay and fair to remove them.
+ // This can change this:
+ // %t1 = getelementptr %Hosp * %hosp, ubyte 4, ubyte 0 ; <%List **>
+ // %t2 = cast %List * * %t1 to %List *
+ // into
+ // %t2 = getelementptr %Hosp * %hosp, ubyte 4 ; <%List *>
+ //
+ GetElementPtrInst *GEP = cast<GetElementPtrInst>(I);
+
+ // Check to see if there are zero elements that we can remove from the
+ // index array. If there are, check to see if removing them causes us to
+ // get to the right type...
+ //
+ vector<ConstPoolVal*> Indices = GEP->getIndices();
+ const Type *BaseType = GEP->getPtrOperand()->getType();
+ const Type *PVTy = cast<PointerType>(Ty)->getValueType();
+ Res = 0;
+ while (Indices.size() &&
+ cast<ConstPoolUInt>(Indices.back())->getValue() == 0) {
+ Indices.pop_back();
+ if (GetElementPtrInst::getIndexedType(BaseType, Indices, true) == PVTy) {
+ if (Indices.size() == 0) {
+ Res = new CastInst(GEP->getPtrOperand(), BaseType); // NOOP
+ } else {
+ Res = new GetElementPtrInst(GEP->getPtrOperand(), Indices, Name);
+ }
+ break;
+ }
+ }
+ assert(Res && "Didn't find match!");
+ break; // No match, maybe next time.
+ }
+
+ default:
+ assert(0 && "Expression convertable, but don't know how to convert?");
+ return 0;
+ }
+
+ BasicBlock::iterator It = find(BIL.begin(), BIL.end(), I);
+ assert(It != BIL.end() && "Instruction not in own basic block??");
+ BIL.insert(It, Res);
+
+ //cerr << "RInst: " << Res << "BB After: " << BB << endl << endl;
+
+ return Res;
+}
+
+
+
+
+
+
+
+static inline const Type *getTy(const Value *V, ValueTypeCache &CT) {
+ ValueTypeCache::iterator I = CT.find(V);
+ if (I == CT.end()) return V->getType();
+ return I->second;
+}
+
+
+static bool OperandConvertableToType(User *U, Value *V, const Type *Ty,
+ ValueTypeCache &ConvertedTypes);
+
+// RetValConvertableToType - Return true if it is possible
+bool RetValConvertableToType(Value *V, const Type *Ty,
+ ValueTypeCache &ConvertedTypes) {
+ ValueTypeCache::iterator I = ConvertedTypes.find(V);
+ if (I != ConvertedTypes.end()) return I->second == Ty;
+ ConvertedTypes[V] = Ty;
+
+ // It is safe to convert the specified value to the specified type IFF all of
+ // the uses of the value can be converted to accept the new typed value.
+ //
+ for (Value::use_iterator I = V->use_begin(), E = V->use_end(); I != E; ++I)
+ if (!OperandConvertableToType(*I, V, Ty, ConvertedTypes))
+ return false;
+
+ return true;
+}
+
+
+// OperandConvertableToType - 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
+// of converted types, so that circular definitions will see the future type of
+// the expression, not the static current type.
+//
+static bool OperandConvertableToType(User *U, Value *V, const Type *Ty,
+ ValueTypeCache &CTMap) {
+ assert(V->getType() != Ty &&
+ "OperandConvertableToType: Operand is already right type!");
+ Instruction *I = dyn_cast<Instruction>(U);
+ if (I == 0) return false; // We can't convert!
+
+ switch (I->getOpcode()) {
+ case Instruction::Cast:
+ assert(I->getOperand(0) == V);
+ // We can convert the expr if the cast destination type is losslessly
+ // convertable to the requested type.
+ return losslessCastableTypes(Ty, I->getOperand(0)->getType());
+
+ case Instruction::Add:
+ case Instruction::Sub: {
+ Value *OtherOp = I->getOperand((V == I->getOperand(0)) ? 1 : 0);
+ return RetValConvertableToType(I, Ty, CTMap) &&
+ ExpressionConvertableToType(OtherOp, Ty, CTMap);
+ }
+ case Instruction::SetEQ:
+ case Instruction::SetNE: {
+ Value *OtherOp = I->getOperand((V == I->getOperand(0)) ? 1 : 0);
+ return ExpressionConvertableToType(OtherOp, Ty, CTMap);
+ }
+ case Instruction::Shr:
+ if (Ty->isSigned() != V->getType()->isSigned()) return false;
+ // FALL THROUGH
+ case Instruction::Shl:
+ assert(I->getOperand(0) == V);
+ return RetValConvertableToType(I, Ty, CTMap);
+
+ case Instruction::Load:
+ assert(I->getOperand(0) == V);
+ if (const PointerType *PT = dyn_cast<PointerType>(Ty)) {
+ LoadInst *LI = cast<LoadInst>(I);
+ if (LI->hasIndices() ||
+ TD.getTypeSize(PT->getValueType()) != TD.getTypeSize(LI->getType()))
+ return false;
+
+ return RetValConvertableToType(LI, PT->getValueType(), CTMap);
+ }
+ return false;
+
+ case Instruction::Store: {
+ StoreInst *SI = cast<StoreInst>(I);
+ if (SI->hasIndices()) return false;
+
+ if (V == I->getOperand(0)) {
+ // Can convert the store if we can convert the pointer operand to match
+ // the new value type...
+ return ExpressionConvertableToType(I->getOperand(1), PointerType::get(Ty),
+ CTMap);
+ } else if (const PointerType *PT = dyn_cast<PointerType>(Ty)) {
+ if (isa<ArrayType>(PT->getValueType()))
+ return false; // Avoid getDataSize on unsized array type!
+ assert(V == I->getOperand(1));
+
+ // Must move the same amount of data...
+ if (TD.getTypeSize(PT->getValueType()) !=
+ TD.getTypeSize(I->getOperand(0)->getType())) return false;
+
+ // Can convert store if the incoming value is convertable...
+ return ExpressionConvertableToType(I->getOperand(0), PT->getValueType(),
+ CTMap);
+ }
+ return false;
+ }
+
+
+#if 0
+ case Instruction::GetElementPtr: {
+ // GetElementPtr's are directly convertable to a pointer type if they have
+ // a number of zeros at the end. Because removing these values does not
+ // change the logical offset of the GEP, it is okay and fair to remove them.
+ // This can change this:
+ // %t1 = getelementptr %Hosp * %hosp, ubyte 4, ubyte 0 ; <%List **>
+ // %t2 = cast %List * * %t1 to %List *
+ // into
+ // %t2 = getelementptr %Hosp * %hosp, ubyte 4 ; <%List *>
+ //
+ GetElementPtrInst *GEP = cast<GetElementPtrInst>(I);
+ const PointerType *PTy = dyn_cast<PointerType>(Ty);
+ if (!PTy) return false;
+
+ // Check to see if there are zero elements that we can remove from the
+ // index array. If there are, check to see if removing them causes us to
+ // get to the right type...
+ //
+ vector<ConstPoolVal*> Indices = GEP->getIndices();
+ const Type *BaseType = GEP->getPtrOperand()->getType();
+
+ while (Indices.size() &&
+ cast<ConstPoolUInt>(Indices.back())->getValue() == 0) {
+ Indices.pop_back();
+ const Type *ElTy = GetElementPtrInst::getIndexedType(BaseType, Indices,
+ true);
+ if (ElTy == PTy->getValueType())
+ return true; // Found a match!!
+ }
+ break; // No match, maybe next time.
+ }
+#endif
+ }
+ return false;
+}
+
+
+
+
+
+
+static void ConvertOperandToType(User *U, Value *OldVal, Value *NewVal,
+ ValueMapCache &VMC);
+
+void ConvertUsersType(Value *V, Value *NewVal, ValueMapCache &VMC) {
+
+ // It is safe to convert the specified value to the specified type IFF all of
+ // the uses of the value can be converted to accept the new typed value.
+ //
+ while (!V->use_empty()) {
+ unsigned OldSize = V->use_size();
+ ConvertOperandToType(V->use_back(), V, NewVal, VMC);
+ assert(V->use_size() != OldSize && "Use didn't detatch from value!");
+ }
+}
+
+
+
+static void ConvertOperandToType(User *U, Value *OldVal, Value *NewVal,
+ ValueMapCache &VMC) {
+ Instruction *I = cast<Instruction>(U); // Only Instructions convertable
+
+ BasicBlock *BB = I->getParent();
+ BasicBlock::InstListType &BIL = BB->getInstList();
+ string Name = I->getName(); if (!Name.empty()) I->setName("");
+ Instruction *Res; // Result of conversion
+
+ //cerr << endl << endl << "Type:\t" << Ty << "\nInst: " << I << "BB Before: " << BB << endl;
+
+ switch (I->getOpcode()) {
+ case Instruction::Cast:
+ assert(I->getOperand(0) == OldVal);
+ Res = new CastInst(NewVal, I->getType(), Name);
+ break;
+
+ case Instruction::Add:
+ case Instruction::Sub:
+ case Instruction::SetEQ:
+ case Instruction::SetNE: {
+ unsigned OtherIdx = (OldVal == I->getOperand(0)) ? 1 : 0;
+ Value *OtherOp = I->getOperand(OtherIdx);
+ Value *NewOther = ConvertExpressionToType(OtherOp, NewVal->getType(),VMC);
+
+ Res = BinaryOperator::create(cast<BinaryOperator>(I)->getOpcode(),
+ OtherIdx == 0 ? NewOther : NewVal,
+ OtherIdx == 1 ? NewOther : NewVal,
+ Name);
+ break;
+ }
+ case Instruction::Shl:
+ case Instruction::Shr:
+ assert(I->getOperand(0) == OldVal);
+ Res = new ShiftInst(cast<ShiftInst>(I)->getOpcode(), NewVal,
+ I->getOperand(1), Name);
+ break;
+
+ case Instruction::Load:
+ assert(I->getOperand(0) == OldVal);
+ Res = new LoadInst(NewVal, Name);
+ break;
+
+ case Instruction::Store: {
+ if (I->getOperand(0) == OldVal) { // Replace the source value
+ Value *NewPtr =
+ ConvertExpressionToType(I->getOperand(1),
+ PointerType::get(NewVal->getType()), VMC);
+ Res = new StoreInst(NewVal, NewPtr);
+ } else { // Replace the source pointer
+ const Type *ValType =cast<PointerType>(NewVal->getType())->getValueType();
+ Value *NewV = ConvertExpressionToType(I->getOperand(0), ValType, VMC);
+ Res = new StoreInst(NewV, NewVal);
+ }
+ break;
+ }
+
+#if 0
+ case Instruction::GetElementPtr: {
+ // GetElementPtr's are directly convertable to a pointer type if they have
+ // a number of zeros at the end. Because removing these values does not
+ // change the logical offset of the GEP, it is okay and fair to remove them.
+ // This can change this:
+ // %t1 = getelementptr %Hosp * %hosp, ubyte 4, ubyte 0 ; <%List **>
+ // %t2 = cast %List * * %t1 to %List *
+ // into
+ // %t2 = getelementptr %Hosp * %hosp, ubyte 4 ; <%List *>
+ //
+ GetElementPtrInst *GEP = cast<GetElementPtrInst>(I);
+
+ // Check to see if there are zero elements that we can remove from the
+ // index array. If there are, check to see if removing them causes us to
+ // get to the right type...
+ //
+ vector<ConstPoolVal*> Indices = GEP->getIndices();
+ const Type *BaseType = GEP->getPtrOperand()->getType();
+ const Type *PVTy = cast<PointerType>(Ty)->getValueType();
+ Res = 0;
+ while (Indices.size() &&
+ cast<ConstPoolUInt>(Indices.back())->getValue() == 0) {
+ Indices.pop_back();
+ if (GetElementPtrInst::getIndexedType(BaseType, Indices, true) == PVTy) {
+ if (Indices.size() == 0) {
+ Res = new CastInst(GEP->getPtrOperand(), BaseType); // NOOP
+ } else {
+ Res = new GetElementPtrInst(GEP->getPtrOperand(), Indices, Name);
+ }
+ break;
+ }
+ }
+ assert(Res && "Didn't find match!");
+ break; // No match, maybe next time.
+ }
+#endif
+
+ default:
+ assert(0 && "Expression convertable, but don't know how to convert?");
+ return;
+ }
+
+ BasicBlock::iterator It = find(BIL.begin(), BIL.end(), I);
+ assert(It != BIL.end() && "Instruction not in own basic block??");
+ BIL.insert(It, Res); // Keep It pointing to old instruction
+
+#if DEBUG_PEEPHOLE_INSTS
+ cerr << "In: " << I << "Out: " << Res;
+#endif
+
+ //cerr << "RInst: " << Res << "BB After: " << BB << endl << endl;
+
+ if (I->getType() != Res->getType())
+ ConvertUsersType(I, Res, VMC);
+ else
+ I->replaceAllUsesWith(Res);
+
+ // Now we just need to remove the old instruction so we don't get infinite
+ // loops. Note that we cannot use DCE because DCE won't remove a store
+ // instruction, for example.
+ assert(I->use_size() == 0 && "Uses of Instruction remain!!!");
+
+ It = find(BIL.begin(), BIL.end(), I);
+ assert(It != BIL.end() && "Instruction no longer in basic block??");
+ delete BIL.remove(It);
+}