PhiCleaner.cpp

Go to the documentation of this file.
00001 //===-- PhiCleaner.cpp ----------------------------------------------------===//
00002 //
00003 //                     The KLEE Symbolic Virtual Machine
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 
00010 #include "Passes.h"
00011 
00012 #include <set>
00013 
00014 using namespace llvm;
00015 
00016 char klee::PhiCleanerPass::ID = 0;
00017 
00018 bool klee::PhiCleanerPass::runOnFunction(Function &f) {
00019   bool changed = false;
00020   
00021   for (Function::iterator b = f.begin(), be = f.end(); b != be; ++b) {
00022     BasicBlock::iterator it = b->begin();
00023 
00024     if (it->getOpcode() == Instruction::PHI) {
00025       PHINode *reference = cast<PHINode>(it);
00026       
00027       std::set<Value*> phis;
00028       phis.insert(reference);
00029 
00030       unsigned numBlocks = reference->getNumIncomingValues();
00031       for (++it; isa<PHINode>(*it); ++it) {
00032         PHINode *pi = cast<PHINode>(it);
00033 
00034         assert(numBlocks == pi->getNumIncomingValues());
00035 
00036         // see if it is out of order
00037         unsigned i;
00038         for (i=0; i<numBlocks; i++)
00039           if (pi->getIncomingBlock(i) != reference->getIncomingBlock(i))
00040             break;
00041 
00042         if (i!=numBlocks) {
00043           std::vector<Value*> values;
00044           values.reserve(numBlocks);
00045           for (unsigned i=0; i<numBlocks; i++)
00046             values[i] = pi->getIncomingValueForBlock(reference->getIncomingBlock(i));
00047           for (unsigned i=0; i<numBlocks; i++) {
00048             pi->setIncomingBlock(i, reference->getIncomingBlock(i));
00049             pi->setIncomingValue(i, values[i]);
00050           }
00051           changed = true;
00052         }
00053 
00054         // see if it uses any previously defined phi nodes
00055         for (i=0; i<numBlocks; i++) {
00056           Value *value = pi->getIncomingValue(i);
00057 
00058           if (phis.find(value) != phis.end()) {
00059             // fix by making a "move" at the end of the incoming block
00060             // to a new temporary, which is thus known not to be a phi
00061             // result. we could be somewhat more efficient about this
00062             // by sharing temps and by reordering phi instructions so
00063             // this isn't completely necessary, but in the end this is
00064             // just a pathological case which does not occur very
00065             // often.
00066             Instruction *tmp = 
00067               new BitCastInst(value, 
00068                               value->getType(),
00069                               value->getName() + ".phiclean",
00070                               pi->getIncomingBlock(i)->getTerminator());
00071             pi->setIncomingValue(i, tmp);
00072           }
00073 
00074           changed = true;
00075         }
00076         
00077         phis.insert(pi);
00078       }
00079     }
00080   }
00081 
00082   return changed;
00083 }

Generated on Fri Jun 5 03:31:32 2009 for klee by  doxygen 1.5.8