Don't inline non representable results with free type variables.
authorMatthijs Kooijman <matthijs@stdin.nl>
Tue, 13 Apr 2010 14:48:35 +0000 (16:48 +0200)
committerMatthijs Kooijman <matthijs@stdin.nl>
Tue, 13 Apr 2010 14:48:35 +0000 (16:48 +0200)
argprop should ensure that these variables get removed eventually
anyway.

cλash/CLasH/Normalize.hs

index acb3450fe14ab17711d0ed85ae59ed8dedbf3c06..20d3ac85d778f649c04e17d0219fc59ee78a8542 100644 (file)
@@ -819,47 +819,54 @@ inlinenonrepresult context expr | not (is_fun expr) =
           case body_maybe of
             Just body -> do
               let (bndrs, binds, res) = splitNormalizedNonRep body
-              -- Get the free local variables of res
-              global_bndrs <- Trans.lift getGlobalBinders
-              let interesting var = Var.isLocalVar var && (var `notElem` global_bndrs)
-              let free_vars = VarSet.varSetElems $ CoreFVs.exprSomeFreeVars interesting res
-              let free_var_types = map Id.idType free_vars
-              let n_free_vars = length free_vars
-              -- Get a tuple datacon to wrap around the free variables
-              let fvs_datacon = TysWiredIn.tupleCon BasicTypes.Boxed n_free_vars
-              let fvs_datacon_id = DataCon.dataConWorkId fvs_datacon
-              -- Let the function now return a tuple with references to
-              -- all free variables of the old return value. First pass
-              -- all the types of the variables, since tuple
-              -- constructors are polymorphic.
-              let newres = mkApps (Var fvs_datacon_id) (map Type free_var_types ++  map Var free_vars)
-              -- Recreate the function body with the changed return value
-              let newbody = mkLams bndrs (Let (Rec binds) newres) 
-              -- Create the new function
-              f' <- Trans.lift $ mkFunction f newbody
-
-              -- Call the new function
-              let newapp = mkApps (Var f') args
-              res_bndr <- Trans.lift $ mkBinderFor newapp "res"
-              -- Create extractor case expressions to extract each of the
-              -- free variables from the tuple.
-              sel_cases <- Trans.lift $ mapM (mkSelCase (Var res_bndr)) [0..n_free_vars-1]
-
-              -- Bind the res_bndr to the result of the new application
-              -- and each of the free variables to the corresponding
-              -- selector case. Replace the let body with the original
-              -- body of the called function (which can still access all
-              -- of its free variables, from the let).
-              let binds = (res_bndr, newapp):(zip free_vars sel_cases)
-              let letexpr = Let (Rec binds) res
-
-              -- Finally, regenarate all uniques in the new expression,
-              -- since the free variables could otherwise become
-              -- duplicated. It is not strictly necessary to regenerate
-              -- res, since we're moving that expression, but it won't
-              -- hurt.
-              letexpr_uniqued <- Trans.lift $ genUniques letexpr
-              change letexpr_uniqued
+              if has_free_tyvars res 
+                then
+                  -- Don't touch anything with free type variables, since
+                  -- we can't return those. We'll wait until argprop
+                  -- removed those variables.
+                  return expr
+                else do
+                  -- Get the free local variables of res
+                  global_bndrs <- Trans.lift getGlobalBinders
+                  let interesting var = Var.isLocalVar var && (var `notElem` global_bndrs)
+                  let free_vars = VarSet.varSetElems $ CoreFVs.exprSomeFreeVars interesting res
+                  let free_var_types = map Id.idType free_vars
+                  let n_free_vars = length free_vars
+                  -- Get a tuple datacon to wrap around the free variables
+                  let fvs_datacon = TysWiredIn.tupleCon BasicTypes.Boxed n_free_vars
+                  let fvs_datacon_id = DataCon.dataConWorkId fvs_datacon
+                  -- Let the function now return a tuple with references to
+                  -- all free variables of the old return value. First pass
+                  -- all the types of the variables, since tuple
+                  -- constructors are polymorphic.
+                  let newres = mkApps (Var fvs_datacon_id) (map Type free_var_types ++  map Var free_vars)
+                  -- Recreate the function body with the changed return value
+                  let newbody = mkLams bndrs (Let (Rec binds) newres) 
+                  -- Create the new function
+                  f' <- Trans.lift $ mkFunction f newbody
+
+                  -- Call the new function
+                  let newapp = mkApps (Var f') args
+                  res_bndr <- Trans.lift $ mkBinderFor newapp "res"
+                  -- Create extractor case expressions to extract each of the
+                  -- free variables from the tuple.
+                  sel_cases <- Trans.lift $ mapM (mkSelCase (Var res_bndr)) [0..n_free_vars-1]
+
+                  -- Bind the res_bndr to the result of the new application
+                  -- and each of the free variables to the corresponding
+                  -- selector case. Replace the let body with the original
+                  -- body of the called function (which can still access all
+                  -- of its free variables, from the let).
+                  let binds = (res_bndr, newapp):(zip free_vars sel_cases)
+                  let letexpr = Let (Rec binds) res
+
+                  -- Finally, regenarate all uniques in the new expression,
+                  -- since the free variables could otherwise become
+                  -- duplicated. It is not strictly necessary to regenerate
+                  -- res, since we're moving that expression, but it won't
+                  -- hurt.
+                  letexpr_uniqued <- Trans.lift $ genUniques letexpr
+                  change letexpr_uniqued
             Nothing -> return expr
         else
           -- Don't touch representable expressions or (applications of)