Two Cleanups to generated C code:
authorChris Lattner <sabre@nondot.org>
Thu, 9 May 2002 21:18:38 +0000 (21:18 +0000)
committerChris Lattner <sabre@nondot.org>
Thu, 9 May 2002 21:18:38 +0000 (21:18 +0000)
1. Avoid printing *(&globalvariable), instead print globalvariable alone
   as a special case.
2. Inline subexpressions into expressions as much as legal that preserves
   execution characteristics of expressions.  Now we get nice (but
   over-parenthesized, oh well) things like:

     ltmp_428_7 = spec__putc(((unsigned char )((bsBuff) >> 24)), (bsStream));

   instead of five seperate instructions (bsBuff & bsStream are globals).

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@2587 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/CBackend/CBackend.cpp
lib/Target/CBackend/Writer.cpp

index dd791872e8e97c2a4f7440341e228e0f0d723994..39cdff49adc0e845a75b9c0c0cc2f6bb7886d7ef 100644 (file)
@@ -229,6 +229,7 @@ namespace {
     }
 
     void writeOperand(const Value *Operand);
+    void writeOperandInternal(const Value *Operand);
 
     string getValueName(const Value *V);
 
@@ -241,6 +242,22 @@ namespace {
     
     void printFunction(Function *);
 
+    // isInlinableInst - Attempt to inline instructions into their uses to build
+    // trees as much as possible.  To do this, we have to consistently decide
+    // what is acceptable to inline, so that variable declarations don't get
+    // printed and an extra copy of the expr is not emitted.
+    //
+    static bool isInlinableInst(Instruction *I) {
+      // Must be an expression, must be used exactly once.  If it is dead, we
+      // emit it inline where it would go.
+      if (I->getType() == Type::VoidTy || I->use_size() != 1 ||
+          isa<TerminatorInst>(I) || isa<CallInst>(I) || isa<PHINode>(I))
+        return false;
+
+      // Only inline instruction it it's use is in the same BB as the inst.
+      return I->getParent() == cast<Instruction>(I->use_back())->getParent();
+    }
+
     // Instruction visitation functions
     friend class InstVisitor<CWriter>;
 
@@ -306,10 +323,7 @@ string CWriter::getValueName(const Value *V) {
   return "ltmp_" + itostr(Slot) + "_" + utostr(V->getType()->getUniqueID());
 }
 
-void CWriter::writeOperand(const Value *Operand) {
-  if (isa<GlobalVariable>(Operand))
-    Out << "(&";  // Global variables are references as their addresses by llvm
-
+void CWriter::writeOperandInternal(const Value *Operand) {
   if (Operand->hasName()) {   
     Out << getValueName(Operand);
   } else if (const Constant *CPV = dyn_cast<const Constant>(Operand)) {
@@ -324,6 +338,22 @@ void CWriter::writeOperand(const Value *Operand) {
     assert(Slot >= 0 && "Malformed LLVM!");
     Out << "ltmp_" << Slot << "_" << Operand->getType()->getUniqueID();
   }
+}
+
+void CWriter::writeOperand(const Value *Operand) {
+  if (Instruction *I = dyn_cast<Instruction>(Operand))
+    if (isInlinableInst(I)) {
+      // Should we inline this instruction to build a tree?
+      Out << "(";
+      visit(I);
+      Out << ")";    
+      return;
+    }
+
+  if (isa<GlobalVariable>(Operand))
+    Out << "(&";  // Global variables are references as their addresses by llvm
+
+  writeOperandInternal(Operand);
 
   if (isa<GlobalVariable>(Operand))
     Out << ")";
@@ -469,7 +499,7 @@ void CWriter::printFunction(Function *F) {
 
   // print local variable information for the function
   for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I)
-    if ((*I)->getType() != Type::VoidTy) {
+    if ((*I)->getType() != Type::VoidTy && !isInlinableInst(*I)) {
       Out << "  ";
       printTypeVar((*I)->getType(), getValueName(*I));
       Out << ";\n";
@@ -496,8 +526,21 @@ void CWriter::printFunction(Function *F) {
     if (NeedsLabel) Out << getValueName(BB) << ":\n";
 
     // Output all of the instructions in the basic block...
-    // print the basic blocks
-    visit(BB);
+    for (BasicBlock::iterator II = BB->begin(), E = BB->end()-1;
+         II != E; ++II) {
+      if (!isInlinableInst(*II) && !isa<PHINode>(*II)) {
+        Instruction *I = *II;
+        if (I->getType() != Type::VoidTy)
+          outputLValue(I);
+        else
+          Out << "  ";
+        visit(I);
+        Out << ";\n";
+      }
+    }
+
+    // Don't emit prefix or suffix for the terminator...
+    visit(BB->getTerminator());
   }
   
   Out << "}\n\n";
@@ -591,15 +634,12 @@ void CWriter::visitBranchInst(BranchInst *I) {
 
 
 void CWriter::visitNot(GenericUnaryInst *I) {
-  outputLValue(I);
   Out << "~";
   writeOperand(I->getOperand(0));
-  Out << ";\n";
 }
 
 void CWriter::visitBinaryOperator(Instruction *I) {
   // binary instructions, shift instructions, setCond instructions.
-  outputLValue(I);
   if (isa<PointerType>(I->getType())) {
     Out << "(";
     printType(I->getType());
@@ -631,24 +671,16 @@ void CWriter::visitBinaryOperator(Instruction *I) {
 
   if (isa<PointerType>(I->getType())) Out << "(long long)";
   writeOperand(I->getOperand(1));
-  Out << ";\n";
 }
 
 void CWriter::visitCastInst(CastInst *I) {
-  outputLValue(I);
   Out << "(";
   printType(I->getType());
   Out << ")";
   writeOperand(I->getOperand(0));
-  Out << ";\n";
 }
 
 void CWriter::visitCallInst(CallInst *I) {
-  if (I->getType() != Type::VoidTy)
-    outputLValue(I);
-  else
-    Out << "  ";
-
   const PointerType  *PTy   = cast<PointerType>(I->getCalledValue()->getType());
   const FunctionType *FTy   = cast<FunctionType>(PTy->getElementType());
   const Type         *RetTy = FTy->getReturnType();
@@ -663,11 +695,10 @@ void CWriter::visitCallInst(CallInst *I) {
       writeOperand(I->getOperand(op));
     }
   }
-  Out << ");\n";
+  Out << ")";
 }  
 
 void CWriter::visitMallocInst(MallocInst *I) {
-  outputLValue(I);
   Out << "(";
   printType(I->getType());
   Out << ")malloc(sizeof(";
@@ -678,11 +709,10 @@ void CWriter::visitMallocInst(MallocInst *I) {
     Out << " * " ;
     writeOperand(I->getOperand(0));
   }
-  Out << ");\n";
+  Out << ")";
 }
 
 void CWriter::visitAllocaInst(AllocaInst *I) {
-  outputLValue(I);
   Out << "(";
   printType(I->getType());
   Out << ") alloca(sizeof(";
@@ -692,19 +722,26 @@ void CWriter::visitAllocaInst(AllocaInst *I) {
     Out << " * " ;
     writeOperand(I->getOperand(0));
   }
-  Out << ");\n";
+  Out << ")";
 }
 
 void CWriter::visitFreeInst(FreeInst *I) {
-  Out << "  free(";
+  Out << "free(";
   writeOperand(I->getOperand(0));
-  Out << ");\n";
+  Out << ")";
 }
 
 void CWriter::printIndexingExpr(MemAccessInst *MAI) {
   MemAccessInst::op_iterator I = MAI->idx_begin(), E = MAI->idx_end();
-  if (I == E)
+  if (I == E) {
+    // If accessing a global value with no indexing, avoid *(&GV) syndrome
+    if (GlobalValue *V = dyn_cast<GlobalValue>(MAI->getPointerOperand())) {
+      writeOperandInternal(V);
+      return;
+    }
+
     Out << "*";  // Implicit zero first argument: '*x' is equivalent to 'x[0]'
+  }
 
   writeOperand(MAI->getPointerOperand());
 
@@ -714,9 +751,8 @@ void CWriter::printIndexingExpr(MemAccessInst *MAI) {
   Constant *CI = dyn_cast<Constant>(*I);
   if (CI && CI->isNullValue() && I+1 != E &&
       (*(I+1))->getType() == Type::UByteTy) {
-    ++I;
-    Out << "->field" << cast<ConstantUInt>(*I)->getValue();
-    ++I;
+    Out << "->field" << cast<ConstantUInt>(*(I+1))->getValue();
+    I += 2;
   }
     
   for (; I != E; ++I)
@@ -730,24 +766,18 @@ void CWriter::printIndexingExpr(MemAccessInst *MAI) {
 }
 
 void CWriter::visitLoadInst(LoadInst *I) {
-  outputLValue(I);
   printIndexingExpr(I);
-  Out << ";\n";
 }
 
 void CWriter::visitStoreInst(StoreInst *I) {
-  Out << "  ";
   printIndexingExpr(I);
   Out << " = ";
   writeOperand(I->getOperand(0));
-  Out << ";\n";
 }
 
 void CWriter::visitGetElementPtrInst(GetElementPtrInst *I) {
-  outputLValue(I);
   Out << "&";
   printIndexingExpr(I);
-  Out << ";\n";
 }
 
 //===----------------------------------------------------------------------===//
index dd791872e8e97c2a4f7440341e228e0f0d723994..39cdff49adc0e845a75b9c0c0cc2f6bb7886d7ef 100644 (file)
@@ -229,6 +229,7 @@ namespace {
     }
 
     void writeOperand(const Value *Operand);
+    void writeOperandInternal(const Value *Operand);
 
     string getValueName(const Value *V);
 
@@ -241,6 +242,22 @@ namespace {
     
     void printFunction(Function *);
 
+    // isInlinableInst - Attempt to inline instructions into their uses to build
+    // trees as much as possible.  To do this, we have to consistently decide
+    // what is acceptable to inline, so that variable declarations don't get
+    // printed and an extra copy of the expr is not emitted.
+    //
+    static bool isInlinableInst(Instruction *I) {
+      // Must be an expression, must be used exactly once.  If it is dead, we
+      // emit it inline where it would go.
+      if (I->getType() == Type::VoidTy || I->use_size() != 1 ||
+          isa<TerminatorInst>(I) || isa<CallInst>(I) || isa<PHINode>(I))
+        return false;
+
+      // Only inline instruction it it's use is in the same BB as the inst.
+      return I->getParent() == cast<Instruction>(I->use_back())->getParent();
+    }
+
     // Instruction visitation functions
     friend class InstVisitor<CWriter>;
 
@@ -306,10 +323,7 @@ string CWriter::getValueName(const Value *V) {
   return "ltmp_" + itostr(Slot) + "_" + utostr(V->getType()->getUniqueID());
 }
 
-void CWriter::writeOperand(const Value *Operand) {
-  if (isa<GlobalVariable>(Operand))
-    Out << "(&";  // Global variables are references as their addresses by llvm
-
+void CWriter::writeOperandInternal(const Value *Operand) {
   if (Operand->hasName()) {   
     Out << getValueName(Operand);
   } else if (const Constant *CPV = dyn_cast<const Constant>(Operand)) {
@@ -324,6 +338,22 @@ void CWriter::writeOperand(const Value *Operand) {
     assert(Slot >= 0 && "Malformed LLVM!");
     Out << "ltmp_" << Slot << "_" << Operand->getType()->getUniqueID();
   }
+}
+
+void CWriter::writeOperand(const Value *Operand) {
+  if (Instruction *I = dyn_cast<Instruction>(Operand))
+    if (isInlinableInst(I)) {
+      // Should we inline this instruction to build a tree?
+      Out << "(";
+      visit(I);
+      Out << ")";    
+      return;
+    }
+
+  if (isa<GlobalVariable>(Operand))
+    Out << "(&";  // Global variables are references as their addresses by llvm
+
+  writeOperandInternal(Operand);
 
   if (isa<GlobalVariable>(Operand))
     Out << ")";
@@ -469,7 +499,7 @@ void CWriter::printFunction(Function *F) {
 
   // print local variable information for the function
   for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I)
-    if ((*I)->getType() != Type::VoidTy) {
+    if ((*I)->getType() != Type::VoidTy && !isInlinableInst(*I)) {
       Out << "  ";
       printTypeVar((*I)->getType(), getValueName(*I));
       Out << ";\n";
@@ -496,8 +526,21 @@ void CWriter::printFunction(Function *F) {
     if (NeedsLabel) Out << getValueName(BB) << ":\n";
 
     // Output all of the instructions in the basic block...
-    // print the basic blocks
-    visit(BB);
+    for (BasicBlock::iterator II = BB->begin(), E = BB->end()-1;
+         II != E; ++II) {
+      if (!isInlinableInst(*II) && !isa<PHINode>(*II)) {
+        Instruction *I = *II;
+        if (I->getType() != Type::VoidTy)
+          outputLValue(I);
+        else
+          Out << "  ";
+        visit(I);
+        Out << ";\n";
+      }
+    }
+
+    // Don't emit prefix or suffix for the terminator...
+    visit(BB->getTerminator());
   }
   
   Out << "}\n\n";
@@ -591,15 +634,12 @@ void CWriter::visitBranchInst(BranchInst *I) {
 
 
 void CWriter::visitNot(GenericUnaryInst *I) {
-  outputLValue(I);
   Out << "~";
   writeOperand(I->getOperand(0));
-  Out << ";\n";
 }
 
 void CWriter::visitBinaryOperator(Instruction *I) {
   // binary instructions, shift instructions, setCond instructions.
-  outputLValue(I);
   if (isa<PointerType>(I->getType())) {
     Out << "(";
     printType(I->getType());
@@ -631,24 +671,16 @@ void CWriter::visitBinaryOperator(Instruction *I) {
 
   if (isa<PointerType>(I->getType())) Out << "(long long)";
   writeOperand(I->getOperand(1));
-  Out << ";\n";
 }
 
 void CWriter::visitCastInst(CastInst *I) {
-  outputLValue(I);
   Out << "(";
   printType(I->getType());
   Out << ")";
   writeOperand(I->getOperand(0));
-  Out << ";\n";
 }
 
 void CWriter::visitCallInst(CallInst *I) {
-  if (I->getType() != Type::VoidTy)
-    outputLValue(I);
-  else
-    Out << "  ";
-
   const PointerType  *PTy   = cast<PointerType>(I->getCalledValue()->getType());
   const FunctionType *FTy   = cast<FunctionType>(PTy->getElementType());
   const Type         *RetTy = FTy->getReturnType();
@@ -663,11 +695,10 @@ void CWriter::visitCallInst(CallInst *I) {
       writeOperand(I->getOperand(op));
     }
   }
-  Out << ");\n";
+  Out << ")";
 }  
 
 void CWriter::visitMallocInst(MallocInst *I) {
-  outputLValue(I);
   Out << "(";
   printType(I->getType());
   Out << ")malloc(sizeof(";
@@ -678,11 +709,10 @@ void CWriter::visitMallocInst(MallocInst *I) {
     Out << " * " ;
     writeOperand(I->getOperand(0));
   }
-  Out << ");\n";
+  Out << ")";
 }
 
 void CWriter::visitAllocaInst(AllocaInst *I) {
-  outputLValue(I);
   Out << "(";
   printType(I->getType());
   Out << ") alloca(sizeof(";
@@ -692,19 +722,26 @@ void CWriter::visitAllocaInst(AllocaInst *I) {
     Out << " * " ;
     writeOperand(I->getOperand(0));
   }
-  Out << ");\n";
+  Out << ")";
 }
 
 void CWriter::visitFreeInst(FreeInst *I) {
-  Out << "  free(";
+  Out << "free(";
   writeOperand(I->getOperand(0));
-  Out << ");\n";
+  Out << ")";
 }
 
 void CWriter::printIndexingExpr(MemAccessInst *MAI) {
   MemAccessInst::op_iterator I = MAI->idx_begin(), E = MAI->idx_end();
-  if (I == E)
+  if (I == E) {
+    // If accessing a global value with no indexing, avoid *(&GV) syndrome
+    if (GlobalValue *V = dyn_cast<GlobalValue>(MAI->getPointerOperand())) {
+      writeOperandInternal(V);
+      return;
+    }
+
     Out << "*";  // Implicit zero first argument: '*x' is equivalent to 'x[0]'
+  }
 
   writeOperand(MAI->getPointerOperand());
 
@@ -714,9 +751,8 @@ void CWriter::printIndexingExpr(MemAccessInst *MAI) {
   Constant *CI = dyn_cast<Constant>(*I);
   if (CI && CI->isNullValue() && I+1 != E &&
       (*(I+1))->getType() == Type::UByteTy) {
-    ++I;
-    Out << "->field" << cast<ConstantUInt>(*I)->getValue();
-    ++I;
+    Out << "->field" << cast<ConstantUInt>(*(I+1))->getValue();
+    I += 2;
   }
     
   for (; I != E; ++I)
@@ -730,24 +766,18 @@ void CWriter::printIndexingExpr(MemAccessInst *MAI) {
 }
 
 void CWriter::visitLoadInst(LoadInst *I) {
-  outputLValue(I);
   printIndexingExpr(I);
-  Out << ";\n";
 }
 
 void CWriter::visitStoreInst(StoreInst *I) {
-  Out << "  ";
   printIndexingExpr(I);
   Out << " = ";
   writeOperand(I->getOperand(0));
-  Out << ";\n";
 }
 
 void CWriter::visitGetElementPtrInst(GetElementPtrInst *I) {
-  outputLValue(I);
   Out << "&";
   printIndexingExpr(I);
-  Out << ";\n";
 }
 
 //===----------------------------------------------------------------------===//