Optimisations

Vue d'ensemble des optimisations disponibles dans Catnip.

Niveaux d'Optimisation

Catnip supporte 4 niveaux d'optimisation (0-3) contrôlables via pragma, CLI ou API.

Défaut : optimize=0 (aucune optimisation)

Niveau Alias Description Passes actives
0 none, off (défaut) Aucune optimisation Aucune
1 basic, low Optimisations légères Constant folding (IR)
2 medium Optimisations standard Constant folding, Strength reduction, Block flattening (IR)
3 aggressive, high, full Optimisations agressives Toutes passes IR + CFG (dead code, merge, empty, branches), 5 itérations

Quand Activer les Optimisations

Défaut (optimize=0) - Recommandé pour :

  • Scripts et REPL (latence optimale)
  • Code avec JIT activé (JIT domine les optimisations)
  • Développement itératif (compilation 2x plus rapide)

optimize=3 - Activer pour :

  • Code exécuté 100+ fois sans JIT (gains 4-11%)
  • Templates/code généré avec beaucoup de dead code (réduction AST 46%)
  • Scripts de production sans JIT

Trade-offs mesurés :

  • Compile-time : optimize=3 est 2x plus lent (0.3ms → 0.7ms)
  • Runtime sans JIT : optimize=3 est 4-11% plus rapide
  • Runtime avec JIT : aucune différence (JIT masque les optimisations)

Les optimisations sont un multiplicateur de vitesse appliqué au démarrage. Le JIT est un turbo qui s'active en plein vol. Si ton code chauffe assez pour déclencher le JIT, les optimisations de compile-time deviennent du bruit de mesure.

Contrôle du Niveau

Via CLI :

catnip script.cat                 # Défaut (optimize=0)
catnip -o level:3 script.cat      # Active toutes les optimisations

# Alias textuels
catnip -o level:none script.cat   # Niveau 0 (défaut)
catnip -o level:low script.cat    # Niveau 1
catnip -o level:medium script.cat # Niveau 2
catnip -o level:high script.cat   # Niveau 3

Via pragma :

# Défaut : optimize=0
pragma("optimize", 3)   # Activer toutes les optimisations
pragma("optimize", 1)   # Optimisations légères

Via API Python :

from catnip import Catnip

cat = Catnip()              # Défaut (optimize=0)
cat = Catnip(optimize=3)    # Toutes les optimisations

Introspection :

catnip.optimize  # Retourne le niveau actuel (0-3)

# Branchement conditionnel
if catnip.optimize > 0 {
    "code optimisé"
} else {
    "sans optimisation"
}

Passes Disponibles

Catnip applique deux types de passes complémentaires :

Passes IR (Niveau Expression)

Optimisations locales sur expressions et statements :

  1. Constant Folding - Évalue les expressions constantes au compile-time

  2. 2 + 35

  3. True and FalseFalse

  4. Strength Reduction - Remplace opérations coûteuses par équivalents rapides

  5. x * 2x + x (si x simple)

  6. x ** 2x * x

  7. Block Flattening - Simplifie les blocs imbriqués

  8. { { { x } } }x

  9. Dead Code Elimination - Supprime code inaccessible

  10. Code après return

  11. Branches if False

  12. Common Subexpression Elimination (CSE) - Réutilise calculs identiques

  13. a*b + a*btemp = a*b; temp + temp

  14. Blunt Code Simplification - Simplifie patterns maladroits

  15. not not xx

  16. x == Truex

  17. Constant/Copy Propagation - Propage valeurs connues

  18. x = 5; y = x * 2x = 5; y = 10

Passes CFG (Niveau Contrôle de Flux)

Optimisations globales sur le graphe de flot de contrôle :

  1. Dead Block Elimination - Supprime blocs inaccessibles
  2. Block Merging - Fusionne blocs consécutifs
  3. Empty Block Removal - Supprime blocs vides
  4. Constant Branch Folding - Résout branches constantes

Architecture du Pipeline

IR → IR Optimizer → CFG → Semantic → Op → Tail→Loop
     ├─ BluntCode              ├─ Dead code (CFG)
     ├─ ConstantPropagation    ├─ Merge blocks
     ├─ ConstantFolding        ├─ Empty removal
     ├─ CopyPropagation        └─ Const branches
     ├─ DeadStoreElimination
     ├─ StrengthReduction
     ├─ BlockFlattening
     ├─ DeadCodeElimination
     └─ CSE

Ordre d'exécution :

  1. Passes IR (7 passes) sur l'IR brut
  2. CFG construction depuis IR optimisé
  3. Passes CFG (4 passes) sur le graphe
  4. Reconstruction IR depuis CFG optimisé
  5. Semantic analysis → Op final

Itérations : À niveau 3, le pipeline IR+CFG est exécuté 5 fois (certaines passes débloquent d'autres optimisations)

Tail Call Optimization (TCO)

La TCO est une optimisation toujours active (indépendante du niveau) :

Principe : Transforme récursion terminale en boucle (stack O(1))

fact = (n, acc) => {
    if n <= 1 { acc }
    else { fact(n-1, n*acc) }  # ← Tail call
}

Détection : Automatique par l'analyseur sémantique (appels en dernière position)

Implémentation : Trampoline pattern (pas de frame empilée)

Voir ARCHITECTURE.md section TCO pour détails.