[llvm-commits] SSI patch

Nick Lewycky nicholas at mxc.ca
Sat Jun 27 21:54:06 PDT 2009


Andre Tavares wrote:
> Hello,
> 
> I'm submiting a patch that will be responsible to create SSI 
> representation on demand. This representation conforms with the current 
> SSA, and will not break other optimizations. It only inserts some phi 
> functions on the code. A brief description is below, and the code is 
> attached.
> 
> // This pass converts a list of variables to the Static Single Information
> // form. This is a program representation described by Scott Ananian in his
> // Master Thesis: "The Static Single Information Form (1999)".
> // We are building an on-demand representation, that is, we do not convert
> // every single variable in the target function to SSI form. Rather, we 
> receive
> // a list of target variables that must be converted. We also do not
> // completely convert a target variable to the SSI format. Instead, we only
> // change the variable in the points where new information can be attached
> // to its live range, that is, at branch points.

   // Test if there is a need to transform to SSI
   if (needConstruction.count() > 0) {

Use !needConstruction.empty() .

   void SSI::insertSigmaFunctions(std::vector<Instruction *> & value) {
     for (unsigned i = 0; i < num_values; ++i) {
       if (needConstruction[i]) {

Just put "if (!needConstruction[i]) continue;" to avoid indenting 
everything another level.

   for (; begin != end; ++begin) {
     // Test if the Use of the Value is in a comparator
     CmpInst * CI;
     if ((CI = dyn_cast<CmpInst> (begin)) && isUsedInTerminator(CI)) {

How about:
   for (; begin != end; ++begin) {
     CmpInst *CI = dyn_cast<CmpInst>(begin);
     if (!CI || !isUsedInTerminator(CI)) {
instead?

In insertPhiFunctions:

   std::set<BasicBlock *> * BB_visited = new std::set<BasicBlock *>();
   while (...) { ...
     free(BB_visited);
   }

How about allocating std::set<BasicBlock *> BB_visited on the stack and 
calling BB_visited.clear() each iteration through the loop?

   // Test if has not yet visited this node and if the
   // original definition dominates this node
   if (BB_visited->insert(BB_dominated).second && value_original[i]
       != BB_dominated
       && DT_->dominates(value_original[i], BB_dominated)
       && dominateAny(BB_dominated, value[i])) {

I think the "value_original[i] != BB_dominated &&
DT_->dominates(value_original[i], BB_dominated)" part can be rewritten 
as "DT_->properlyDominates(value_original[i], BB_dominated)".

Also, please fit the operators on the end of the line.

In SSI::rename:
   // For SSI_SIG (b = PHI(a)), b is a new definition to a. So we need to
"new definition *of a"?
   // Then store bin the value_stack as the new definition of a.
Not sure what the means.

   TerminatorInst * TI = BB->getTerminator();
   for (unsigned i = 0; i < TI->getNumSuccessors(); ++i) {
     BasicBlock * BB_succ = TI->getSuccessor(i);

Perhaps you wanted:
   for (succ_iterator SI = succ_begin(BI), SE = succ_end(B); SI != SE; 
++SI) {
? You need to #include "llvm/Support/CFG.h" for that.

   // This loop calls rename on all children from this block. This time 
children
   // refers to a successor block in the dominance tree.

In other words, it calls rename on all immediately dominated blocks?

   if (defined->count() > 0) {

Use "if (defined->any()) {". Count isn't particularly expensive but 
any() is cheaper.


   void SSI::substituteUse(Instruction * I) {
     for (unsigned i = 0; i < I->getNumOperands(); ++i) {
       Value * operand = I->getOperand(i);
       for (unsigned j = 0; j < num_values; ++j) {
         if (operand == value_stack[j].front() && I != 
value_stack[j].back()) {

It's not clear to me what the if-statement is actually doing, and 
whether it's any different from just using "if (i != j) continue;".

   if ((I_phi = dyn_cast<PHINode> (I)) && (vs_phi = dyn_cast<PHINode> (
       value_stack[j].back())) && value_stack[j].back()->getParent()
       == I->getParent()) {

This needs to be line-flowed better. Here's my suggestion:
   if ((I_phi = dyn_cast<PHINode>(I)) &&
       (vs_phi = dyn_cast<PHINode> (value_stack[j].back())) &&
       value_stack[j].back()->getParent() == I->getParent()) {
which keeps each 'phrase' on one line.

   /// Test if the BasicBlock BB dominates any use or definition of value.
   ///
   bool SSI::dominateAny(BasicBlock * BB, Instruction * value) {

This whole method should work by a) checking whether the Instruction 
itself is dominator (if so, so are all non-phi uses, so return true 
fast) else just loop over the users who are PHINodes and test them only.

Break SSI::getPosition up into getPositionPhi and getPositionSigma. All 
callers put a constant value into compare anyways, and there's no way 
that copying an std::map like that can be cheap.

In SSI::isUsedInTerminator, we know that the comparison field of a 
BranchInst or SwitchInst is going to be field 0. Just make sure 
getNumOperands() != 0 then look at field 0. No loop needed.


Overall, looks good! I like your choice of Ananian's algorithm over 
Singer's because it avoids requiring reverse dominfo (yay!). I didn't 
see anything wrong with the algorithm details.

The one thing to remember is that when placing sigma's in the first 
place you use a very simple flow of "is it a CmpInst which flows to a 
TerminatorInst". That's probably good enough for ABCD but not for a 
GCC-like VRP algorithm. You don't need to worry about that though, 
whoever tried to implement a GCC-like VRP gets to worry about it.

Nick



More information about the llvm-commits mailing list