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:
@@ -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("}")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user