mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-19 00:56:41 +00:00
[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:
parent
db5e4016c0
commit
d6a4828c8a
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user