/- Copyright (c) 2019 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura -/ prelude import Init.Lean.Compiler.IR.Basic import Init.Lean.Compiler.IR.Format namespace Lean namespace IR def ensureHasDefault (alts : Array Alt) : Array Alt := if alts.any Alt.isDefault then alts else if alts.size < 2 then alts else let last := alts.back; let alts := alts.pop; alts.push (Alt.default last.body) private def getOccsOf (alts : Array Alt) (i : Nat) : Nat := let aBody := (alts.get! i).body; alts.iterateFrom 1 (i + 1) $ fun _ a' n => if a'.body == aBody then n+1 else n private def maxOccs (alts : Array Alt) : Alt × Nat := alts.iterateFrom (alts.get! 0, getOccsOf alts 0) 1 $ fun i a p => let noccs := getOccsOf alts i.val; if noccs > p.2 then (alts.get i, noccs) else p private def addDefault (alts : Array Alt) : Array Alt := if alts.size <= 1 || alts.any Alt.isDefault then alts else let (max, noccs) := maxOccs alts; if noccs == 1 then alts else let alts := alts.filter $ (fun alt => alt.body != max.body); alts.push (Alt.default max.body) private def mkSimpCase (tid : Name) (x : VarId) (xType : IRType) (alts : Array Alt) : FnBody := let alts := alts.filter (fun alt => alt.body != FnBody.unreachable); let alts := addDefault alts; if alts.size == 0 then FnBody.unreachable else if alts.size == 1 then (alts.get! 0).body else FnBody.case tid x xType alts partial def FnBody.simpCase : FnBody → FnBody | b => let (bs, term) := b.flatten; let bs := modifyJPs bs FnBody.simpCase; match term with | FnBody.case tid x xType alts => let alts := alts.map $ fun alt => alt.modifyBody FnBody.simpCase; reshape bs (mkSimpCase tid x xType alts) | other => reshape bs term /-- Simplify `case` - Remove unreachable branches. - Remove `case` if there is only one branch. - Merge most common branches using `Alt.default`. -/ def Decl.simpCase : Decl → Decl | Decl.fdecl f xs t b => Decl.fdecl f xs t b.simpCase | other => other end IR end Lean