forked from OSchip/llvm-project
Avoid generation of dead code in a few more situations.
- Emit variable declarations as "simple", we want to avoid forcing the creation of a dummy basic block, but still need to make the variable available for later use. - With that, we can now skip IRgen for other unreachable statements (which don't define a label). - Anders, I added two fixmes on calls to EmitVLASize, can you check them? llvm-svn: 76361
This commit is contained in:
parent
567daf3ce8
commit
b6adc43f6e
|
@ -112,7 +112,6 @@ CodeGenFunction::CreateStaticBlockVarDecl(const VarDecl &D,
|
|||
}
|
||||
|
||||
void CodeGenFunction::EmitStaticBlockVarDecl(const VarDecl &D) {
|
||||
|
||||
llvm::Value *&DMEntry = LocalDeclMap[&D];
|
||||
assert(DMEntry == 0 && "Decl already exists in localdeclmap!");
|
||||
|
||||
|
@ -124,6 +123,8 @@ void CodeGenFunction::EmitStaticBlockVarDecl(const VarDecl &D) {
|
|||
DMEntry = GV;
|
||||
|
||||
// Make sure to evaluate VLA bounds now so that we have them for later.
|
||||
//
|
||||
// FIXME: Can this happen?
|
||||
if (D.getType()->isVariablyModifiedType())
|
||||
EmitVLASize(D.getType());
|
||||
|
||||
|
@ -274,9 +275,12 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
|
|||
::InternalLinkage);
|
||||
}
|
||||
|
||||
// FIXME: Can this happen?
|
||||
if (Ty->isVariablyModifiedType())
|
||||
EmitVLASize(Ty);
|
||||
} else {
|
||||
EnsureInsertPoint();
|
||||
|
||||
if (!DidCallStackSave) {
|
||||
// Save the stack.
|
||||
const llvm::Type *LTy =
|
||||
|
@ -321,6 +325,11 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
|
|||
|
||||
// Emit debug info for local var declaration.
|
||||
if (CGDebugInfo *DI = getDebugInfo()) {
|
||||
// FIXME: Remove this once debug info isn't modeled as instructions.
|
||||
EnsureInsertPoint();
|
||||
|
||||
EmitStopPoint(S);
|
||||
|
||||
DI->setLocation(D.getLocation());
|
||||
if (Target.useGlobalsForAutomaticVariables()) {
|
||||
DI->EmitGlobalVariable(static_cast<llvm::GlobalVariable *>(DeclPtr), &D);
|
||||
|
@ -338,7 +347,18 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
|
|||
}
|
||||
|
||||
// If this local has an initializer, emit it now.
|
||||
if (const Expr *Init = D.getInit()) {
|
||||
const Expr *Init = D.getInit();
|
||||
|
||||
// If we are at an unreachable point, we don't need to emit the initializer
|
||||
// unless it contains a label.
|
||||
if (!HaveInsertPoint()) {
|
||||
if (!ContainsLabel(Init))
|
||||
Init = 0;
|
||||
else
|
||||
EnsureInsertPoint();
|
||||
}
|
||||
|
||||
if (Init) {
|
||||
llvm::Value *Loc = DeclPtr;
|
||||
if (isByRef) {
|
||||
bool needsCopyDispose = BlockRequiresCopying(Ty);
|
||||
|
@ -357,10 +377,12 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
|
|||
EmitAggExpr(Init, Loc, D.getType().isVolatileQualified());
|
||||
}
|
||||
}
|
||||
|
||||
if (isByRef) {
|
||||
const llvm::PointerType *PtrToInt8Ty
|
||||
= VMContext.getPointerTypeUnqual(llvm::Type::Int8Ty);
|
||||
|
||||
EnsureInsertPoint();
|
||||
llvm::Value *isa_field = Builder.CreateStructGEP(DeclPtr, 0);
|
||||
llvm::Value *forwarding_field = Builder.CreateStructGEP(DeclPtr, 1);
|
||||
llvm::Value *flags_field = Builder.CreateStructGEP(DeclPtr, 2);
|
||||
|
|
|
@ -43,13 +43,24 @@ void CodeGenFunction::EmitStmt(const Stmt *S) {
|
|||
if (EmitSimpleStmt(S))
|
||||
return;
|
||||
|
||||
// If we happen to be at an unreachable point just create a dummy
|
||||
// basic block to hold the code. We could change parts of irgen to
|
||||
// simply not generate this code, but this situation is rare and
|
||||
// probably not worth the effort.
|
||||
// FIXME: Verify previous performance/effort claim.
|
||||
EnsureInsertPoint();
|
||||
|
||||
// Check if we are generating unreachable code.
|
||||
if (!HaveInsertPoint()) {
|
||||
// If so, and the statement doesn't contain a label, then we do not need to
|
||||
// generate actual code. This is safe because (1) the current point is
|
||||
// unreachable, so we don't need to execute the code, and (2) we've already
|
||||
// handled the statements which update internal data structures (like the
|
||||
// local variable map) which could be used by subsequent statements.
|
||||
if (!ContainsLabel(S)) {
|
||||
// Verify that any decl statements were handled as simple, they may be in
|
||||
// scope of subsequent reachable statements.
|
||||
assert(!isa<DeclStmt>(*S) && "Unexpected DeclStmt!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, make a new block to hold the code.
|
||||
EnsureInsertPoint();
|
||||
}
|
||||
|
||||
// Generate a stoppoint if we are emitting debug info.
|
||||
EmitStopPoint(S);
|
||||
|
||||
|
@ -72,7 +83,6 @@ void CodeGenFunction::EmitStmt(const Stmt *S) {
|
|||
case Stmt::ForStmtClass: EmitForStmt(cast<ForStmt>(*S)); break;
|
||||
|
||||
case Stmt::ReturnStmtClass: EmitReturnStmt(cast<ReturnStmt>(*S)); break;
|
||||
case Stmt::DeclStmtClass: EmitDeclStmt(cast<DeclStmt>(*S)); break;
|
||||
|
||||
case Stmt::SwitchStmtClass: EmitSwitchStmt(cast<SwitchStmt>(*S)); break;
|
||||
case Stmt::AsmStmtClass: EmitAsmStmt(cast<AsmStmt>(*S)); break;
|
||||
|
@ -103,6 +113,7 @@ bool CodeGenFunction::EmitSimpleStmt(const Stmt *S) {
|
|||
default: return false;
|
||||
case Stmt::NullStmtClass: break;
|
||||
case Stmt::CompoundStmtClass: EmitCompoundStmt(cast<CompoundStmt>(*S)); break;
|
||||
case Stmt::DeclStmtClass: EmitDeclStmt(cast<DeclStmt>(*S)); break;
|
||||
case Stmt::LabelStmtClass: EmitLabelStmt(cast<LabelStmt>(*S)); break;
|
||||
case Stmt::GotoStmtClass: EmitGotoStmt(cast<GotoStmt>(*S)); break;
|
||||
case Stmt::BreakStmtClass: EmitBreakStmt(cast<BreakStmt>(*S)); break;
|
||||
|
|
|
@ -450,19 +450,19 @@ void CodeGenFunction::EmitIndirectSwitches() {
|
|||
}
|
||||
}
|
||||
|
||||
llvm::Value *CodeGenFunction::GetVLASize(const VariableArrayType *VAT)
|
||||
{
|
||||
llvm::Value *CodeGenFunction::GetVLASize(const VariableArrayType *VAT) {
|
||||
llvm::Value *&SizeEntry = VLASizeMap[VAT];
|
||||
|
||||
assert(SizeEntry && "Did not emit size for type");
|
||||
return SizeEntry;
|
||||
}
|
||||
|
||||
llvm::Value *CodeGenFunction::EmitVLASize(QualType Ty)
|
||||
{
|
||||
llvm::Value *CodeGenFunction::EmitVLASize(QualType Ty) {
|
||||
assert(Ty->isVariablyModifiedType() &&
|
||||
"Must pass variably modified type to EmitVLASizes!");
|
||||
|
||||
EnsureInsertPoint();
|
||||
|
||||
if (const VariableArrayType *VAT = getContext().getAsVariableArrayType(Ty)) {
|
||||
llvm::Value *&SizeEntry = VLASizeMap[VAT];
|
||||
|
||||
|
|
|
@ -147,7 +147,11 @@ public:
|
|||
|
||||
~CleanupScope() {
|
||||
CGF.PushCleanupBlock(CleanupBB);
|
||||
CGF.Builder.SetInsertPoint(CurBB);
|
||||
// FIXME: This is silly, move this into the builder.
|
||||
if (CurBB)
|
||||
CGF.Builder.SetInsertPoint(CurBB);
|
||||
else
|
||||
CGF.Builder.ClearInsertionPoint();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -510,6 +514,8 @@ public:
|
|||
// EmitVLASize - Generate code for any VLA size expressions that might occur
|
||||
// in a variably modified type. If Ty is a VLA, will return the value that
|
||||
// corresponds to the size in bytes of the VLA type. Will return 0 otherwise.
|
||||
///
|
||||
/// This function can be called with a null (unreachable) insert point.
|
||||
llvm::Value *EmitVLASize(QualType Ty);
|
||||
|
||||
// GetVLASize - Returns an LLVM value that corresponds to the size in bytes
|
||||
|
@ -537,9 +543,21 @@ public:
|
|||
// Declaration Emission
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
||||
/// EmitDecl - Emit a declaration.
|
||||
///
|
||||
/// This function can be called with a null (unreachable) insert point.
|
||||
void EmitDecl(const Decl &D);
|
||||
|
||||
/// EmitBlockVarDecl - Emit a block variable declaration.
|
||||
///
|
||||
/// This function can be called with a null (unreachable) insert point.
|
||||
void EmitBlockVarDecl(const VarDecl &D);
|
||||
|
||||
/// EmitLocalBlockVarDecl - Emit a local block variable declaration.
|
||||
///
|
||||
/// This function can be called with a null (unreachable) insert point.
|
||||
void EmitLocalBlockVarDecl(const VarDecl &D);
|
||||
|
||||
void EmitStaticBlockVarDecl(const VarDecl &D);
|
||||
|
||||
/// EmitParmDecl - Emit a ParmVarDecl or an ImplicitParamDecl.
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
// RUN: clang-cc -emit-llvm -o %t %s &&
|
||||
// RUN: grep '@unreachable' %t | count 0
|
||||
|
||||
extern int unreachable();
|
||||
|
||||
int f0() {
|
||||
return 0;
|
||||
unreachable();
|
||||
}
|
||||
|
||||
int f1(int i) {
|
||||
goto L0;
|
||||
int a = unreachable();
|
||||
L0:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int f2(int i) {
|
||||
goto L0;
|
||||
unreachable();
|
||||
int a;
|
||||
unreachable();
|
||||
L0:
|
||||
a = i + 1;
|
||||
return a;
|
||||
}
|
Loading…
Reference in New Issue