perf(gengo): eliminate dead IF/ELSEIF branches with literal conds

IF .T. collapses to its body; IF .F. forwards to the first live
ELSEIF or ELSE. For dynamic main conditions the chain is still
filtered: ELSEIF .F. drops out, ELSEIF .T. truncates and becomes
the ELSE. Verified with /tmp/test_deadif.prg — five dead labels
all removed from gen output, runtime emits only live branches.

FiveSql2 43/43, Harbour compat 56/56.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-18 08:32:24 +09:00
parent 111ab8a6f0
commit 3f8ef7daef

View File

@@ -1265,7 +1265,85 @@ func (g *Generator) emitCallAsStmt(call *ast.CallExpr, locals localMap) {
g.writeln(fmt.Sprintf("t.Do(%d)", len(call.Args)))
}
// boolLiteralValue returns (value, true) if e is a bare .T./.F. literal.
// Used by emitIf to skip dead branches.
func boolLiteralValue(e ast.Expr) (bool, bool) {
lit, ok := e.(*ast.LiteralExpr)
if !ok {
return false, false
}
switch lit.Kind {
case token.TRUE:
return true, true
case token.FALSE:
return false, true
}
return false, false
}
func (g *Generator) emitIf(s *ast.IfStmt, locals localMap) {
// Dead-branch elimination for literal conditions. An IF .T. collapses
// to its body; an IF .F. collapses to its first live ELSEIF/ELSE.
// We resolve the main Cond here and recurse on the remainder if it
// turns into a new IF chain.
if v, ok := boolLiteralValue(s.Cond); ok {
if v {
for _, stmt := range s.Body {
g.emitStmt(stmt, locals)
}
return
}
// IF .F. — scan ElseIfs for first non-.F. branch.
for i, ei := range s.ElseIfs {
if v2, ok2 := boolLiteralValue(ei.Cond); ok2 {
if v2 {
for _, stmt := range ei.Body {
g.emitStmt(stmt, locals)
}
return
}
continue // ELSEIF .F. — dead, skip
}
// Non-literal ELSEIF becomes the new IF head.
newIf := &ast.IfStmt{
IfPos: ei.ElseIfPos,
Cond: ei.Cond,
Body: ei.Body,
ElseIfs: s.ElseIfs[i+1:],
ElseBody: s.ElseBody,
}
g.emitIf(newIf, locals)
return
}
// All ElseIfs were .F. — only ELSE body remains.
for _, stmt := range s.ElseBody {
g.emitStmt(stmt, locals)
}
return
}
// Main cond is dynamic. Still filter dead ELSEIFs (.F. removed;
// an ELSEIF .T. truncates the chain and becomes the ELSE).
elseIfs := s.ElseIfs
elseBody := s.ElseBody
if len(elseIfs) > 0 {
filtered := make([]*ast.ElseIfClause, 0, len(elseIfs))
for _, ei := range elseIfs {
if v, ok := boolLiteralValue(ei.Cond); ok {
if v {
// ELSEIF .T. — chain stops here; body becomes ELSE.
elseBody = ei.Body
elseIfs = filtered
goto emit
}
continue // ELSEIF .F. — dead
}
filtered = append(filtered, ei)
}
elseIfs = filtered
}
emit:
g.emitExpr(s.Cond)
g.writeln("if t.PopLogical() {")
g.indent++
@@ -1274,7 +1352,7 @@ func (g *Generator) emitIf(s *ast.IfStmt, locals localMap) {
}
g.indent--
for _, ei := range s.ElseIfs {
for _, ei := range elseIfs {
g.writeIndent()
g.write("} else {\n")
g.indent++
@@ -1287,10 +1365,10 @@ func (g *Generator) emitIf(s *ast.IfStmt, locals localMap) {
g.indent--
}
if len(s.ElseBody) > 0 {
if len(elseBody) > 0 {
g.writeln("} else {")
g.indent++
for _, stmt := range s.ElseBody {
for _, stmt := range elseBody {
g.emitStmt(stmt, locals)
}
g.indent--
@@ -1299,7 +1377,7 @@ func (g *Generator) emitIf(s *ast.IfStmt, locals localMap) {
g.writeln("}")
// Close nested elseif braces
for range s.ElseIfs {
for range elseIfs {
g.writeln("}")
}
}