aboutsummaryrefslogtreecommitdiff
path: root/lib/Transforms/LevelRaise.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Transforms/LevelRaise.cpp')
-rw-r--r--lib/Transforms/LevelRaise.cpp308
1 files changed, 297 insertions, 11 deletions
diff --git a/lib/Transforms/LevelRaise.cpp b/lib/Transforms/LevelRaise.cpp
index ff932b6912..58606f098d 100644
--- a/lib/Transforms/LevelRaise.cpp
+++ b/lib/Transforms/LevelRaise.cpp
@@ -220,10 +220,10 @@ static bool ExpressionConvertableToType(Value *V, const Type *Ty) {
case Instruction::Sub:
return ExpressionConvertableToType(I->getOperand(0), Ty) &&
ExpressionConvertableToType(I->getOperand(1), Ty);
- case Instruction::Shl:
- return ExpressionConvertableToType(I->getOperand(0), Ty);
case Instruction::Shr:
if (Ty->isSigned() != V->getType()->isSigned()) return false;
+ // FALL THROUGH
+ case Instruction::Shl:
return ExpressionConvertableToType(I->getOperand(0), Ty);
case Instruction::Load: {
@@ -369,6 +369,286 @@ static Value *ConvertExpressionToType(Value *V, const Type *Ty) {
+
+
+
+static bool OperandConvertableToType(User *U, Value *V, const Type *Ty);
+
+// RetValConvertableToType - Return true if it is possible
+static bool RetValConvertableToType(Value *V, const Type *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))
+ return false;
+
+ return true;
+}
+
+
+
+
+
+
+static bool OperandConvertableToType(User *U, Value *V, const Type *Ty) {
+ 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 ExpressionConvertableToType(OtherOp, Ty) &&
+ RetValConvertableToType(I, Ty);
+ }
+ case Instruction::SetEQ:
+ case Instruction::SetNE: {
+ Value *OtherOp = I->getOperand((V == I->getOperand(0)) ? 1 : 0);
+ return ExpressionConvertableToType(OtherOp, Ty);
+ }
+ 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);
+
+ 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());
+ }
+ 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));
+ } else if (const PointerType *PT = dyn_cast<PointerType>(Ty)) {
+ 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());
+ }
+ 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);
+
+// RetValConvertableToType - Return true if it is possible
+static void ConvertUsersType(Value *V, Value *NewVal) {
+ // 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);
+ assert(V->use_size() != OldSize && "Use didn't detatch from value!");
+ }
+}
+
+
+
+static void ConvertOperandToType(User *U, Value *OldVal, Value *NewVal) {
+ 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());
+
+ 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()));
+ 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);
+ 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
+
+ cerr << "In: " << I << "Out: " << Res;
+
+ //cerr << "RInst: " << Res << "BB After: " << BB << endl << endl;
+
+ if (I->getType() != Res->getType())
+ ConvertUsersType(I, Res);
+ 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);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
// DoInsertArrayCast - If the argument value has a pointer type, and if the
// argument value is used as an array, insert a cast before the specified
// basic block iterator that casts the value to an array pointer. Return the
@@ -573,8 +853,8 @@ static bool PeepholeOptimize(BasicBlock *BB, BasicBlock::iterator &BI) {
CI->replaceAllUsesWith(Src);
if (!Src->hasName() && CI->hasName()) {
string Name = CI->getName();
- CI->setName(""); Src->setName(Name,
- BB->getParent()->getSymbolTable());
+ CI->setName("");
+ Src->setName(Name, BB->getParent()->getSymbolTable());
}
return true;
}
@@ -601,13 +881,19 @@ static bool 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) &&
- ExpressionConvertableToType(Src, DestTy)) {
- PRINT_PEEPHOLE2("EXPR-CONV:in ", CI, Src);
- CI->setOperand(0, ConvertExpressionToType(Src, DestTy));
- BI = BB->begin(); // Rescan basic block. BI might be invalidated.
- PRINT_PEEPHOLE2("EXPR-CONV:out", CI, CI->getOperand(0));
- return true;
+ if (!isReinterpretingCast(CI)) {
+ if (RetValConvertableToType(CI, Src->getType())) {
+ PRINT_PEEPHOLE2("EXPR-CONV:in ", CI, Src);
+
+ ConvertUsersType(CI, Src);
+ if (!Src->hasName() && CI->hasName()) {
+ string Name = CI->getName(); CI->setName("");
+ Src->setName(Name, BB->getParent()->getSymbolTable());
+ }
+ BI = BB->begin(); // Rescan basic block. BI might be invalidated.
+ PRINT_PEEPHOLE1("EXPR-CONV:out", I);
+ return true;
+ }
}
// Check to see if we are casting from a structure pointer to a pointer to