2016-03-05 20 views
7

Dato il codice seguente:Quale ottimizzazione GHC è responsabile della duplicazione delle espressioni del caso?

{-# OPTIONS_GHC -funbox-strict-fields #-} 
module Test where 

data X = X !Int !Int 

test (X a b) (X c d) = X (max a c) (max b d) 

GHC genera questo nucleo durante la compilazione con ottimizzazioni (rinominato agevolare la lettura):

test 
test = 
    \ u v -> 
    case u of x { X y z -> 
    case v of c { X d e -> 
    case tagToEnum# (<=# y d) of _ { 
     False -> 
     case tagToEnum# (<=# z e) of _ { 
      False -> x; 
      True -> X y e 
     }; 
     True -> 
     case tagToEnum# (<=# z e) of _ { 
      False -> X d z; 
      True -> c 
     } 
    } 
    } 
    } 

noti come GHC ha generato in percorsi totali codice diversi . In generale, il numero di percorsi di codice cresce in modo esponenziale con il numero di condizioni.

Quale ottimizzazione GHC conduce a tale comportamento? C'è una bandiera per controllare questa ottimizzazione? Nel mio caso, questo genera un enorme aumento di codice e rende molto difficili da leggere i dump di core a causa di espressioni caso nidificate.

+1

Sei sicuro al 100% che si tratti di un'ottimizzazione? Ho sempre pensato che l'istruzione 'case' di Core fosse limitata per eseguire una corrispondenza di pattern alla volta, e quindi questo tipo di' casing 'nidificato è necessario quando si gestiscono più pattern in una definizione. – Bakuriu

+0

Oh hmm, giuro che ha generato qualcos'altro senza ottimizzazione. Ma ora che sto cercando di riprodurlo, non lo fa più. Fammi controllare ... – bennofs

risposta

4

Dopo alcune ricerche, ho trovato che l'ottimizzazione responsabile di questo è la cosiddetta trasformazione "caso-del-caso", che GHC fa presumibilmente nel sistema di semplificazione, quindi non può essere disattivato (poiché è necessario per molto di ciò che fa GHC e il programma di semplificazione è parte integrante della pipeline di ottimizzazione di GHC).

seguente link spiega come caso di caso porta alla duplicazione: http://lambda.jstolarek.com/2013/01/taking-magic-out-of-ghc-or-tracing-compilation-by-transformation/

In particolare, caso-di-case trasforma questo:

case ( 
    case C of 
     B1 -> F1 
     B2 -> F2 
) of 
    A1 -> E1 
    A2 -> E2 

nelle seguenti:

case C of  
    B1 -> case F1 of 
       A1 -> E1 
       A2 -> E2 
    B2 -> case F2 of 
       A1 -> E1 
       A2 -> E2 

dove la custodia esterna è stata duplicata e spinta nei rami.

+0

Questo non lo spiega pienamente, non penso. Caso-caso entra in gioco solo perché 'max' e' min' sono in linea. Credo che potresti interrompere questo definendo '{- # NOINLINE max '# -}' 'max' :: Int -> Int -> Int' 'max '= max' e similmente per' min' e usando quelli. – dfeuer