summaryrefslogtreecommitdiff
path: root/il.fun
diff options
context:
space:
mode:
authorVladimir Azarov <avm@intermediate-node.net>2025-08-11 23:11:32 +0200
committerVladimir Azarov <avm@intermediate-node.net>2025-08-11 23:11:32 +0200
commitaad6f4f80e3196b052e96176ff412ddb7ceb7ef6 (patch)
tree71cce0d0423b699f63ad51826cddfc75d17f4489 /il.fun
parent47ce22ee86ad9fb329585e7d9ae2052772248c95 (diff)
Mul/Div by constant transformation
Diffstat (limited to 'il.fun')
-rw-r--r--il.fun143
1 files changed, 116 insertions, 27 deletions
diff --git a/il.fun b/il.fun
index 0d45676..2db885b 100644
--- a/il.fun
+++ b/il.fun
@@ -72,6 +72,8 @@ functor IL(P: PARSER) = struct
canFold: bool
}
+ datatype funcType = FtLeaf | FtNonLeaf
+
datatype scopeInfo =
SiLoop of { breakL: label, contL: label, startL: label, endL: label } |
SiIf
@@ -80,6 +82,7 @@ functor IL(P: PARSER) = struct
fname: int,
localVars: { onStack: bool, t: P.ctype, name: int } vector,
paramNum: int,
+ ft: funcType ref,
vregs: regInfo D.t,
ops: (irIns option * (label * label) option) D.t,
@@ -92,6 +95,7 @@ functor IL(P: PARSER) = struct
name: int,
paramNum: int,
localBound: int,
+ t: funcType,
vregs: regInfo D.t,
ops: (irIns option * (label * label) option) D.t,
labels: int option D.t
@@ -126,12 +130,12 @@ functor IL(P: PARSER) = struct
fun updateLctx (Lctx ctx) = fn z =>
let
- fun from fname localVars paramNum vregs ops scopes labels =
- { fname, localVars, paramNum, vregs, ops, scopes, labels }
- fun to f { fname, localVars, paramNum, vregs, ops, scopes, labels } =
- f fname localVars paramNum vregs ops scopes labels
+ fun from fname localVars paramNum ft vregs ops scopes labels =
+ { fname, localVars, paramNum, ft, vregs, ops, scopes, labels }
+ fun to f { fname, localVars, paramNum, ft, vregs, ops, scopes, labels } =
+ f fname localVars paramNum ft vregs ops scopes labels
in
- FRU.makeUpdate6 (from, from, to) ctx (fn (a, f) => z (a, Lctx o f))
+ FRU.makeUpdate7 (from, from, to) ctx (fn (a, f) => z (a, Lctx o f))
end
fun isLocal (Lctx { localVars, ... }) id = id < Vector.length localVars
@@ -337,7 +341,7 @@ functor IL(P: PARSER) = struct
val ctx = Lctx {
fname,
- localVars, paramNum,
+ localVars, paramNum, ft = ref FtLeaf,
vregs, ops = D.create0 (),
scopes = ref [], labels
}
@@ -362,12 +366,14 @@ functor IL(P: PARSER) = struct
val getNew4 = getNewVReg VR4
val getNew8 = getNewVReg VR8
- fun newConst ctx class w =
+ fun newConst (Lctx { vregs, ... }) class w =
let
- val v = getNewVReg class ctx
- val () = ctxPutOp ctx (IrSet (v, SaConst w))
+ val w = P.extz w (if class = VR4 then 0w4 else 0w8)
+
+ val id = D.pushAndGetId vregs { class, defs = [], use = [],
+ t = RtConst w, canFold = true }
in
- v
+ id
end
fun getClass (Lctx { vregs, ... }) id = #class $ D.get vregs id
@@ -694,7 +700,10 @@ functor IL(P: PARSER) = struct
case convCast ctx (Reg vRight, rightT, P.ulong_t) of
Reg v => v
| Addr _ => raise Unreachable
- val multiplier = newConst ctx VR8 (P.sizeOfType (P.pointsTo leftT))
+
+ val mulVal = P.sizeOfType $ P.pointsTo leftT
+ val multiplier = newConst ctx VR8 mulVal
+
val vm = getNew8 ctx
val vRes = getNew8 ctx
in
@@ -868,6 +877,7 @@ functor IL(P: PARSER) = struct
val vLeft = genLogPart ctx left
val (elseLabel, endLabel) = getLabelPair ctx
+
val vRes = getNew4 ctx
val () = ctxPutOp ctx (IrJz (vLeft, elseLabel))
val () = ctxPutOp ctx (IrSet (vRes, SaConst 0w1))
@@ -877,6 +887,7 @@ functor IL(P: PARSER) = struct
val vRight = genLogPart ctx right
val vC = newConst ctx (getClass ctx vRight) 0w0
val () = ctxPutOp ctx (IrCmp (Cmpneq, vRes, vRight, vC))
+ val () = ctxPutOp ctx (IrNopLabel endLabel);
in
Reg vRes
end
@@ -889,6 +900,8 @@ functor IL(P: PARSER) = struct
val vRight = genLogPart ctx right
val vRes = getNew4 ctx
val vC = newConst ctx (getClass ctx vRight) 0w0
+
+ val () = printf `"&& labels: " I falseLabel `", " I endLabel %
in
ctxPutOp ctx (IrCmp (Cmpneq, vRes, vRight, vC));
ctxPutOp ctx (IrJmp endLabel);
@@ -1034,7 +1047,9 @@ functor IL(P: PARSER) = struct
in
vRes
end
+ val Lctx { ft, ... } = ctx
in
+ ft := FtNonLeaf;
ctxPutOp ctx (IrFcall (vRes, vFunc, args));
Reg vRes
end
@@ -1333,7 +1348,7 @@ functor IL(P: PARSER) = struct
IrNopLabel _ => dprintf `"\n" %
| _ => dprintf `" ; (l" I startL `", l" I endL `")\n" %
- val () = dprintf I idx `":" %
+ val () = dprintf Ip 4 idx `":" %
val () =
case op' of
IrNopLabel _ => ()
@@ -1454,7 +1469,7 @@ functor IL(P: PARSER) = struct
let
val c = if class = VR4 then "w4" else "w8"
- val () = dprintf `"%" Ip 4 idx `" " `c
+ val () = dprintf `"%" I idx `" " `c `"\t"
`": defs = " Plist i defs (", ", true, 0)
`", uses = " Plist i use (", ", true, 0) %
in
@@ -1492,7 +1507,7 @@ functor IL(P: PARSER) = struct
in
RtConst w
end
- | RtAddrConst (id, w) => RtAddrConst (id, w)
+ | RtAddrConst p => RtAddrConst p
| RtReg | RtRem => raise Unreachable
val () = D.set vregs vid { class, defs, use, t = v, canFold = true }
@@ -1511,9 +1526,9 @@ functor IL(P: PARSER) = struct
rev acc
else
let
- val { defs, ... } = D.get vregs vid
+ val { defs, t, ... } = D.get vregs vid
- fun addConst arg def =
+ fun addConstFromSet arg def =
let
val v =
case arg of
@@ -1524,21 +1539,23 @@ functor IL(P: PARSER) = struct
constAdd vregs ops vid v def
end
in
- case defs of
- [def] =>
+ case (t, defs) of
+ (RtReg, [def]) =>
let
- val ins = valOf o #1 $ D.get ops def
+ val ins = valOf o #1 $ D.get ops def
in
case ins of
IrSet(_, arg as SaConst _ | arg as SaAddr _) =>
let
- val () = addConst arg def
+ val () = addConstFromSet arg def
in
loop (vid + 1) (vid :: acc)
end
| _ => loop (vid + 1) acc
end
- | _ => loop (vid + 1) acc
+ | (RtReg, _) => loop (vid + 1) acc
+ | (RtConst _, _) => loop (vid + 1) (vid :: acc)
+ | _ => raise Unreachable
end
in
loop (Vector.length localVars + paramNum) []
@@ -1893,7 +1910,7 @@ functor IL(P: PARSER) = struct
if d = idx - 1 andalso rs >= Vector.length localVars + paramNum
then
let
- val () = dprintf `"fusing instruction " I d `" with " I idx %
+ val () = dprintf `"fusing instruction " I d `" with " I idx `"\n" %
val () = removeVR vregs rs
val ins = valOf o #1 $ D.get ops (idx - 1)
@@ -1949,12 +1966,80 @@ functor IL(P: PARSER) = struct
| SOME (IrJz (rs, lid)) => fuseJmpCommon C idx rs lid true
| _ => ()
- fun lowerMul C (idx, (ins, _)) = raise Unimplemented
+ fun log2 0w0 = NONE
+ | log2 w =
+ let
+ open Word
+
+ fun log 0w0 = raise Unreachable
+ | log 0w1 = 0w0
+ | log w = 0w1 + log (>> (w, 0w1))
+
+ in
+ if andb (w, w - 0w1) = 0w0 then
+ SOME $ log w
+ else
+ NONE
+ end
+
+ fun lowerMul' (C as Lctx { vregs, ops, ... }) idx (rd, rs1, rs2) =
+ let
+ val { class, ... } = D.get vregs rd
+ val { t = t1, ... } = D.get vregs rs1
+ val { t = t2, ... } = D.get vregs rs2
+
+ fun tryLower rs v =
+ case log2 v of
+ SOME 0w0 => changeIns ops idx (SOME $ IrSet (rd, SaVReg rs))
+ | SOME log =>
+ let
+ val log = newConst C class log
+ in
+ changeIns ops idx (SOME (IrShl (rd, rs, log)))
+ end
+ | NONE => ()
+ in
+ case (t1, t2) of
+ (RtConst v, _) => tryLower rs2 v
+ | (_, RtConst v) => tryLower rs1 v
+ | _ => ()
+ end
+
+ fun lowerMul C (idx, (ins, _)) =
+ case ins of
+ SOME (IrMul t) => lowerMul' C idx t
+ | SOME (IrIMul t) => lowerMul' C idx t
+ | _ => ()
+
+ fun lowerDiv (C as Lctx { vregs, ops, ... })
+ (idx, (SOME (IrDiv (rd, rs1, rs2)), _))
+ =
+ let
+ val { class, ... } = D.get vregs rd
+ val { t = t1, ... } = D.get vregs rs1
+ val { t = t2, ... } = D.get vregs rs2
+ in
+ case (t1, t2) of
+ (_, RtConst c) => (
+ case log2 c of
+ NONE => ()
+ | SOME 0w0 => changeIns ops idx (SOME $ IrSet (rd, SaVReg rs1))
+ | SOME log =>
+ let
+ val log = newConst C class log
+ in
+ changeIns ops idx (SOME $ IrShr (rd, rs1, log))
+ end
+ )
+ | _ => ()
+ end
+ | lowerDiv _ _ = ()
fun peephole (C as Lctx { ops, ... }) = (
D.appi (fuseSet C) ops;
D.appi (fuseJmpc C) ops;
- D.appi (lowerMul C) ops
+ D.appi (lowerMul C) ops;
+ D.appi (lowerDiv C) ops
)
fun removeUnusedLabels (Lctx { ops, labels, ... }) =
@@ -2055,10 +2140,14 @@ functor IL(P: PARSER) = struct
val () = printVars ctx
*)
- val Lctx { vregs, ops, labels, ... } = ctx
+ val Lctx { vregs, ops, labels, ft, ... } = ctx
in
- Fi { name, localBound = Vector.length localVars + paramNum,
- paramNum, vregs, ops, labels = D.copy labels (fn (v, _) => v) }
+ Fi {
+ name, localBound = Vector.length localVars + paramNum,
+ t = !ft,
+ paramNum, vregs, ops,
+ labels = D.copy labels (fn (v, _) => v)
+ }
end
fun createCtx ({ ext, glob, objsZI, objs, funcs, strlits }) debugFileName =