[clang][bytecode] Special-case ConstantExpr in if conditions (#130294)

This happens a lot with `if constexpr` with a condition based on a
template param. In those cases, the condition is a ConstantExpr with a
value already set, so we can use that and ignore the other branch.
This commit is contained in:
Timm Baeder 2025-03-07 17:35:06 +01:00 committed by GitHub
parent db5e4016c0
commit d6a4828c8a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -5167,6 +5167,12 @@ bool Compiler<Emitter>::visitReturnStmt(const ReturnStmt *RS) {
}
template <class Emitter> bool Compiler<Emitter>::visitIfStmt(const IfStmt *IS) {
auto visitChildStmt = [&](const Stmt *S) -> bool {
LocalScope<Emitter> SScope(this);
if (!visitStmt(S))
return false;
return SScope.destroyLocals();
};
if (auto *CondInit = IS->getInit())
if (!visitStmt(CondInit))
return false;
@ -5175,7 +5181,22 @@ template <class Emitter> bool Compiler<Emitter>::visitIfStmt(const IfStmt *IS) {
if (!visitDeclStmt(CondDecl))
return false;
// Compile condition.
// Save ourselves compiling some code and the jumps, etc. if the condition is
// stataically known to be either true or false. We could look at more cases
// here, but I think all the ones that actually happen are using a
// ConstantExpr.
if (const auto *CE = dyn_cast_if_present<ConstantExpr>(IS->getCond());
CE && CE->hasAPValueResult() &&
CE->getResultAPValueKind() == APValue::ValueKind::Int) {
APSInt Value = CE->getResultAsAPSInt();
if (Value.getBoolValue())
return visitChildStmt(IS->getThen());
else if (const Stmt *Else = IS->getElse())
return visitChildStmt(Else);
return true;
}
// Otherwise, compile the condition.
if (IS->isNonNegatedConsteval()) {
if (!this->emitIsConstantContext(IS))
return false;
@ -5194,35 +5215,20 @@ template <class Emitter> bool Compiler<Emitter>::visitIfStmt(const IfStmt *IS) {
LabelTy LabelEnd = this->getLabel();
if (!this->jumpFalse(LabelElse))
return false;
{
LocalScope<Emitter> ThenScope(this);
if (!visitStmt(IS->getThen()))
return false;
if (!ThenScope.destroyLocals())
return false;
}
if (!visitChildStmt(IS->getThen()))
return false;
if (!this->jump(LabelEnd))
return false;
this->emitLabel(LabelElse);
{
LocalScope<Emitter> ElseScope(this);
if (!visitStmt(Else))
return false;
if (!ElseScope.destroyLocals())
return false;
}
if (!visitChildStmt(Else))
return false;
this->emitLabel(LabelEnd);
} else {
LabelTy LabelEnd = this->getLabel();
if (!this->jumpFalse(LabelEnd))
return false;
{
LocalScope<Emitter> ThenScope(this);
if (!visitStmt(IS->getThen()))
return false;
if (!ThenScope.destroyLocals())
return false;
}
if (!visitChildStmt(IS->getThen()))
return false;
this->emitLabel(LabelEnd);
}