aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGExprScalar.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2008-11-12 08:55:54 +0000
committerChris Lattner <sabre@nondot.org>2008-11-12 08:55:54 +0000
commit9802a5173ffd403d9ede2d4b6b6107fa2e220544 (patch)
tree7c34da80b65d2b7a5b2428914a57034af56d965b /lib/CodeGen/CGExprScalar.cpp
parentf7b5ea9de3d043fa900ab8a8976a4c0eefc233b7 (diff)
Lower ?: into select when the selected values are cheap and side-effect-free.
This cuts another 200 lines off expr.ll, forming 23 selects. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59124 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGExprScalar.cpp')
-rw-r--r--lib/CodeGen/CGExprScalar.cpp37
1 files changed, 37 insertions, 0 deletions
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index a3964ee2fc..918d3bbde8 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -1119,6 +1119,30 @@ Value *ScalarExprEmitter::VisitBinComma(const BinaryOperator *E) {
// Other Operators
//===----------------------------------------------------------------------===//
+/// isCheapEnoughToEvaluateUnconditionally - Return true if the specified
+/// expression is cheap enough and side-effect-free enough to evaluate
+/// unconditionally instead of conditionally. This is used to convert control
+/// flow into selects in some cases.
+static bool isCheapEnoughToEvaluateUnconditionally(const Expr *E) {
+ if (const ParenExpr *PE = dyn_cast<ParenExpr>(E))
+ return isCheapEnoughToEvaluateUnconditionally(PE->getSubExpr());
+
+ // TODO: Allow anything we can constant fold to an integer or fp constant.
+ if (isa<IntegerLiteral>(E) || isa<CharacterLiteral>(E) ||
+ isa<FloatingLiteral>(E))
+ return true;
+
+ // Non-volatile automatic variables too, to get "cond ? X : Y" where
+ // X and Y are local variables.
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
+ if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl()))
+ if (VD->hasLocalStorage() && !VD->getType().isVolatileQualified())
+ return true;
+
+ return false;
+}
+
+
Value *ScalarExprEmitter::
VisitConditionalOperator(const ConditionalOperator *E) {
// If the condition constant folds and can be elided, try to avoid emitting
@@ -1136,6 +1160,19 @@ VisitConditionalOperator(const ConditionalOperator *E) {
return Visit(Live);
}
+
+ // If this is a really simple expression (like x ? 4 : 5), emit this as a
+ // select instead of as control flow. We can only do this if it is cheap and
+ // safe to
+ if (E->getLHS() && isCheapEnoughToEvaluateUnconditionally(E->getLHS()) &&
+ isCheapEnoughToEvaluateUnconditionally(E->getRHS())) {
+ llvm::Value *CondV = CGF.EvaluateExprAsBool(E->getCond());
+ llvm::Value *LHS = Visit(E->getLHS());
+ llvm::Value *RHS = Visit(E->getRHS());
+ return Builder.CreateSelect(CondV, LHS, RHS, "cond");
+ }
+
+
llvm::BasicBlock *LHSBlock = CGF.createBasicBlock("cond.?");
llvm::BasicBlock *RHSBlock = CGF.createBasicBlock("cond.:");
llvm::BasicBlock *ContBlock = CGF.createBasicBlock("cond.cont");