From 3f8ef7daefaf749d7c64e99a24a748d6bbbf26c9 Mon Sep 17 00:00:00 2001 From: CharlesKWON Date: Sat, 18 Apr 2026 08:32:24 +0900 Subject: [PATCH] perf(gengo): eliminate dead IF/ELSEIF branches with literal conds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- compiler/gengo/gengo.go | 86 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 82 insertions(+), 4 deletions(-) diff --git a/compiler/gengo/gengo.go b/compiler/gengo/gengo.go index cc44fbf..d66b800 100644 --- a/compiler/gengo/gengo.go +++ b/compiler/gengo/gengo.go @@ -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("}") } }