diff options
author | Chris Lattner <sabre@nondot.org> | 2008-11-11 07:24:28 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2008-11-11 07:24:28 +0000 |
commit | 62b72f642207ba2ba433d686df924dc9594e9897 (patch) | |
tree | 675865a6e3c988e0e2b64f848d5cfc6f47ebaea0 /lib/CodeGen/CGStmt.cpp | |
parent | 3cc5c406c436a90c8dd61f545552b844391ebf5b (diff) |
Make codegen smart enough to not emit the dead side of an if whose
condition is a constant. This shrinks -O0 codegen by quite a bit
on some cases.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59033 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGStmt.cpp')
-rw-r--r-- | lib/CodeGen/CGStmt.cpp | 54 |
1 files changed, 49 insertions, 5 deletions
diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index 82c39208a4..1d9b30eca8 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -217,14 +217,56 @@ void CodeGenFunction::EmitIndirectGotoStmt(const IndirectGotoStmt &S) { EmitDummyBlock(); } -void CodeGenFunction::EmitIfStmt(const IfStmt &S) { - // FIXME: It would probably be nice for us to skip emission of if - // (0) code here. +/// ContainsLabel - Return true if the statement contains a label in it. If +/// this statement is not executed normally, it not containing a label means +/// that we can just remove the code. +static bool ContainsLabel(const Stmt *S, bool IgnoreCaseStmts = false) { + // If this is a label, we have to emit the code, consider something like: + // if (0) { ... foo: bar(); } goto foo; + if (isa<LabelStmt>(S)) + return true; + + // If this is a case/default statement, and we haven't seen a switch, we have + // to emit the code. + if (isa<SwitchCase>(S) && !IgnoreCaseStmts) + return true; + + // If this is a switch statement, we want to ignore cases below it. + if (isa<SwitchStmt>(S)) + IgnoreCaseStmts = true; + + // Scan subexpressions for verboten labels. + for (Stmt::const_child_iterator I = S->child_begin(), E = S->child_end(); + I != E; ++I) + if (ContainsLabel(*I, IgnoreCaseStmts)) + return true; + + return false; +} + +void CodeGenFunction::EmitIfStmt(const IfStmt &S) { // C99 6.8.4.1: The first substatement is executed if the expression compares // unequal to 0. The condition must be a scalar type. llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond()); + // If we constant folded the condition to true or false, try to avoid emitting + // the dead arm at all. + if (llvm::ConstantInt *CondCst = dyn_cast<llvm::ConstantInt>(BoolCondVal)) { + // Figure out which block (then or else) is executed. + const Stmt *Executed = S.getThen(), *Skipped = S.getElse(); + if (!CondCst->getZExtValue()) + std::swap(Executed, Skipped); + + // If the skipped block has no labels in it, just emit the executed block. + // This avoids emitting dead code and simplifies the CFG substantially. + if (Skipped == 0 || !ContainsLabel(Skipped)) { + if (Executed) + EmitStmt(Executed); + return; + } + } + llvm::BasicBlock *ContBlock = createBasicBlock("ifend"); llvm::BasicBlock *ThenBlock = createBasicBlock("ifthen"); llvm::BasicBlock *ElseBlock = ContBlock; @@ -851,7 +893,8 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { if (ConvertType(InputExpr->getType())->isSingleValueType()) { Arg = EmitScalarExpr(InputExpr); } else { - ErrorUnsupported(&S, "asm statement passing multiple-value types as inputs"); + ErrorUnsupported(&S, + "asm statement passing multiple-value types as inputs"); } } else { LValue Dest = EmitLValue(InputExpr); @@ -891,7 +934,8 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { if (ConvertType(InputExpr->getType())->isSingleValueType()) { Arg = EmitScalarExpr(InputExpr); } else { - ErrorUnsupported(&S, "asm statement passing multiple-value types as inputs"); + ErrorUnsupported(&S, + "asm statement passing multiple-value types as inputs"); } } else { LValue Dest = EmitLValue(InputExpr); |