@@ -5167,6 +5167,12 @@ bool Compiler<Emitter>::visitReturnStmt(const ReturnStmt *RS) {
5167
5167
}
5168
5168
5169
5169
template <class Emitter > bool Compiler<Emitter>::visitIfStmt(const IfStmt *IS) {
5170
+ auto visitChildStmt = [&](const Stmt *S) -> bool {
5171
+ LocalScope<Emitter> SScope (this );
5172
+ if (!visitStmt (S))
5173
+ return false ;
5174
+ return SScope.destroyLocals ();
5175
+ };
5170
5176
if (auto *CondInit = IS->getInit ())
5171
5177
if (!visitStmt (CondInit))
5172
5178
return false ;
@@ -5175,7 +5181,22 @@ template <class Emitter> bool Compiler<Emitter>::visitIfStmt(const IfStmt *IS) {
5175
5181
if (!visitDeclStmt (CondDecl))
5176
5182
return false ;
5177
5183
5178
- // Compile condition.
5184
+ // Save ourselves compiling some code and the jumps, etc. if the condition is
5185
+ // stataically known to be either true or false. We could look at more cases
5186
+ // here, but I think all the ones that actually happen are using a
5187
+ // ConstantExpr.
5188
+ if (const auto *CE = dyn_cast_if_present<ConstantExpr>(IS->getCond ());
5189
+ CE && CE->hasAPValueResult () &&
5190
+ CE->getResultAPValueKind () == APValue::ValueKind::Int) {
5191
+ APSInt Value = CE->getResultAsAPSInt ();
5192
+ if (Value.getBoolValue ())
5193
+ return visitChildStmt (IS->getThen ());
5194
+ else if (const Stmt *Else = IS->getElse ())
5195
+ return visitChildStmt (Else);
5196
+ return true ;
5197
+ }
5198
+
5199
+ // Otherwise, compile the condition.
5179
5200
if (IS->isNonNegatedConsteval ()) {
5180
5201
if (!this ->emitIsConstantContext (IS))
5181
5202
return false ;
@@ -5194,35 +5215,20 @@ template <class Emitter> bool Compiler<Emitter>::visitIfStmt(const IfStmt *IS) {
5194
5215
LabelTy LabelEnd = this ->getLabel ();
5195
5216
if (!this ->jumpFalse (LabelElse))
5196
5217
return false ;
5197
- {
5198
- LocalScope<Emitter> ThenScope (this );
5199
- if (!visitStmt (IS->getThen ()))
5200
- return false ;
5201
- if (!ThenScope.destroyLocals ())
5202
- return false ;
5203
- }
5218
+ if (!visitChildStmt (IS->getThen ()))
5219
+ return false ;
5204
5220
if (!this ->jump (LabelEnd))
5205
5221
return false ;
5206
5222
this ->emitLabel (LabelElse);
5207
- {
5208
- LocalScope<Emitter> ElseScope (this );
5209
- if (!visitStmt (Else))
5210
- return false ;
5211
- if (!ElseScope.destroyLocals ())
5212
- return false ;
5213
- }
5223
+ if (!visitChildStmt (Else))
5224
+ return false ;
5214
5225
this ->emitLabel (LabelEnd);
5215
5226
} else {
5216
5227
LabelTy LabelEnd = this ->getLabel ();
5217
5228
if (!this ->jumpFalse (LabelEnd))
5218
5229
return false ;
5219
- {
5220
- LocalScope<Emitter> ThenScope (this );
5221
- if (!visitStmt (IS->getThen ()))
5222
- return false ;
5223
- if (!ThenScope.destroyLocals ())
5224
- return false ;
5225
- }
5230
+ if (!visitChildStmt (IS->getThen ()))
5231
+ return false ;
5226
5232
this ->emitLabel (LabelEnd);
5227
5233
}
5228
5234
0 commit comments