X-Git-Url: https://git.stderr.nl/gitweb?a=blobdiff_plain;f=c%CE%BBash%2FCLasH%2FNormalize%2FNormalizeTools.hs;h=48a40087a5e70b78772f82d9bc9ec91eb4baf5d7;hb=ab02b890f1921992e1b6b9e19bcaeb57cdd97b78;hp=803fd958cec82637d8177194da570e89ecf40f2b;hpb=0223b461a043e42d3fc5442904b73ce0bd537472;p=matthijs%2Fmaster-project%2Fc%CE%BBash.git diff --git "a/c\316\273ash/CLasH/Normalize/NormalizeTools.hs" "b/c\316\273ash/CLasH/Normalize/NormalizeTools.hs" index 803fd95..48a4008 100644 --- "a/c\316\273ash/CLasH/Normalize/NormalizeTools.hs" +++ "b/c\316\273ash/CLasH/Normalize/NormalizeTools.hs" @@ -6,6 +6,7 @@ module CLasH.Normalize.NormalizeTools where -- Standard modules import qualified Data.Monoid as Monoid +import qualified Data.Either as Either import qualified Control.Monad as Monad import qualified Control.Monad.Trans.Writer as Writer import qualified "transformers" Control.Monad.Trans as Trans @@ -45,12 +46,13 @@ applyboth first (name, second) context expr = do if Monoid.getAny $ -- trace ("Trying to apply transform " ++ name ++ " to:\n" ++ showSDoc (nest 4 $ ppr expr') ++ "\nType: \n" ++ (showSDoc $ nest 4 $ ppr $ CoreUtils.exprType expr') ++ "\n") changed - then do + then -- trace ("Applying transform " ++ name ++ " to:\n" ++ showSDoc (nest 4 $ ppr expr') ++ "\nType: \n" ++ (showSDoc $ nest 4 $ ppr $ CoreUtils.exprType expr') ++ "\n" -- ++ "Context: " ++ show context ++ "\n" -- ++ "Result of applying " ++ name ++ ":\n" ++ showSDoc (nest 4 $ ppr expr'') ++ "\n" ++ "Type: \n" ++ (showSDoc $ nest 4 $ ppr $ CoreUtils.exprType expr'') ++ "\n" ) $ - Trans.lift $ MonadState.modify tsTransformCounter (+1) - applyboth first (name, second) context expr'' + do + Trans.lift $ MonadState.modify tsTransformCounter (+1) + applyboth first (name, second) context expr'' else -- trace ("No changes") $ return expr'' @@ -110,16 +112,43 @@ dotransforms transs expr = do -- Inline all let bindings that satisfy the given condition inlinebind :: ((CoreBndr, CoreExpr) -> TransformMonad Bool) -> Transform -inlinebind condition context expr@(Let (NonRec bndr expr') res) = do - applies <- condition (bndr, expr') - if applies - then do - -- Substitute the binding in res and return that - res' <- substitute_clone bndr expr' context res - change res' - else - -- Don't change this let - return expr +inlinebind condition context expr@(Let (Rec binds) res) = do + -- Find all bindings that adhere to the condition + res_eithers <- mapM docond binds + case Either.partitionEithers res_eithers of + -- No replaces? No change + ([], _) -> return expr + (replace, others) -> do + -- Substitute the to be replaced binders with their expression + newexpr <- do_substitute replace (Let (Rec others) res) + change newexpr + where + -- Apply the condition to a let binding and return an Either + -- depending on whether it needs to be inlined or not. + docond :: (CoreBndr, CoreExpr) -> TransformMonad (Either (CoreBndr, CoreExpr) (CoreBndr, CoreExpr)) + docond b = do + res <- condition b + return $ case res of True -> Left b; False -> Right b + + -- Apply the given list of substitutions to the the given expression + do_substitute :: [(CoreBndr, CoreExpr)] -> CoreExpr -> TransformMonad CoreExpr + do_substitute [] expr = return expr + do_substitute ((bndr, val):reps) expr = do + -- Perform this substitution in the expression + expr' <- substitute_clone bndr val context expr + -- And in the substitution values we will be using next + reps' <- mapM (subs_bind bndr val) reps + -- And then perform the remaining substitutions + do_substitute reps' expr' + + -- Replace the given binder with the given expression in the + -- expression oft the given let binding + subs_bind :: CoreBndr -> CoreExpr -> (CoreBndr, CoreExpr) -> TransformMonad (CoreBndr, CoreExpr) + subs_bind bndr expr (b, v) = do + v' <- substitute_clone bndr expr (LetBinding:context) v + return (b, v') + + -- Leave all other expressions unchanged inlinebind _ context expr = return expr @@ -186,17 +215,17 @@ isUserDefined bndr = str `notElem` builtinIds where str = Name.getOccString bndr --- Is the given binder normalizable? This means that its type signature can be +-- | Is the given binder normalizable? This means that its type signature can be -- represented in hardware, which should (?) guarantee that it can be made --- into hardware. Note that if a binder is not normalizable, it might become --- so using argument propagation. -isNormalizeable :: CoreBndr -> TransformMonad Bool -isNormalizeable bndr = Trans.lift (isNormalizeable' bndr) - -isNormalizeable' :: CoreBndr -> TranslatorSession Bool -isNormalizeable' bndr = do +-- into hardware. This checks whether all the arguments and (optionally) +-- the return value are +-- representable. +isNormalizeable :: + Bool -- ^ Allow the result to be unrepresentable? + -> CoreBndr -- ^ The binder to check + -> TranslatorSession Bool -- ^ Is it normalizeable? +isNormalizeable result_nonrep bndr = do let ty = Id.idType bndr let (arg_tys, res_ty) = Type.splitFunTys ty - -- This function is normalizable if all its arguments and return value are - -- representable. - andM $ mapM isRepr' (res_ty:arg_tys) + let check_tys = if result_nonrep then arg_tys else (res_ty:arg_tys) + andM $ mapM isRepr' check_tys