зеркало из https://github.com/microsoft/clang-1.git
short circuit && and || when possible. This substantially reduces
the size of the -O0 output on some cases. For example, on expr.c from 176.gcc, it shrinks the .ll file from 43164 to 42835 lines, and removed references to two external symbols. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59034 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
62b72f6422
Коммит
0946ccd1e5
|
@ -1028,6 +1028,20 @@ Value *ScalarExprEmitter::VisitBinAssign(const BinaryOperator *E) {
|
|||
Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
|
||||
Value *LHSCond = CGF.EvaluateExprAsBool(E->getLHS());
|
||||
|
||||
if (llvm::ConstantInt *LHSCst = dyn_cast<llvm::ConstantInt>(LHSCond)) {
|
||||
// If we have 0 && RHS, see if we can elide RHS, if so, just return LHSCond.
|
||||
if (LHSCst->getZExtValue() == 0) {
|
||||
if (!CGF.ContainsLabel(E->getRHS()))
|
||||
// Elide RHS, return 0
|
||||
return llvm::Constant::getNullValue(CGF.LLVMIntTy);
|
||||
} else {
|
||||
// If we have 1 && X, just emit X without inserting the control flow.
|
||||
Value *RHSCond = CGF.EvaluateExprAsBool(E->getRHS());
|
||||
// ZExt result to int.
|
||||
return Builder.CreateZExt(RHSCond, CGF.LLVMIntTy, "land.ext");
|
||||
}
|
||||
}
|
||||
|
||||
llvm::BasicBlock *ContBlock = llvm::BasicBlock::Create("land_cont");
|
||||
llvm::BasicBlock *RHSBlock = llvm::BasicBlock::Create("land_rhs");
|
||||
|
||||
|
@ -1055,6 +1069,20 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
|
|||
Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) {
|
||||
Value *LHSCond = CGF.EvaluateExprAsBool(E->getLHS());
|
||||
|
||||
if (llvm::ConstantInt *LHSCst = dyn_cast<llvm::ConstantInt>(LHSCond)) {
|
||||
// If we have 1 || RHS, see if we can elide RHS, if so, just return LHSCond.
|
||||
if (LHSCst->getZExtValue() != 0) {
|
||||
if (!CGF.ContainsLabel(E->getRHS()))
|
||||
// Elide RHS, return 1
|
||||
return llvm::ConstantInt::get(CGF.LLVMIntTy, 1);
|
||||
} else {
|
||||
// If we have 0 || X, just emit X without inserting the control flow.
|
||||
Value *RHSCond = CGF.EvaluateExprAsBool(E->getRHS());
|
||||
// ZExt result to int.
|
||||
return Builder.CreateZExt(RHSCond, CGF.LLVMIntTy, "lor.ext");
|
||||
}
|
||||
}
|
||||
|
||||
llvm::BasicBlock *ContBlock = CGF.createBasicBlock("lor_cont");
|
||||
llvm::BasicBlock *RHSBlock = CGF.createBasicBlock("lor_rhs");
|
||||
|
||||
|
|
|
@ -217,34 +217,6 @@ void CodeGenFunction::EmitIndirectGotoStmt(const IndirectGotoStmt &S) {
|
|||
EmitDummyBlock();
|
||||
}
|
||||
|
||||
/// 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.
|
||||
|
|
|
@ -163,6 +163,36 @@ bool CodeGenFunction::isDummyBlock(const llvm::BasicBlock *BB) {
|
|||
return false;
|
||||
}
|
||||
|
||||
/// 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.
|
||||
bool CodeGenFunction::ContainsLabel(const Stmt *S, bool IgnoreCaseStmts) {
|
||||
// Null statement, not a label!
|
||||
if (S == 0) return 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;
|
||||
}
|
||||
|
||||
/// getCGRecordLayout - Return record layout info.
|
||||
const CGRecordLayout *CodeGenFunction::getCGRecordLayout(CodeGenTypes &CGT,
|
||||
QualType Ty) {
|
||||
|
|
|
@ -513,7 +513,13 @@ public:
|
|||
// Internal Helpers
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
||||
/// 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);
|
||||
|
||||
private:
|
||||
|
||||
/// EmitIndirectSwitches - Emit code for all of the switch
|
||||
/// instructions in IndirectSwitches.
|
||||
void EmitIndirectSwitches();
|
||||
|
|
Загрузка…
Ссылка в новой задаче