From a8ab89e3da4fcd85f330ee3f85ac656cbb6cf048 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Tue, 17 Jun 2003 04:39:14 +0000 Subject: [PATCH] Fairly major change: emit fixed sized allocas in the entry block as a variable, instead of a variable pointer and an alloca. All accesses to the variable then use the address-of operator to access it. This plays better with the internal GCC code generation phases, which bail early on functions which contain allocas. It also makes the code a bit easier to read. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@6734 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/CBackend/CBackend.cpp | 32 ++++++++++++++++++++++++++------ lib/Target/CBackend/Writer.cpp | 32 ++++++++++++++++++++++++++------ 2 files changed, 52 insertions(+), 12 deletions(-) diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp index 3dfd8f9cd00..1d2a85abe11 100644 --- a/lib/Target/CBackend/CBackend.cpp +++ b/lib/Target/CBackend/CBackend.cpp @@ -97,6 +97,20 @@ namespace { return I.getParent() == cast(I.use_back())->getParent(); } + // isDirectAlloca - Define fixed sized allocas in the entry block as direct + // variables which are accessed with the & operator. This causes GCC to + // generate significantly better code than to emit alloca calls directly. + // + static const AllocaInst *isDirectAlloca(const Value *V) { + const AllocaInst *AI = dyn_cast(V); + if (!AI) return false; + if (AI->isArrayAllocation()) + return 0; // FIXME: we can also inline fixed size array allocas! + if (AI->getParent() != &AI->getParent()->getParent()->getEntryNode()) + return 0; + return AI; + } + // Instruction visitation functions friend class InstVisitor; @@ -463,7 +477,7 @@ void CWriter::printConstant(Constant *CPV) { void CWriter::writeOperandInternal(Value *Operand) { if (Instruction *I = dyn_cast(Operand)) - if (isInlinableInst(*I)) { + if (isInlinableInst(*I) && !isDirectAlloca(I)) { // Should we inline this instruction to build a tree? Out << "("; visit(*I); @@ -483,12 +497,12 @@ void CWriter::writeOperandInternal(Value *Operand) { } void CWriter::writeOperand(Value *Operand) { - if (isa(Operand)) + if (isa(Operand) || isDirectAlloca(Operand)) Out << "(&"; // Global variables are references as their addresses by llvm writeOperandInternal(Operand); - if (isa(Operand)) + if (isa(Operand) || isDirectAlloca(Operand)) Out << ")"; } @@ -792,11 +806,15 @@ 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 && !isInlinableInst(**I)) { + if (const AllocaInst *AI = isDirectAlloca(*I)) { + Out << " "; + printType(Out, AI->getAllocatedType(), getValueName(AI)); + Out << "; /* Address exposed local */\n"; + } else if ((*I)->getType() != Type::VoidTy && !isInlinableInst(**I)) { Out << " "; printType(Out, (*I)->getType(), getValueName(*I)); Out << ";\n"; - + if (isa(*I)) { // Print out PHI node temporaries as well... Out << " "; printType(Out, (*I)->getType(), getValueName(*I)+"__PHI_TEMPORARY"); @@ -856,7 +874,7 @@ void CWriter::printFunction(Function *F) { // Output all of the instructions in the basic block... for (BasicBlock::iterator II = BB->begin(), E = --BB->end(); II != E; ++II){ - if (!isInlinableInst(*II)) { + if (!isInlinableInst(*II) && !isDirectAlloca(II)) { if (II->getType() != Type::VoidTy) outputLValue(II); else @@ -1132,6 +1150,8 @@ void CWriter::printIndexingExpression(Value *Ptr, User::op_iterator I, } else if (ConstantPointerRef *CPR = dyn_cast(Ptr)) { HasImplicitAddress = true; Ptr = CPR->getValue(); // Get to the global... + } else if (isDirectAlloca(Ptr)) { + HasImplicitAddress = true; } if (I == E) { diff --git a/lib/Target/CBackend/Writer.cpp b/lib/Target/CBackend/Writer.cpp index 3dfd8f9cd00..1d2a85abe11 100644 --- a/lib/Target/CBackend/Writer.cpp +++ b/lib/Target/CBackend/Writer.cpp @@ -97,6 +97,20 @@ namespace { return I.getParent() == cast(I.use_back())->getParent(); } + // isDirectAlloca - Define fixed sized allocas in the entry block as direct + // variables which are accessed with the & operator. This causes GCC to + // generate significantly better code than to emit alloca calls directly. + // + static const AllocaInst *isDirectAlloca(const Value *V) { + const AllocaInst *AI = dyn_cast(V); + if (!AI) return false; + if (AI->isArrayAllocation()) + return 0; // FIXME: we can also inline fixed size array allocas! + if (AI->getParent() != &AI->getParent()->getParent()->getEntryNode()) + return 0; + return AI; + } + // Instruction visitation functions friend class InstVisitor; @@ -463,7 +477,7 @@ void CWriter::printConstant(Constant *CPV) { void CWriter::writeOperandInternal(Value *Operand) { if (Instruction *I = dyn_cast(Operand)) - if (isInlinableInst(*I)) { + if (isInlinableInst(*I) && !isDirectAlloca(I)) { // Should we inline this instruction to build a tree? Out << "("; visit(*I); @@ -483,12 +497,12 @@ void CWriter::writeOperandInternal(Value *Operand) { } void CWriter::writeOperand(Value *Operand) { - if (isa(Operand)) + if (isa(Operand) || isDirectAlloca(Operand)) Out << "(&"; // Global variables are references as their addresses by llvm writeOperandInternal(Operand); - if (isa(Operand)) + if (isa(Operand) || isDirectAlloca(Operand)) Out << ")"; } @@ -792,11 +806,15 @@ 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 && !isInlinableInst(**I)) { + if (const AllocaInst *AI = isDirectAlloca(*I)) { + Out << " "; + printType(Out, AI->getAllocatedType(), getValueName(AI)); + Out << "; /* Address exposed local */\n"; + } else if ((*I)->getType() != Type::VoidTy && !isInlinableInst(**I)) { Out << " "; printType(Out, (*I)->getType(), getValueName(*I)); Out << ";\n"; - + if (isa(*I)) { // Print out PHI node temporaries as well... Out << " "; printType(Out, (*I)->getType(), getValueName(*I)+"__PHI_TEMPORARY"); @@ -856,7 +874,7 @@ void CWriter::printFunction(Function *F) { // Output all of the instructions in the basic block... for (BasicBlock::iterator II = BB->begin(), E = --BB->end(); II != E; ++II){ - if (!isInlinableInst(*II)) { + if (!isInlinableInst(*II) && !isDirectAlloca(II)) { if (II->getType() != Type::VoidTy) outputLValue(II); else @@ -1132,6 +1150,8 @@ void CWriter::printIndexingExpression(Value *Ptr, User::op_iterator I, } else if (ConstantPointerRef *CPR = dyn_cast(Ptr)) { HasImplicitAddress = true; Ptr = CPR->getValue(); // Get to the global... + } else if (isDirectAlloca(Ptr)) { + HasImplicitAddress = true; } if (I == E) {