summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2003-06-17 04:39:14 +0000
committerChris Lattner <sabre@nondot.org>2003-06-17 04:39:14 +0000
commita8ab89e3da4fcd85f330ee3f85ac656cbb6cf048 (patch)
tree6658365b85501d22b4059f03d850c011d436709a /lib
parentbea68b3021ee9fea9ca28f8d14e742b025f95c2b (diff)
downloadllvm-a8ab89e3da4fcd85f330ee3f85ac656cbb6cf048.tar.gz
llvm-a8ab89e3da4fcd85f330ee3f85ac656cbb6cf048.tar.bz2
llvm-a8ab89e3da4fcd85f330ee3f85ac656cbb6cf048.tar.xz
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
Diffstat (limited to 'lib')
-rw-r--r--lib/Target/CBackend/CBackend.cpp32
-rw-r--r--lib/Target/CBackend/Writer.cpp32
2 files changed, 52 insertions, 12 deletions
diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp
index 3dfd8f9cd0..1d2a85abe1 100644
--- a/lib/Target/CBackend/CBackend.cpp
+++ b/lib/Target/CBackend/CBackend.cpp
@@ -97,6 +97,20 @@ namespace {
return I.getParent() == cast<Instruction>(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<AllocaInst>(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<CWriter>;
@@ -463,7 +477,7 @@ void CWriter::printConstant(Constant *CPV) {
void CWriter::writeOperandInternal(Value *Operand) {
if (Instruction *I = dyn_cast<Instruction>(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<GlobalVariable>(Operand))
+ if (isa<GlobalVariable>(Operand) || isDirectAlloca(Operand))
Out << "(&"; // Global variables are references as their addresses by llvm
writeOperandInternal(Operand);
- if (isa<GlobalVariable>(Operand))
+ if (isa<GlobalVariable>(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<PHINode>(*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<ConstantPointerRef>(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 3dfd8f9cd0..1d2a85abe1 100644
--- a/lib/Target/CBackend/Writer.cpp
+++ b/lib/Target/CBackend/Writer.cpp
@@ -97,6 +97,20 @@ namespace {
return I.getParent() == cast<Instruction>(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<AllocaInst>(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<CWriter>;
@@ -463,7 +477,7 @@ void CWriter::printConstant(Constant *CPV) {
void CWriter::writeOperandInternal(Value *Operand) {
if (Instruction *I = dyn_cast<Instruction>(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<GlobalVariable>(Operand))
+ if (isa<GlobalVariable>(Operand) || isDirectAlloca(Operand))
Out << "(&"; // Global variables are references as their addresses by llvm
writeOperandInternal(Operand);
- if (isa<GlobalVariable>(Operand))
+ if (isa<GlobalVariable>(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<PHINode>(*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<ConstantPointerRef>(Ptr)) {
HasImplicitAddress = true;
Ptr = CPR->getValue(); // Get to the global...
+ } else if (isDirectAlloca(Ptr)) {
+ HasImplicitAddress = true;
}
if (I == E) {