Skip to content

Commit a2ab137

Browse files
committed
wip:raw-opt improvements
1 parent fe0b0fd commit a2ab137

File tree

3 files changed

+77
-35
lines changed

3 files changed

+77
-35
lines changed

compiler/src/RawOpt.hs

Lines changed: 62 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,14 @@ data PState =
9696
stateSubst :: Subst,
9797
stateChange:: ChangeFlag,
9898
stateRawVarTypes :: Map RawVar RawType, -- for assertions optimizations
99-
stateLValTypes :: Map VarName RawType -- for assertions optimizations
99+
stateLValTypes :: Map VarName RawType -- for assertions optimizations
100100
}
101101

102+
103+
data ReadEnv =
104+
ReadEnv { readConsts :: Map RawVar Core.Lit }
105+
106+
102107
-- 2021-02-28; AA
103108
-- As we traverse the AST we collect information about how
104109
-- different bindings are used. We distinguish two different
@@ -113,7 +118,7 @@ type Used = (Set VarName, Set RawVar)
113118
type ChangeFlag = Bool
114119

115120
-- Optimization monad: keep track of used variables, to be able to eliminate unused variables.
116-
type Opt = RWS () Used PState
121+
type Opt = RWS ReadEnv Used PState
117122

118123
class PEval a where
119124
peval :: a -> Opt a
@@ -266,13 +271,13 @@ _setLValType x t = modify (\pstate ->
266271
-- Partially evaluate instruction. This is called multiple times in the optimization sequence.
267272
-- First pass: partially evaluate functions (instructions).
268273
-- Removes e.g. redundant state projections state (e.g. if multiple in same block).
269-
-- Returns 'Nothing' if the instruction is to be ommitted.
270-
pevalInst:: RawInst -> Opt (Maybe RawInst)
274+
--
275+
pevalInst:: RawInst -> Opt [RawInst]
271276
pevalInst i = do
272277
pstate <- get
273278
i' <- subst i -- apply the collected substitutions
274-
let _omit x = x >> (return Nothing)
275-
let _keep x = x >> (return $ Just i')
279+
let _omit x = x >> return []
280+
let _keep x = x >> return [i']
276281

277282
case i' of
278283
AssignRaw r (ProjectState p) -> do
@@ -319,21 +324,39 @@ pevalInst i = do
319324
case guessType rexpr of
320325
Nothing -> return ()
321326
Just ty -> _setRawType r ty
322-
323327

324-
AssignLVal v complexExpr -> _keep $ do
325-
case complexExpr of
326-
Bin op (UseNativeBinop False) r1 r2 | op `elem` [Basics.Eq, Basics.Neq] ->
327-
_setLValType v RawBoolean
328-
_ -> return ()
328+
AssignLVal v complexExpr@(Bin op (UseNativeBinop False) r1 r2)
329+
| op `elem` [Basics.Eq, Basics.Neq] -> do
330+
_setLValType v RawBoolean
331+
a <- isSuitableForNativeEq r1
332+
b <- isSuitableForNativeEq r2
333+
if a || b
334+
then do
335+
let VN s = v
336+
r3 = RawVar $ s ++ "$val_opt"
337+
r4 = RawVar $ s ++ "$vlev_opt"
338+
r5 = RawVar $ s ++ "$tlev_opt"
339+
markUsed v
340+
markUsed [r1, r2, r3, r4, r5]
341+
return $
342+
[ AssignRaw r3 (Bin op (UseNativeBinop True) r1 r2)
343+
, AssignRaw r4 (ProjectState MonPC)
344+
, AssignRaw r5 (ProjectState MonPC)
345+
, AssignLVal v (ConstructLVal r3 r4 r5)
346+
]
347+
else
348+
_keep $ markUsed complexExpr
349+
350+
351+
AssignLVal v complexExpr ->
329352
_keep $ markUsed complexExpr
330353

331354
SetState p r -> _keep $ do
332355
markUsed r
333356
monInsert p r
334357
RTAssertion (AssertType r rt) -> do
335358
case Map.lookup r (stateRawVarTypes pstate) of
336-
Just rt' | rt' == rt -> return Nothing
359+
Just rt' | rt' == rt -> return []
337360
_ -> _keep $ _setRawType r rt >> markUsed r
338361
-- RTAssertion (AssertEqTypes opt_ls x y) -> do
339362
-- let _m = stateTypes pstate
@@ -353,19 +376,34 @@ pevalInst i = do
353376
case (Map.lookup x _m, Map.lookup y _m) of
354377
(Just t1 , Just t2) | t1 == t2 ->
355378
if t1 `elem` [RawNumber, RawString]
356-
then return Nothing
379+
then return []
357380
else keep
358381
_ -> keep
359382
-- TODO track tuple length
360383
RTAssertion (AssertTupleLengthGreaterThan r n) -> _keep $ markUsed r
361384
-- TODO track record fields
362385
RTAssertion (AssertRecordHasField r f) -> _keep $ markUsed r
363-
RTAssertion (AssertNotZero r) -> _keep $ markUsed r
386+
RTAssertion (AssertNotZero r) -> do
387+
renv <- ask
388+
case Map.lookup r (readConsts renv) of
389+
Just (Core.LInt x _) | x /= 0 -> return []
390+
_ -> _keep $ markUsed r
364391
MkFunClosures ee _ -> _keep $ markUsed (snd (unzip ee))
365392
-- No applicable optimizations.
366-
SetBranchFlag -> return $ Just i'
367-
InvalidateSparseBit -> return $ Just i'
368-
393+
SetBranchFlag -> return [i']
394+
InvalidateSparseBit -> return [i']
395+
396+
397+
isSuitableForNativeEq r = do
398+
pstate <- get
399+
return $
400+
case Map.lookup r (stateRawVarTypes pstate) of
401+
Nothing -> False
402+
Just t -> case t of
403+
RawNumber -> True
404+
RawString -> True
405+
_ -> False
406+
369407

370408
instance PEval RawTerminator where
371409
peval tr = do
@@ -488,7 +526,7 @@ instOrder ii = work [] ii
488526
instance PEval RawBBTree where
489527
peval bb@(BB insts tr) = do
490528
(BB jj tr'', used) <- listen $ do
491-
ii <- Data.Maybe.catMaybes <$> mapM pevalInst insts
529+
ii <- concat <$> mapM pevalInst insts
492530
tr' <- peval tr
493531
return $ BB ii tr'
494532
let (insts_no_ret, set_pc_bl) = filterInstBwd (filter (isLiveInstFwd used) jj)
@@ -538,8 +576,11 @@ funopt (FunDef hfn consts bb ir) =
538576
stateRawVarTypes = constTypes,
539577
stateLValTypes = Map.empty
540578
}
541-
(bb', _, _) = runRWS (peval bb) () pstate
542-
new = FunDef hfn consts' bb' ir
579+
580+
readenv = ReadEnv { readConsts = Map.fromList consts }
581+
(bb', _, (_, used_rvars)) = runRWS (peval bb) readenv pstate
582+
const_used = filter (\(x,_) -> Set.member x used_rvars) consts'
583+
new = FunDef hfn const_used bb' ir
543584
in if bb /= bb' then funopt new else new
544585

545586

compiler/src/Stack2JS.hs

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ addOneLib (LibAccess (Basics.LibName libname) varname) =
9393
let args = (PP.quotes.PP.text) libname <+> text "," <+> (PP.quotes. PP.text) varname
9494
in text "this.addLib " <+> PP.parens args
9595

96-
addLibs xs = vcat (map addOneLib xs)
96+
addLibs xs = vcat $ nub (map addOneLib xs)
9797

9898

9999
data TheState = TheState { freshCounter :: Integer
@@ -312,8 +312,8 @@ instance ToJS StackInst where
312312
instance ToJS StackTerminator where
313313
toJS = tr2js
314314

315-
binOpToJS :: BinOp -> String
316-
binOpToJS = \case
315+
binOpToJS :: BinOp -> Raw.UseNativeBinop -> String
316+
binOpToJS op (Raw.UseNativeBinop isNative) = case op of
317317
-- JS binary operators (some not implemented in IR2Raw)
318318
Plus -> "+"
319319
Minus -> "-"
@@ -334,8 +334,8 @@ binOpToJS = \case
334334
BinZeroShiftRight -> ">>>"
335335
-- Functions defined in UserRuntimeZero.ts
336336
IntDiv -> "rt.intdiv"
337-
Eq -> "rt.eq"
338-
Neq -> "rt.neq"
337+
Eq -> if isNative then "===" else "rt.eq"
338+
Neq -> if isNative then "!==" else "rt.neq"
339339
Concat -> "+"
340340
HasField -> "rt.hasField"
341341
LatticeJoin -> "rt.raw_join"
@@ -414,7 +414,7 @@ ir2js (MkFunClosures envBindings funBindings) = do
414414
d_b <- toJS b
415415
return $ d_b <> text ".dataLevel") ls
416416
let d2 = penv PP.<> text ".__dataLevel = "
417-
<+> jsFunCall (text $ binOpToJS Basics.LatticeJoin) d3
417+
<+> jsFunCall (text $ binOpToJS Basics.LatticeJoin (Raw.UseNativeBinop False)) d3
418418

419419
return $ vcat ( d1 ++ [d2])
420420
hsepc ls = semi $ PP.hsep (PP.punctuate (text ",") ls)
@@ -583,9 +583,9 @@ instance ToJS RawExpr where
583583
Raw.FieldValLev -> monStateToJs MonPC
584584
Raw.FieldTypLev -> monStateToJs MonPC)
585585
e@(ProjectLVal _ _) -> return $ ppRawExpr e
586-
Bin binop _ va1 va2 -> return $
587-
let text' = (text . binOpToJS) binop in
588-
if isInfixBinop binop
586+
Bin binop use_native va1 va2 -> return $
587+
let text' = text (binOpToJS binop use_native) in
588+
if isInfixBinop binop use_native
589589
then hsep [ ppId va1, text', ppId va2 ]
590590
else jsFunCall text' [ppId va1, ppId va2]
591591
Un op v -> return $ text (unaryOpToJS op) <> PP.parens (ppId v)
@@ -663,8 +663,8 @@ freshKontName = do
663663
return $ VN $ "$$$" ++ s ++ "$$$kont" ++ (show j)
664664

665665

666-
isInfixBinop :: Basics.BinOp -> Bool
667-
isInfixBinop = \case
666+
isInfixBinop :: Basics.BinOp -> Raw.UseNativeBinop -> Bool
667+
isInfixBinop op (Raw.UseNativeBinop use_native) = case op of
668668
-- Infix
669669
Plus -> True
670670
Minus -> True
@@ -684,9 +684,10 @@ isInfixBinop = \case
684684
BinShiftLeft -> True
685685
BinShiftRight -> True
686686
BinZeroShiftRight -> True
687+
-- Flag dependent
688+
Eq -> use_native
689+
Neq -> use_native
687690
-- Not infix
688-
Eq -> False
689-
Neq -> False
690691
RaisedTo -> False
691692
FlowsTo -> False
692693
IntDiv -> False

tests/_unautomated/loop.trp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
let
22
fun loop n =
3-
if n = 10 then
3+
if n <> 10 then
44
let val _ = printWithLabels n
55
in loop (n + 1)
66
end

0 commit comments

Comments
 (0)