From d4c412e2d3edafe502794023d23c116623aa5626 Mon Sep 17 00:00:00 2001 From: Octaplex Date: Wed, 23 May 2018 12:05:21 -0400 Subject: [PATCH 01/57] Ignore vim configuration files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 0ba45dd349..34f9885d88 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /build/ /install/ +.nvimrc From c938d1bbd328e57caa5e071a8bc86f2ecbbcacc5 Mon Sep 17 00:00:00 2001 From: Octaplex Date: Wed, 23 May 2018 12:05:36 -0400 Subject: [PATCH 02/57] Flip semantics of `!` and `?` primitive operators Previously, the `!` family of primitive operators (`+!` etc.) was an operation that always checked for overflow, whereas the `?` family never checked for overflow. However, as a first step towards transitioning to a model wherein the `?` family is a predicate that checks for overflow, here the semantics are flipped such that the `!` family never checks for overflow, and `?` always does. --- basis-library/arrays-and-vectors/sequence.fun | 11 +- basis-library/integer/int-inf0.sml | 22 +-- basis-library/integer/int.sml | 10 +- basis-library/integer/integer.sig | 8 +- basis-library/integer/num0.sml | 8 +- basis-library/list/list.sml | 2 +- basis-library/primitive/prim-int.sml | 136 +++++++++--------- basis-library/text/char.sml | 8 +- basis-library/text/string-cvt.sml | 6 +- basis-library/util/CUtil.sml | 4 +- 10 files changed, 108 insertions(+), 107 deletions(-) diff --git a/basis-library/arrays-and-vectors/sequence.fun b/basis-library/arrays-and-vectors/sequence.fun index 9ce7af531d..97e70dba46 100644 --- a/basis-library/arrays-and-vectors/sequence.fun +++ b/basis-library/arrays-and-vectors/sequence.fun @@ -68,8 +68,9 @@ structure SeqIndex = functor Sequence (S: PRIM_SEQUENCE): SEQUENCE = struct + (* TODO what are these operators *) + val op +? = SeqIndex.+? val op +? = SeqIndex.+? - val op +! = SeqIndex.+! val op -? = SeqIndex.-? val op <= = SeqIndex.<= val op > = SeqIndex.> @@ -246,7 +247,7 @@ functor Sequence (S: PRIM_SEQUENCE): SEQUENCE = val add = if Primitive.Controls.safe then (fn (x, s) => - (s +! S.Slice.length (toSlice x)) + (s +? S.Slice.length (toSlice x)) handle Overflow => raise Size) else (fn (x, s) => s +? S.Slice.length (toSlice x)) val n = List.foldl add 0 xs @@ -276,7 +277,7 @@ functor Sequence (S: PRIM_SEQUENCE): SEQUENCE = val add = if Primitive.Controls.safe then (fn (x, s) => - (s +! sepn +! S.Slice.length (toSlice x)) + (s +? sepn +? S.Slice.length (toSlice x)) handle Overflow => raise Size) else (fn (x, s) => (s +? sepn +? S.Slice.length (toSlice x))) @@ -320,7 +321,7 @@ functor Sequence (S: PRIM_SEQUENCE): SEQUENCE = then S.Slice.unsafeSubslice (sl, len, SOME 0) else S.Slice.unsafeSubslice (sl, k, SOME (len -? k)) end handle Overflow => - (* k is positive, so behavior is specified! *) + (* k is positive, so behavior is specified? *) S.Slice.unsafeSubslice (sl, S.Slice.length sl, SOME 0) fun trimr k sl = if Primitive.Controls.safe andalso Int.< (k, 0) @@ -336,7 +337,7 @@ functor Sequence (S: PRIM_SEQUENCE): SEQUENCE = then S.Slice.unsafeSubslice (sl, 0, SOME 0) else S.Slice.unsafeSubslice (sl, 0, SOME (len -? k)) end handle Overflow => - (* k is positive, so behavior is specified! *) + (* k is positive, so behavior is specified? *) S.Slice.unsafeSubslice (sl, 0, SOME 0) fun isSubsequence (eq: 'a elt * 'a elt -> bool) (seq: 'a sequence) diff --git a/basis-library/integer/int-inf0.sml b/basis-library/integer/int-inf0.sml index a8d3528d77..c1973d061e 100644 --- a/basis-library/integer/int-inf0.sml +++ b/basis-library/integer/int-inf0.sml @@ -31,24 +31,24 @@ signature PRIM_INT_INF = val areSmall: int * int -> bool val abs: int -> int - val +! : int * int -> int val +? : int * int -> int + val +! : int * int -> int val + : int * int -> int val divMod: int * int -> int * int val div: int * int -> int val gcd: int * int -> int val mod: int * int -> int - val *! : int * int -> int val *? : int * int -> int + val *! : int * int -> int val * : int * int -> int - val ~! : int -> int val ~? : int -> int + val ~! : int -> int val ~ : int -> int val quotRem: int * int -> int * int val quot: int * int -> int val rem: int * int -> int - val -! : int * int -> int val -? : int * int -> int + val -! : int * int -> int val - : int * int -> int val < : int * int -> bool @@ -1015,9 +1015,9 @@ structure IntInf = | SOME i => i end in - val bigAdd = make (I.+!, Prim.+, S.max, 1) - val bigSub = make (I.-!, Prim.-, S.max, 1) - val bigMul = make (I.*!, Prim.*, S.+, 0) + val bigAdd = make (I.+?, Prim.+, S.max, 1) + val bigSub = make (I.-?, Prim.-, S.max, 1) + val bigMul = make (I.*?, Prim.*, S.+, 0) end fun bigNeg (arg: bigInt): bigInt = @@ -1324,24 +1324,24 @@ structure IntInf = val minInt = NONE val abs = bigAbs - val op +! = bigAdd val op +? = bigAdd + val op +! = bigAdd val op + = bigAdd val divMod = bigDivMod val op div = bigDiv val gcd = bigGcd val op mod = bigMod - val op *! = bigMul val op *? = bigMul + val op *! = bigMul val op * = bigMul - val op ~! = bigNeg val op ~? = bigNeg + val op ~! = bigNeg val op ~ = bigNeg val quotRem = bigQuotRem val quot = bigQuot val rem = bigRem - val op -! = bigSub val op -? = bigSub + val op -! = bigSub val op - = bigSub val op < = bigLT diff --git a/basis-library/integer/int.sml b/basis-library/integer/int.sml index 135e83db89..6b833a4643 100644 --- a/basis-library/integer/int.sml +++ b/basis-library/integer/int.sml @@ -80,7 +80,7 @@ in let val _ = CharArray.update - (buf, i, StringCvt.digitToChar (toInt (~? (rem (q, radix))))) + (buf, i, StringCvt.digitToChar (toInt (~! (rem (q, radix))))) val q = quot (q, radix) in if q = zero @@ -103,7 +103,7 @@ in else loop (q, Int.- (i, 1)) end in - loop (if n < zero then n else ~? n, Int.- (maxNumDigits, 1)) + loop (if n < zero then n else ~! n, Int.- (maxNumDigits, 1)) end) end @@ -138,15 +138,15 @@ fun scan radix reader s = | SOME (c, s') => case charToDigit c of NONE => SOME (zero, s) - | SOME n => finishNum (s', ~? n) + | SOME n => finishNum (s', ~! n) else case charToDigit c of NONE => SOME (zero, s) - | SOME n => finishNum (s', ~? n)) + | SOME n => finishNum (s', ~! n)) | (SOME (c, s), _) => case charToDigit c of NONE => NONE - | SOME n => finishNum (s, ~? n) + | SOME n => finishNum (s, ~! n) fun negate s = case num s of NONE => NONE diff --git a/basis-library/integer/integer.sig b/basis-library/integer/integer.sig index 4fe4c1aee5..4f2ed217db 100644 --- a/basis-library/integer/integer.sig +++ b/basis-library/integer/integer.sig @@ -58,10 +58,10 @@ signature INTEGER_EXTRA = val maxInt' : int val minInt' : int - val +? : int * int -> int - val *? : int * int -> int - val -? : int * int -> int - val ~? : int -> int + val +! : int * int -> int + val *! : int * int -> int + val -! : int * int -> int + val ~! : int -> int val andb: int * int -> int val << : int * Word.word -> int diff --git a/basis-library/integer/num0.sml b/basis-library/integer/num0.sml index 72f3c98b33..bab330379d 100644 --- a/basis-library/integer/num0.sml +++ b/basis-library/integer/num0.sml @@ -187,7 +187,7 @@ functor MkNum0 (S: MKNUM0_ARG): sig else if y < zero then if x = zero then zero - else quotUnsafe (x -? one, y) -? one + else quotUnsafe (x -! one, y) -! one else raise Div else if y < zero then if (Primitive.Controls.detectOverflow @@ -198,7 +198,7 @@ functor MkNum0 (S: MKNUM0_ARG): sig else minInt' else quotUnsafe (x, y) else if y > zero - then quotUnsafe (x +? one, y) -? one + then quotUnsafe (x +! one, y) -! one else raise Div fun x mod y = @@ -208,14 +208,14 @@ functor MkNum0 (S: MKNUM0_ARG): sig else if y < zero then if x = zero then zero - else remUnsafe (x -? one, y) +? (y + one) + else remUnsafe (x -! one, y) +! (y + one) else raise Div else if y < zero then if x = minInt' andalso y = ~one then zero else remUnsafe (x, y) else if y > zero - then remUnsafe (x +? one, y) +? (y -? one) + then remUnsafe (x +! one, y) +! (y -! one) else raise Div local diff --git a/basis-library/list/list.sml b/basis-library/list/list.sml index 57cbe88696..1a86acbfca 100644 --- a/basis-library/list/list.sml +++ b/basis-library/list/list.sml @@ -44,7 +44,7 @@ structure List: LIST = in loop (l, b) end - fun length l = foldl (fn (_, n) => n +? 1) 0 l + fun length l = foldl (fn (_, n) => n +! 1) 0 l fun appendRev (l1, l2) = foldl (op ::) l2 l1 diff --git a/basis-library/primitive/prim-int.sml b/basis-library/primitive/prim-int.sml index dd0ea8705d..43a8773c3d 100644 --- a/basis-library/primitive/prim-int.sml +++ b/basis-library/primitive/prim-int.sml @@ -17,18 +17,18 @@ signature PRIM_INTEGER = val sizeInBitsWord: Primitive.Word32.word val precision: Primitive.Int32.int option - val +! : int * int -> int val +? : int * int -> int + val +! : int * int -> int val + : int * int -> int - val *! : int * int -> int val *? : int * int -> int + val *! : int * int -> int val * : int * int -> int - val ~! : int -> int val ~? : int -> int + val ~! : int -> int val ~ : int -> int val quotUnsafe: int * int -> int - val -! : int * int -> int val -? : int * int -> int + val -! : int * int -> int val - : int * int -> int val remUnsafe: int * int -> int @@ -110,31 +110,31 @@ structure Int8 = IntWordConv.zextdFromInt32ToWord32 sizeInBits val precision = SOME sizeInBits - val +! = Exn.wrapOverflow (_prim "WordS8_addCheck": int * int -> int;) - val +? = _prim "Word8_add": int * int -> int; + val +? = Exn.wrapOverflow (_prim "WordS8_addCheck": int * int -> int;) + val +! = _prim "Word8_add": int * int -> int; val + = if Controls.detectOverflow - then +! - else +? - val *! = Exn.wrapOverflow (_prim "WordS8_mulCheck": int * int -> int;) - val *? = _prim "WordS8_mul": int * int -> int; + then +? + else +! + val *? = Exn.wrapOverflow (_prim "WordS8_mulCheck": int * int -> int;) + val *! = _prim "WordS8_mul": int * int -> int; val * = if Controls.detectOverflow - then *! - else *? - val ~! = Exn.wrapOverflow (_prim "Word8_negCheck": int -> int;) - val ~? = _prim "Word8_neg": int -> int; + then *? + else *! + val ~? = Exn.wrapOverflow (_prim "Word8_negCheck": int -> int;) + val ~! = _prim "Word8_neg": int -> int; val ~ = if Controls.detectOverflow - then ~! - else ~? + then ~? + else ~! val quotUnsafe = _prim "WordS8_quot": int * int -> int; - val -! = Exn.wrapOverflow (_prim "WordS8_subCheck": int * int -> int;) - val -? = _prim "Word8_sub": int * int -> int; + val -? = Exn.wrapOverflow (_prim "WordS8_subCheck": int * int -> int;) + val -! = _prim "Word8_sub": int * int -> int; val - = if Controls.detectOverflow - then -! - else -? + then -? + else -! val remUnsafe = _prim "WordS8_rem": int * int -> int; val < = _prim "WordS8_lt": int * int -> bool; @@ -213,31 +213,31 @@ structure Int16 = IntWordConv.zextdFromInt32ToWord32 sizeInBits val precision = SOME sizeInBits - val +! = Exn.wrapOverflow (_prim "WordS16_addCheck": int * int -> int;) - val +? = _prim "Word16_add": int * int -> int; + val +? = Exn.wrapOverflow (_prim "WordS16_addCheck": int * int -> int;) + val +! = _prim "Word16_add": int * int -> int; val + = if Controls.detectOverflow - then +! - else +? - val *! = Exn.wrapOverflow (_prim "WordS16_mulCheck": int * int -> int;) - val *? = _prim "WordS16_mul": int * int -> int; + then +? + else +! + val *? = Exn.wrapOverflow (_prim "WordS16_mulCheck": int * int -> int;) + val *! = _prim "WordS16_mul": int * int -> int; val * = if Controls.detectOverflow - then *! - else *? - val ~! = Exn.wrapOverflow (_prim "Word16_negCheck": int -> int;) - val ~? = _prim "Word16_neg": int -> int; + then *? + else *! + val ~? = Exn.wrapOverflow (_prim "Word16_negCheck": int -> int;) + val ~! = _prim "Word16_neg": int -> int; val ~ = if Controls.detectOverflow - then ~! - else ~? + then ~? + else ~! val quotUnsafe = _prim "WordS16_quot": int * int -> int; - val -! = Exn.wrapOverflow (_prim "WordS16_subCheck": int * int -> int;) - val -? = _prim "Word16_sub": int * int -> int; + val -? = Exn.wrapOverflow (_prim "WordS16_subCheck": int * int -> int;) + val -! = _prim "Word16_sub": int * int -> int; val - = if Controls.detectOverflow - then -! - else -? + then -? + else -! val remUnsafe = _prim "WordS16_rem": int * int -> int; val < = _prim "WordS16_lt": int * int -> bool; @@ -380,31 +380,31 @@ structure Int32 = IntWordConv.zextdFromInt32ToWord32 sizeInBits val precision = SOME sizeInBits - val +! = Exn.wrapOverflow (_prim "WordS32_addCheck": int * int -> int;) - val +? = _prim "Word32_add": int * int -> int; + val +? = Exn.wrapOverflow (_prim "WordS32_addCheck": int * int -> int;) + val +! = _prim "Word32_add": int * int -> int; val + = if Controls.detectOverflow - then +! - else +? - val *! = Exn.wrapOverflow (_prim "WordS32_mulCheck": int * int -> int;) - val *? = _prim "WordS32_mul": int * int -> int; + then +? + else +! + val *? = Exn.wrapOverflow (_prim "WordS32_mulCheck": int * int -> int;) + val *! = _prim "WordS32_mul": int * int -> int; val * = if Controls.detectOverflow - then *! - else *? - val ~! = Exn.wrapOverflow (_prim "Word32_negCheck": int -> int;) - val ~? = _prim "Word32_neg": int -> int; + then *? + else *! + val ~? = Exn.wrapOverflow (_prim "Word32_negCheck": int -> int;) + val ~! = _prim "Word32_neg": int -> int; val ~ = if Controls.detectOverflow - then ~! - else ~? + then ~? + else ~! val quotUnsafe = _prim "WordS32_quot": int * int -> int; - val -! = Exn.wrapOverflow (_prim "WordS32_subCheck": int * int -> int;) - val -? = _prim "Word32_sub": int * int -> int; + val -? = Exn.wrapOverflow (_prim "WordS32_subCheck": int * int -> int;) + val -! = _prim "Word32_sub": int * int -> int; val - = if Controls.detectOverflow - then -! - else -? + then -? + else -! val remUnsafe = _prim "WordS32_rem": int * int -> int; val < = _prim "WordS32_lt": int * int -> bool; @@ -427,31 +427,31 @@ structure Int64 = IntWordConv.zextdFromInt32ToWord32 sizeInBits val precision = SOME sizeInBits - val +! = Exn.wrapOverflow (_prim "WordS64_addCheck": int * int -> int;) - val +? = _prim "Word64_add": int * int -> int; + val +? = Exn.wrapOverflow (_prim "WordS64_addCheck": int * int -> int;) + val +! = _prim "Word64_add": int * int -> int; val + = if Controls.detectOverflow - then +! - else +? - val *! = Exn.wrapOverflow (_prim "WordS64_mulCheck": int * int -> int;) - val *? = _prim "WordS64_mul": int * int -> int; + then +? + else +! + val *? = Exn.wrapOverflow (_prim "WordS64_mulCheck": int * int -> int;) + val *! = _prim "WordS64_mul": int * int -> int; val * = if Controls.detectOverflow - then *! - else *? - val ~! = Exn.wrapOverflow (_prim "Word64_negCheck": int -> int;) - val ~? = _prim "Word64_neg": int -> int; + then *? + else *! + val ~? = Exn.wrapOverflow (_prim "Word64_negCheck": int -> int;) + val ~! = _prim "Word64_neg": int -> int; val ~ = if Controls.detectOverflow - then ~! - else ~? + then ~? + else ~! val quotUnsafe = _prim "WordS64_quot": int * int -> int; - val -! = Exn.wrapOverflow (_prim "WordS64_subCheck": int * int -> int;) - val -? = _prim "Word64_sub": int * int -> int; + val -? = Exn.wrapOverflow (_prim "WordS64_subCheck": int * int -> int;) + val -! = _prim "Word64_sub": int * int -> int; val - = if Controls.detectOverflow - then -! - else -? + then -? + else -! val remUnsafe = _prim "WordS64_rem": int * int -> int; val < = _prim "WordS64_lt": int * int -> bool; diff --git a/basis-library/text/char.sml b/basis-library/text/char.sml index 7f27eeff2a..01ddfed71a 100644 --- a/basis-library/text/char.sml +++ b/basis-library/text/char.sml @@ -103,7 +103,7 @@ functor CharFn(Arg : CHAR_ARG) local fun make (test, diff) c = - if test c then chrUnsafe (Int.+? (ord c, diff)) else c + if test c then chrUnsafe (Int.+! (ord c, diff)) else c val diff = Int.- (ord lA, ord la) in val toLower = make (isUpper, Int.~ diff) @@ -115,7 +115,7 @@ functor CharFn(Arg : CHAR_ARG) NONE => NONE | SOME (c, state) => if Char.<= (#"@", c) andalso Char.<= (c, #"_") - then SOME (chr (Int.-? (Char.ord c, Char.ord #"@")), state) + then SOME (chr (Int.-! (Char.ord c, Char.ord #"@")), state) else NONE fun formatChar reader state = @@ -274,7 +274,7 @@ functor CharFn(Arg : CHAR_ARG) fun padLeft (s: String.string, n: int): String.string = let val m = String.size s - val diff = Int.-? (n, m) + val diff = Int.-! (n, m) in if Int.> (diff, 0) then String.concat [String.new (diff, #"0"), s] else if diff = 0 @@ -314,7 +314,7 @@ functor CharFn(Arg : CHAR_ARG) then String.concat ["\\^", String.new (1, Char.chrUnsafe - (Int.+? (ord, 64 (* #"@" *) )))] + (Int.+! (ord, 64 (* #"@" *) )))] else if Int.< (ord, 256) then String.concat ["\\", padLeft (Int.fmt StringCvt.DEC ord, 3)] diff --git a/basis-library/text/string-cvt.sml b/basis-library/text/string-cvt.sml index 71489794f7..bf643d0412 100644 --- a/basis-library/text/string-cvt.sml +++ b/basis-library/text/string-cvt.sml @@ -38,7 +38,7 @@ structure StringCvt: STRING_CVT_EXTRA = in if n >= i then s - else f (s, String.vector (i -? n, c)) + else f (s, String.vector (i -! n, c)) end in val padLeft = pad (fn (s, pad) => String.^ (pad, s)) @@ -82,7 +82,7 @@ structure StringCvt: STRING_CVT_EXTRA = fun range (add: int, cmin: char, cmax: char): char -> int option = let val min = Char.ord cmin in fn c => if Char.<= (cmin, c) andalso Char.<= (c, cmax) - then SOME (add +? Char.ord c -? min) + then SOME (add +! Char.ord c -! min) else NONE end @@ -146,7 +146,7 @@ structure StringCvt: STRING_CVT_EXTRA = | SOME (c, state) => case charToDigit radix c of NONE => NONE - | SOME n => digits (radix, max -? 1, n) reader state + | SOME n => digits (radix, max -! 1, n) reader state fun digitsExact (radix, num) reader state = let val r = radixToInt radix diff --git a/basis-library/util/CUtil.sml b/basis-library/util/CUtil.sml index 0e4dfb0c93..18e8cf845a 100644 --- a/basis-library/util/CUtil.sml +++ b/basis-library/util/CUtil.sml @@ -17,7 +17,7 @@ structure CUtil: C_UTIL = fun loop i = if term (sub (p, i)) then i - else loop (i +? 1) + else loop (i +! 1) in loop 0 end @@ -96,7 +96,7 @@ structure CUtil: C_UTIL = let val (a, _) = Array.unfoldi - (1 +? List.length l, l, fn (_, l) => + (1 +! List.length l, l, fn (_, l) => case l of [] => (NullString.empty, l) | s::l => (NullString.nullTerm s, l)) From 8b3cef190cff802dc3604ae5d1ea8f5bfc029254 Mon Sep 17 00:00:00 2001 From: Octaplex Date: Wed, 23 May 2018 13:38:32 -0400 Subject: [PATCH 03/57] Introduce `$` operators and make `?` predicates This change introduces a new family of `$` operators, which always check their arguments for overflow and raise an appropriate exception. The `?` family of operators is changed to detect overflow (returning a `Bool`), and the `$` family is defined in terms of the corresponding `?` and `!` operators. Previous uses of `?` in the basis library are also corrected to use the new system. --- basis-library/arrays-and-vectors/array2.sml | 38 +++---- basis-library/arrays-and-vectors/sequence.fun | 51 +++++---- .../arrays-and-vectors/sequence0.sml | 100 ++++++++--------- basis-library/integer/int-inf0.sml | 6 +- basis-library/primitive/prim-int.sml | 102 +++++++++++------- basis-library/top-level/infixes-overflow.sml | 4 +- basis-library/top-level/infixes-unsafe.sml | 4 +- 7 files changed, 162 insertions(+), 143 deletions(-) diff --git a/basis-library/arrays-and-vectors/array2.sml b/basis-library/arrays-and-vectors/array2.sml index a8a91e5826..3ffb268a09 100644 --- a/basis-library/arrays-and-vectors/array2.sml +++ b/basis-library/arrays-and-vectors/array2.sml @@ -10,11 +10,11 @@ structure Array2 : ARRAY2 = struct - val op +? = SeqIndex.+? + val op +$ = SeqIndex.+$ val op + = SeqIndex.+ - val op -? = SeqIndex.-? + val op -$ = SeqIndex.-$ val op - = SeqIndex.- - val op *? = SeqIndex.*? + val op *$ = SeqIndex.*$ val op * = SeqIndex.* val op < = SeqIndex.< val op <= = SeqIndex.<= @@ -66,12 +66,12 @@ structure Array2 : ARRAY2 = handle Overflow => raise Subscript in if (start < 0 orelse num < 0 - orelse start +? num > max) + orelse start +$ num > max) then raise Subscript - else (start, start +? num) + else (start, start +$ num) end else (SeqIndex.fromIntUnsafe start, - SeqIndex.fromIntUnsafe start +? num) + SeqIndex.fromIntUnsafe start +$ num) fun checkSliceMax (start: int, num: int option, max: SeqIndex.int): SeqIndex.int * SeqIndex.int = @@ -147,7 +147,7 @@ structure Array2 : ARRAY2 = cols = 0} fun unsafeSpot' ({cols, ...}: 'a array, r, c) = - r *? cols +? c + r *$ cols +$ c fun spot' (a as {rows, cols, ...}: 'a array, r, c) = if Primitive.Controls.safe andalso (geu (r, rows) orelse geu (c, cols)) @@ -197,13 +197,13 @@ structure Array2 : ARRAY2 = List.foldl (fn (row: 'a list, i) => let - val max = i +? cols' + val max = i +$ cols' val i' = List.foldl (fn (x: 'a, i) => (if i >= max then raise Size else (Primitive.Array.unsafeUpdate (array, i, x) - ; i +? 1))) + ; i +$ 1))) i row in if i' = max then i' @@ -218,7 +218,7 @@ structure Array2 : ARRAY2 = if Primitive.Controls.safe andalso geu (r, rows) then raise Subscript else - ArraySlice.vector (Primitive.Array.Slice.slice (array, r *? cols, SOME cols)) + ArraySlice.vector (Primitive.Array.Slice.slice (array, r *$ cols, SOME cols)) fun row (a, r) = if Primitive.Controls.safe then let @@ -257,9 +257,9 @@ structure Array2 : ARRAY2 = else let fun loopCol (c, b) = if c >= stopCol then b - else loopCol (c +? 1, f (r, c, sub' (base, r, c), b)) + else loopCol (c +$ 1, f (r, c, sub' (base, r, c), b)) in - loopRow (r +? 1, loopCol (startCol, b)) + loopRow (r +$ 1, loopCol (startCol, b)) end in loopRow (startRow, b) @@ -271,9 +271,9 @@ structure Array2 : ARRAY2 = else let fun loopRow (r, b) = if r >= stopRow then b - else loopRow (r +? 1, f (r, c, sub' (base, r, c), b)) + else loopRow (r +$ 1, f (r, c, sub' (base, r, c), b)) in - loopCol (c +? 1, loopRow (startRow, b)) + loopCol (c +$ 1, loopRow (startRow, b)) end in loopCol (startCol, b) @@ -310,8 +310,8 @@ structure Array2 : ARRAY2 = dst, dst_row, dst_col} = let val {startRow, stopRow, startCol, stopCol} = checkRegion src - val nrows = stopRow -? startRow - val ncols = stopCol -? startCol + val nrows = stopRow -$ startRow + val ncols = stopCol -$ startCol val {startRow = dst_row, startCol = dst_col, ...} = checkRegion' {base = dst, row = dst_row, col = dst_col, nrows = SOME nrows, @@ -330,13 +330,13 @@ structure Array2 : ARRAY2 = if i < start then () else (f i; loop (i - 1)) - in loop (stop -? 1) + in loop (stop -$ 1) end val forRows = if startRow <= dst_row then forDown else forUp val forCols = if startCol <= dst_col then forUp else forDown in forRows (0, nrows, fn r => forCols (0, ncols, fn c => - unsafeUpdate' (dst, dst_row +? r, dst_col +? c, - unsafeSub' (base, startRow +? r, startCol +? c)))) + unsafeUpdate' (dst, dst_row +$ r, dst_col +$ c, + unsafeSub' (base, startRow +$ r, startCol +$ c)))) end end diff --git a/basis-library/arrays-and-vectors/sequence.fun b/basis-library/arrays-and-vectors/sequence.fun index 97e70dba46..8adb237c8a 100644 --- a/basis-library/arrays-and-vectors/sequence.fun +++ b/basis-library/arrays-and-vectors/sequence.fun @@ -68,10 +68,9 @@ structure SeqIndex = functor Sequence (S: PRIM_SEQUENCE): SEQUENCE = struct - (* TODO what are these operators *) - val op +? = SeqIndex.+? - val op +? = SeqIndex.+? - val op -? = SeqIndex.-? + val op +$ = SeqIndex.+$ + val op +! = SeqIndex.+! + val op -$ = SeqIndex.-$ val op <= = SeqIndex.<= val op > = SeqIndex.> val op >= = SeqIndex.>= @@ -247,9 +246,9 @@ functor Sequence (S: PRIM_SEQUENCE): SEQUENCE = val add = if Primitive.Controls.safe then (fn (x, s) => - (s +? S.Slice.length (toSlice x)) + (s +$ S.Slice.length (toSlice x)) handle Overflow => raise Size) - else (fn (x, s) => s +? S.Slice.length (toSlice x)) + else (fn (x, s) => s +! S.Slice.length (toSlice x)) val n = List.foldl add 0 xs val a = Primitive.Array.alloc n fun loop (di, xs) = @@ -259,7 +258,7 @@ functor Sequence (S: PRIM_SEQUENCE): SEQUENCE = let val sl = toSlice x in S.Slice.unsafeCopy {dst = a, di = di, src = sl} - ; loop (di +? S.Slice.length sl, xs) + ; loop (di +$ S.Slice.length sl, xs) end in loop (0, xs) @@ -277,10 +276,10 @@ functor Sequence (S: PRIM_SEQUENCE): SEQUENCE = val add = if Primitive.Controls.safe then (fn (x, s) => - (s +? sepn +? S.Slice.length (toSlice x)) + (s +$ sepn +$ S.Slice.length (toSlice x)) handle Overflow => raise Size) else (fn (x, s) => - (s +? sepn +? S.Slice.length (toSlice x))) + (s +$ sepn +$ S.Slice.length (toSlice x))) val n = List.foldl add (S.Slice.length (toSlice x)) xs val a = Primitive.Array.alloc n fun loop (di, xs) = @@ -297,9 +296,9 @@ functor Sequence (S: PRIM_SEQUENCE): SEQUENCE = let val sl = toSlice x val _ = S.Slice.unsafeCopy {dst = a, di = di, src = sl} - val di = di +? S.Slice.length sl + val di = di +$ S.Slice.length sl val _ = S.Slice.unsafeCopy {dst = a, di = di, src = sep} - val di = di +? sepn + val di = di +$ sepn in loop (di, xs) end @@ -319,7 +318,7 @@ functor Sequence (S: PRIM_SEQUENCE): SEQUENCE = in if SeqIndex.> (k, len) then S.Slice.unsafeSubslice (sl, len, SOME 0) - else S.Slice.unsafeSubslice (sl, k, SOME (len -? k)) + else S.Slice.unsafeSubslice (sl, k, SOME (len -$ k)) end handle Overflow => (* k is positive, so behavior is specified? *) S.Slice.unsafeSubslice (sl, S.Slice.length sl, SOME 0) @@ -335,7 +334,7 @@ functor Sequence (S: PRIM_SEQUENCE): SEQUENCE = in if SeqIndex.> (k, len) then S.Slice.unsafeSubslice (sl, 0, SOME 0) - else S.Slice.unsafeSubslice (sl, 0, SOME (len -? k)) + else S.Slice.unsafeSubslice (sl, 0, SOME (len -$ k)) end handle Overflow => (* k is positive, so behavior is specified? *) S.Slice.unsafeSubslice (sl, 0, SOME 0) @@ -348,16 +347,16 @@ functor Sequence (S: PRIM_SEQUENCE): SEQUENCE = in if n <= n' then let - val n'' = n' -? n + val n'' = n' -$ n fun loop (i, j) = if i > n'' then false else if j >= n then true else if eq (S.unsafeSub (seq, j), - S.Slice.unsafeSub (sl, i +? j)) - then loop (i, j +? 1) - else loop (i +? 1, 0) + S.Slice.unsafeSub (sl, i +$ j)) + then loop (i, j +$ 1) + else loop (i +$ 1, 0) in loop (0, 0) end @@ -377,7 +376,7 @@ functor Sequence (S: PRIM_SEQUENCE): SEQUENCE = then true else if eq (S.unsafeSub (seq, j), S.Slice.unsafeSub (sl, j)) - then loop (j +? 1) + then loop (j +$ 1) else false in loop (0) @@ -393,13 +392,13 @@ functor Sequence (S: PRIM_SEQUENCE): SEQUENCE = in if n <= n' then let - val n'' = n' -? n + val n'' = n' -$ n fun loop (j) = if j >= n then true else if eq (S.unsafeSub (seq, j), - S.Slice.unsafeSub (sl, n'' +? j)) - then loop (j +? 1) + S.Slice.unsafeSub (sl, n'' +$ j)) + then loop (j +$ 1) else false in loop (0) @@ -424,14 +423,14 @@ functor Sequence (S: PRIM_SEQUENCE): SEQUENCE = fun make finish p sl = let val (seq, start, len) = S.Slice.base sl - val max = start +? len + val max = start +$ len fun loop (i, start, sls) = if i >= max then List.rev (finish (seq, start, i, sls)) else if p (S.unsafeSub (seq, i)) - then loop (i +? 1, i +? 1, finish (seq, start, i, sls)) - else loop (i +? 1, start, sls) + then loop (i +$ 1, i +$ 1, finish (seq, start, i, sls)) + else loop (i +$ 1, start, sls) in loop (start, start, []) end in @@ -442,14 +441,14 @@ functor Sequence (S: PRIM_SEQUENCE): SEQUENCE = else (fromSlice (S.Slice.unsafeSlice - (seq, start, SOME (stop -? start)))) + (seq, start, SOME (stop -$ start)))) :: sls) p sl fun fieldsGen fromSlice p sl = make (fn (seq, start, stop, sls) => (fromSlice (S.Slice.unsafeSlice - (seq, start, SOME (stop -? start)))) + (seq, start, SOME (stop -$ start)))) :: sls) p sl end diff --git a/basis-library/arrays-and-vectors/sequence0.sml b/basis-library/arrays-and-vectors/sequence0.sml index e5f01dc200..90c39c035f 100644 --- a/basis-library/arrays-and-vectors/sequence0.sml +++ b/basis-library/arrays-and-vectors/sequence0.sml @@ -27,9 +27,9 @@ functor PrimSequence (S: sig struct structure Array = Primitive.Array - val op +? = SeqIndex.+? + val op +$ = SeqIndex.+$ val op + = SeqIndex.+ - val op -? = SeqIndex.-? + val op -$ = SeqIndex.-$ val op < = SeqIndex.< val op <= = SeqIndex.<= val op > = SeqIndex.> @@ -130,7 +130,7 @@ functor PrimSequence (S: sig val (x, b) = f (i, b) val () = Array.updateUnsafe (a, i, x) in - loop (i +? 1, b) + loop (i +$ 1, b) end val b = loop (0, b) in @@ -154,13 +154,13 @@ functor PrimSequence (S: sig fun length (T {len, ...}) = len fun unsafeSub (T {seq, start, ...}, i) = - S.subUnsafe (seq, start +? i) + S.subUnsafe (seq, start +$ i) fun sub (sl as T {len, ...}, i) = if Primitive.Controls.safe andalso geu (i, len) then raise Subscript else unsafeSub (sl, i) fun unsafeUpdate (T {seq, start, ...}, i, x) = - S.updateUnsafe (seq, start +? i, x) + S.updateUnsafe (seq, start +$ i, x) fun update (sl as T {len, ...}, i, x) = if Primitive.Controls.safe andalso geu (i, len) then raise Subscript @@ -168,7 +168,7 @@ functor PrimSequence (S: sig fun uninitIsNop (T {seq, ...}) = S.uninitIsNop seq fun unsafeUninit (T {seq, start, ...}, i) = - S.uninitUnsafe (seq, start +? i) + S.uninitUnsafe (seq, start +$ i) fun uninit (sl as T {len, ...}, i) = if Primitive.Controls.safe andalso geu (i, len) then raise Subscript @@ -179,15 +179,15 @@ functor PrimSequence (S: sig len: SeqIndex.int, overlap: unit -> bool} = let - fun move i = Array.updateUnsafe (dst, di +? i, S.subUnsafe (src, si +? i)) - val len = len -? 1 + fun move i = Array.updateUnsafe (dst, di +$ i, S.subUnsafe (src, si +$ i)) + val len = len -$ 1 in if overlap () then let fun loop i = if i < 0 then () - else (move i; loop (i -? 1)) + else (move i; loop (i -$ 1)) in loop len end @@ -195,7 +195,7 @@ functor PrimSequence (S: sig fun loop i = if i > len then () - else (move i; loop (i +? 1)) + else (move i; loop (i +$ 1)) in loop 0 end @@ -222,13 +222,13 @@ functor PrimSequence (S: sig src = T {seq = src, start = si, len}} = if Primitive.Controls.safe andalso (gtu (di, Array.length dst) - orelse gtu (di +? len, Array.length dst)) + orelse gtu (di +$ len, Array.length dst)) then raise Subscript else let fun overlap () = S.sameArray (dst, src) andalso si < di - andalso di <= si +? len + andalso di <= si +$ len in maybeSmallCopy {dst = dst, di = di, src = src, si = si, @@ -240,9 +240,9 @@ functor PrimSequence (S: sig T {seq = seq, start = 0, len = S.length seq} fun unsafeSubslice (T {seq, start, len}, start', len') = T {seq = seq, - start = start +? start', + start = start +$ start', len = (case len' of - NONE => len -? start' + NONE => len -$ start' | SOME len' => len')} fun unsafeSlice (seq, start, len) = unsafeSubslice (full seq, start, len) @@ -253,15 +253,15 @@ functor PrimSequence (S: sig andalso gtu (start', len) then raise Subscript else T {seq = seq, - start = start +? start', - len = len -? start'} + start = start +$ start', + len = len -$ start'} | SOME len' => if Primitive.Controls.safe andalso (gtu (start', len) - orelse gtu (len', len -? start')) + orelse gtu (len', len -$ start')) then raise Subscript else T {seq = seq, - start = start +? start', + start = start +$ start', len = len'} fun slice (seq: 'a sequence, start, len) = subslice (full seq, start, len) @@ -273,26 +273,26 @@ functor PrimSequence (S: sig then NONE else SOME (S.subUnsafe (seq, start), T {seq = seq, - start = start +? 1, - len = len -? 1}) + start = start +$ 1, + len = len -$ 1}) fun foldli f b (T {seq, start, len}) = let val min = start - val len = len -? 1 - val max = start +? len + val len = len -$ 1 + val max = start +$ len fun loop (i, b) = if i > max then b - else loop (i +? 1, f (i -? min, S.subUnsafe (seq, i), b)) + else loop (i +$ 1, f (i -$ min, S.subUnsafe (seq, i), b)) in loop (min, b) end fun foldri f b (T {seq, start, len}) = let val min = start - val len = len -? 1 - val max = start +? len + val len = len -$ 1 + val max = start +$ len fun loop (i, b) = if i < min then b - else loop (i -? 1, f (i -? min, S.subUnsafe (seq, i), b)) + else loop (i -$ 1, f (i -$ min, S.subUnsafe (seq, i), b)) in loop (max, b) end local @@ -304,20 +304,20 @@ functor PrimSequence (S: sig fun appi f sl = foldli (fn (i, x, ()) => f (i, x)) () sl fun app f sl = appi (f o #2) sl fun mapi f (T {seq, start, len}) = - tabulate (len, fn i => f (i, S.subUnsafe (seq, start +? i))) + tabulate (len, fn i => f (i, S.subUnsafe (seq, start +$ i))) fun map f sl = mapi (f o #2) sl fun findi p (T {seq, start, len}) = let val min = start - val len = len -? 1 - val max = start +? len + val len = len -$ 1 + val max = start +$ len fun loop i = if i > max then NONE - else let val z = (i -? min, S.subUnsafe (seq, i)) + else let val z = (i -$ min, S.subUnsafe (seq, i)) in if p z then SOME z - else loop (i +? 1) + else loop (i +$ 1) end in loop min end @@ -337,8 +337,8 @@ functor PrimSequence (S: sig let val min1 = start1 val min2 = start2 - val max1 = start1 +? len1 - val max2 = start2 +? len2 + val max1 = start1 +$ len1 + val max2 = start2 +$ len2 fun loop (i, j) = case (i >= max1, j >= max2) of (true, true) => EQUAL @@ -347,7 +347,7 @@ functor PrimSequence (S: sig | (false, false) => (case cmp (S.subUnsafe (seq1, i), S.subUnsafe (seq2, j)) of - EQUAL => loop (i +? 1, j +? 1) + EQUAL => loop (i +$ 1, j +$ 1) | ans => ans) in loop (min1, min2) end @@ -369,7 +369,7 @@ functor PrimSequence (S: sig let val (seq1, start1, len1) = base sl1 val (seq2, start2, len2) = base sl2 - val n = len1 +? len2 + val n = len1 +$ len2 val a = arrayAlloc n in S.copyUnsafe (a, 0, seq1, start1, len1) @@ -377,16 +377,16 @@ functor PrimSequence (S: sig ; S.fromArray a end fun split (T {seq, start, len}, i) = - (unsafeSlice (seq, start, SOME (i -? start)), - unsafeSlice (seq, i, SOME (len -? (i -? start)))) + (unsafeSlice (seq, start, SOME (i -$ start)), + unsafeSlice (seq, i, SOME (len -$ (i -$ start)))) fun splitl f (sl as T {seq, start, len}) = let - val stop = start +? len + val stop = start +$ len fun loop i = if i >= stop then i else if f (S.subUnsafe (seq, i)) - then loop (i +? 1) + then loop (i +$ 1) else i in split (sl, loop start) end @@ -396,15 +396,15 @@ functor PrimSequence (S: sig if i < start then start else if f (S.subUnsafe (seq, i)) - then loop (i -? 1) - else i +? 1 - in split (sl, loop (start +? len -? 1)) + then loop (i -$ 1) + else i +$ 1 + in split (sl, loop (start +$ len -$ 1)) end fun splitAt (T {seq, start, len}, i) = if Primitive.Controls.safe andalso gtu (i, len) then raise Subscript else (unsafeSlice (seq, start, SOME i), - unsafeSlice (seq, start +? i, SOME (len -? i))) + unsafeSlice (seq, start +$ i, SOME (len -$ i))) fun dropl p s = #2 (splitl p s) fun dropr p s = #1 (splitr p s) fun takel p s = #1 (splitl p s) @@ -414,19 +414,19 @@ functor PrimSequence (S: sig (sl as T {seq, start, len}) = let val len' = S.length seq' - val max = start +? len -? len' +? 1 + val max = start +$ len -$ len' +$ 1 (* loop returns the index of the front of the suffix. *) fun loop i = if i >= max - then start +? len + then start +$ len else let fun loop' j = if j >= len' then i - else if eq (S.subUnsafe (seq, i +? j), + else if eq (S.subUnsafe (seq, i +$ j), S.subUnsafe (seq', j)) - then loop' (j +? 1) - else loop (i +? 1) + then loop' (j +$ 1) + else loop (i +$ 1) in loop' 0 end in split (sl, loop start) @@ -435,9 +435,9 @@ functor PrimSequence (S: sig (T {seq, start, ...}, T {seq = seq', start = start', len = len'}) = if Primitive.Controls.safe andalso - (not (eq (seq, seq')) orelse start' +? len' < start) + (not (eq (seq, seq')) orelse start' +$ len' < start) then raise Span - else unsafeSlice (seq, start, SOME ((start' +? len') -? start)) + else unsafeSlice (seq, start, SOME ((start' +$ len') -$ start)) end local diff --git a/basis-library/integer/int-inf0.sml b/basis-library/integer/int-inf0.sml index c1973d061e..331f2bb74e 100644 --- a/basis-library/integer/int-inf0.sml +++ b/basis-library/integer/int-inf0.sml @@ -1015,9 +1015,9 @@ structure IntInf = | SOME i => i end in - val bigAdd = make (I.+?, Prim.+, S.max, 1) - val bigSub = make (I.-?, Prim.-, S.max, 1) - val bigMul = make (I.*?, Prim.*, S.+, 0) + val bigAdd = make (I.+$, Prim.+, S.max, 1) + val bigSub = make (I.-$, Prim.-, S.max, 1) + val bigMul = make (I.*$, Prim.*, S.+, 0) end fun bigNeg (arg: bigInt): bigInt = diff --git a/basis-library/primitive/prim-int.sml b/basis-library/primitive/prim-int.sml index 43a8773c3d..4acce2c9ef 100644 --- a/basis-library/primitive/prim-int.sml +++ b/basis-library/primitive/prim-int.sml @@ -17,18 +17,22 @@ signature PRIM_INTEGER = val sizeInBitsWord: Primitive.Word32.word val precision: Primitive.Int32.int option - val +? : int * int -> int + val +? : int * int -> bool val +! : int * int -> int + val +$ : int * int -> int val + : int * int -> int - val *? : int * int -> int + val *? : int * int -> bool val *! : int * int -> int + val *$ : int * int -> int val * : int * int -> int - val ~? : int -> int + val ~? : int -> bool val ~! : int -> int + val ~$ : int -> int val ~ : int -> int val quotUnsafe: int * int -> int - val -? : int * int -> int + val -? : int * int -> bool val -! : int * int -> int + val -$ : int * int -> int val - : int * int -> int val remUnsafe: int * int -> int @@ -110,30 +114,34 @@ structure Int8 = IntWordConv.zextdFromInt32ToWord32 sizeInBits val precision = SOME sizeInBits - val +? = Exn.wrapOverflow (_prim "WordS8_addCheck": int * int -> int;) + val +? = _prim "WordS8_addCheck": int * int -> bool; val +! = _prim "Word8_add": int * int -> int; + val +$ = fn (x, y) => if +? (x,y) then raise Overflow else +! (x,y) val + = if Controls.detectOverflow - then +? + then +$ else +! - val *? = Exn.wrapOverflow (_prim "WordS8_mulCheck": int * int -> int;) + val *? = _prim "WordS8_mulCheck": int * int -> bool; val *! = _prim "WordS8_mul": int * int -> int; + val *$ = fn (x, y) => if *? (x,y) then raise Overflow else *! (x,y) val * = if Controls.detectOverflow - then *? + then *$ else *! - val ~? = Exn.wrapOverflow (_prim "Word8_negCheck": int -> int;) - val ~! = _prim "Word8_neg": int -> int; + val ~? = _prim "Word8_negCheck": int -> bool; + val ~! = _prim "Word8_neg": int -> int; + val ~$ = fn x => if ~? x then raise Overflow else ~! x val ~ = if Controls.detectOverflow - then ~? + then ~$ else ~! val quotUnsafe = _prim "WordS8_quot": int * int -> int; - val -? = Exn.wrapOverflow (_prim "WordS8_subCheck": int * int -> int;) + val -? = _prim "WordS8_subCheck": int * int -> bool; val -! = _prim "Word8_sub": int * int -> int; + val -$ = fn (x, y) => if -? (x,y) then raise Overflow else -! (x,y) val - = if Controls.detectOverflow - then -? + then -$ else -! val remUnsafe = _prim "WordS8_rem": int * int -> int; @@ -213,30 +221,34 @@ structure Int16 = IntWordConv.zextdFromInt32ToWord32 sizeInBits val precision = SOME sizeInBits - val +? = Exn.wrapOverflow (_prim "WordS16_addCheck": int * int -> int;) + val +? = _prim "WordS16_addCheck": int * int -> bool; val +! = _prim "Word16_add": int * int -> int; + val +$ = fn (x, y) => if +? (x,y) then raise Overflow else +! (x,y) val + = if Controls.detectOverflow - then +? + then +$ else +! - val *? = Exn.wrapOverflow (_prim "WordS16_mulCheck": int * int -> int;) + val *? = _prim "WordS16_mulCheck": int * int -> bool; val *! = _prim "WordS16_mul": int * int -> int; + val *$ = fn (x, y) => if *? (x,y) then raise Overflow else *! (x,y) val * = if Controls.detectOverflow - then *? + then *$ else *! - val ~? = Exn.wrapOverflow (_prim "Word16_negCheck": int -> int;) - val ~! = _prim "Word16_neg": int -> int; + val ~? = _prim "Word16_negCheck": int -> bool; + val ~! = _prim "Word16_neg": int -> int; + val ~$ = fn x => if ~? x then raise Overflow else ~! x val ~ = if Controls.detectOverflow - then ~? + then ~$ else ~! val quotUnsafe = _prim "WordS16_quot": int * int -> int; - val -? = Exn.wrapOverflow (_prim "WordS16_subCheck": int * int -> int;) + val -? = _prim "WordS16_subCheck": int * int -> bool; val -! = _prim "Word16_sub": int * int -> int; + val -$ = fn (x, y) => if -? (x,y) then raise Overflow else -! (x,y) val - = if Controls.detectOverflow - then -? + then -$ else -! val remUnsafe = _prim "WordS16_rem": int * int -> int; @@ -380,30 +392,34 @@ structure Int32 = IntWordConv.zextdFromInt32ToWord32 sizeInBits val precision = SOME sizeInBits - val +? = Exn.wrapOverflow (_prim "WordS32_addCheck": int * int -> int;) + val +? = _prim "WordS32_addCheck": int * int -> bool; val +! = _prim "Word32_add": int * int -> int; + val +$ = fn (x, y) => if +? (x,y) then raise Overflow else +! (x,y) val + = if Controls.detectOverflow - then +? + then +$ else +! - val *? = Exn.wrapOverflow (_prim "WordS32_mulCheck": int * int -> int;) + val *? = _prim "WordS32_mulCheck": int * int -> bool; val *! = _prim "WordS32_mul": int * int -> int; + val *$ = fn (x, y) => if *? (x,y) then raise Overflow else *! (x,y) val * = if Controls.detectOverflow - then *? + then *$ else *! - val ~? = Exn.wrapOverflow (_prim "Word32_negCheck": int -> int;) - val ~! = _prim "Word32_neg": int -> int; + val ~? = _prim "Word32_negCheck": int -> bool; + val ~! = _prim "Word32_neg": int -> int; + val ~$ = fn x => if ~? x then raise Overflow else ~! x val ~ = if Controls.detectOverflow - then ~? + then ~$ else ~! val quotUnsafe = _prim "WordS32_quot": int * int -> int; - val -? = Exn.wrapOverflow (_prim "WordS32_subCheck": int * int -> int;) + val -? = _prim "WordS32_subCheck": int * int -> bool; val -! = _prim "Word32_sub": int * int -> int; + val -$ = fn (x, y) => if -? (x,y) then raise Overflow else -! (x,y) val - = if Controls.detectOverflow - then -? + then -$ else -! val remUnsafe = _prim "WordS32_rem": int * int -> int; @@ -427,30 +443,34 @@ structure Int64 = IntWordConv.zextdFromInt32ToWord32 sizeInBits val precision = SOME sizeInBits - val +? = Exn.wrapOverflow (_prim "WordS64_addCheck": int * int -> int;) + val +? = _prim "WordS64_addCheck": int * int -> bool; val +! = _prim "Word64_add": int * int -> int; + val +$ = fn (x, y) => if +? (x,y) then raise Overflow else +! (x,y) val + = if Controls.detectOverflow - then +? + then +$ else +! - val *? = Exn.wrapOverflow (_prim "WordS64_mulCheck": int * int -> int;) + val *? = _prim "WordS64_mulCheck": int * int -> bool; val *! = _prim "WordS64_mul": int * int -> int; + val *$ = fn (x, y) => if *? (x,y) then raise Overflow else *! (x,y) val * = if Controls.detectOverflow - then *? + then *$ else *! - val ~? = Exn.wrapOverflow (_prim "Word64_negCheck": int -> int;) - val ~! = _prim "Word64_neg": int -> int; + val ~? = _prim "Word64_negCheck": int -> bool; + val ~! = _prim "Word64_neg": int -> int; + val ~$ = fn x => if ~? x then raise Overflow else ~! x val ~ = if Controls.detectOverflow - then ~? + then ~$ else ~! val quotUnsafe = _prim "WordS64_quot": int * int -> int; - val -? = Exn.wrapOverflow (_prim "WordS64_subCheck": int * int -> int;) + val -? = _prim "WordS64_subCheck": int * int -> bool; val -! = _prim "Word64_sub": int * int -> int; + val -$ = fn (x, y) => if -? (x,y) then raise Overflow else -! (x,y) val - = - if Controls.detectOverflow - then -? + if Controls.detectOverflow + then -$ else -! val remUnsafe = _prim "WordS64_rem": int * int -> int; diff --git a/basis-library/top-level/infixes-overflow.sml b/basis-library/top-level/infixes-overflow.sml index f34650b7dc..d1b389735f 100644 --- a/basis-library/top-level/infixes-overflow.sml +++ b/basis-library/top-level/infixes-overflow.sml @@ -6,5 +6,5 @@ * See the file MLton-LICENSE for details. *) -infix 7 *! -infix 6 +! -! +infix 7 *? *$ +infix 6 +? +$ -? -$ diff --git a/basis-library/top-level/infixes-unsafe.sml b/basis-library/top-level/infixes-unsafe.sml index 14a50df55d..be6e2dbcb7 100644 --- a/basis-library/top-level/infixes-unsafe.sml +++ b/basis-library/top-level/infixes-unsafe.sml @@ -6,5 +6,5 @@ * See the file MLton-LICENSE for details. *) -infix 7 *? -infix 6 +? -? +infix 7 *! +infix 6 +! -! From cb4f3fc84f79f6211e579bd50222ba6c98f89cba Mon Sep 17 00:00:00 2001 From: Daman Morris Date: Thu, 31 May 2018 10:45:54 -0400 Subject: [PATCH 04/57] Make new primitives backwards-compatible Previously the old primitives were simply deleted; this commit introduces a compile-time switch (`MLton.newOverflow`) to switch between the old and new systems. This should allow for easier development and eventual integration of the new primitives, which can be incrementally implemented on the backend while keeping the old ones intact. --- basis-library/primitive/prim-int.sml | 212 +++++++++++++++------------ basis-library/primitive/prim1.sml | 3 + 2 files changed, 119 insertions(+), 96 deletions(-) diff --git a/basis-library/primitive/prim-int.sml b/basis-library/primitive/prim-int.sml index 4acce2c9ef..f68f00d8da 100644 --- a/basis-library/primitive/prim-int.sml +++ b/basis-library/primitive/prim-int.sml @@ -114,35 +114,40 @@ structure Int8 = IntWordConv.zextdFromInt32ToWord32 sizeInBits val precision = SOME sizeInBits - val +? = _prim "WordS8_addCheck": int * int -> bool; + val +? = _prim "WordS8_addCheckP": int * int -> bool; val +! = _prim "Word8_add": int * int -> int; - val +$ = fn (x, y) => if +? (x,y) then raise Overflow else +! (x,y) - val + = - if Controls.detectOverflow - then +$ - else +! - val *? = _prim "WordS8_mulCheck": int * int -> bool; + val +$ = if Controls.newOverflow then + Exn.mkOverflow (+!, +?) + else + Exn.wrapOverflow (_prim "WordS8_addCheck": int * int -> int;) + val + = if Controls.detectOverflow then +$ else +! + + val *? = _prim "WordS8_mulCheckP": int * int -> bool; val *! = _prim "WordS8_mul": int * int -> int; - val *$ = fn (x, y) => if *? (x,y) then raise Overflow else *! (x,y) - val * = - if Controls.detectOverflow - then *$ - else *! - val ~? = _prim "Word8_negCheck": int -> bool; + val *$ = if Controls.newOverflow then + Exn.mkOverflow ( *!, *? ) + else + Exn.wrapOverflow (_prim "WordS8_mulCheck": int * int -> int;) + val * = if Controls.detectOverflow then *$ else *! + + val ~? = _prim "Word8_negCheckP": int -> bool; val ~! = _prim "Word8_neg": int -> int; - val ~$ = fn x => if ~? x then raise Overflow else ~! x - val ~ = - if Controls.detectOverflow - then ~$ - else ~! + val ~$ = if Controls.newOverflow then + Exn.mkOverflow (~!, ~?) + else + Exn.wrapOverflow (_prim "Word8_negCheck": int -> int;) + val ~ = if Controls.detectOverflow then ~$ else ~! + val quotUnsafe = _prim "WordS8_quot": int * int -> int; - val -? = _prim "WordS8_subCheck": int * int -> bool; + + val -? = _prim "WordS8_subCheckP": int * int -> bool; val -! = _prim "Word8_sub": int * int -> int; - val -$ = fn (x, y) => if -? (x,y) then raise Overflow else -! (x,y) - val - = - if Controls.detectOverflow - then -$ - else -! + val -$ = if Controls.newOverflow then + Exn.mkOverflow (-!, -?) + else + Exn.wrapOverflow (_prim "WordS8_subCheck": int * int -> int;) + val - = if Controls.detectOverflow then -$ else -! + val remUnsafe = _prim "WordS8_rem": int * int -> int; val < = _prim "WordS8_lt": int * int -> bool; @@ -221,35 +226,40 @@ structure Int16 = IntWordConv.zextdFromInt32ToWord32 sizeInBits val precision = SOME sizeInBits - val +? = _prim "WordS16_addCheck": int * int -> bool; + val +? = _prim "WordS16_addCheckP": int * int -> bool; val +! = _prim "Word16_add": int * int -> int; - val +$ = fn (x, y) => if +? (x,y) then raise Overflow else +! (x,y) - val + = - if Controls.detectOverflow - then +$ - else +! - val *? = _prim "WordS16_mulCheck": int * int -> bool; + val +$ = if Controls.newOverflow then + Exn.mkOverflow (+!, +?) + else + Exn.wrapOverflow (_prim "WordS16_addCheck": int * int -> int;) + val + = if Controls.detectOverflow then +$ else +! + + val *? = _prim "WordS16_mulCheckP": int * int -> bool; val *! = _prim "WordS16_mul": int * int -> int; - val *$ = fn (x, y) => if *? (x,y) then raise Overflow else *! (x,y) - val * = - if Controls.detectOverflow - then *$ - else *! - val ~? = _prim "Word16_negCheck": int -> bool; + val *$ = if Controls.newOverflow then + Exn.mkOverflow ( *!, *? ) + else + Exn.wrapOverflow (_prim "WordS16_mulCheck": int * int -> int;) + val * = if Controls.detectOverflow then *$ else *! + + val ~? = _prim "Word16_negCheckP": int -> bool; val ~! = _prim "Word16_neg": int -> int; - val ~$ = fn x => if ~? x then raise Overflow else ~! x - val ~ = - if Controls.detectOverflow - then ~$ - else ~! + val ~$ = if Controls.newOverflow then + Exn.mkOverflow (~!, ~?) + else + Exn.wrapOverflow (_prim "Word16_negCheck": int -> int;) + val ~ = if Controls.detectOverflow then ~$ else ~! + val quotUnsafe = _prim "WordS16_quot": int * int -> int; - val -? = _prim "WordS16_subCheck": int * int -> bool; + + val -? = _prim "WordS16_subCheckP": int * int -> bool; val -! = _prim "Word16_sub": int * int -> int; - val -$ = fn (x, y) => if -? (x,y) then raise Overflow else -! (x,y) - val - = - if Controls.detectOverflow - then -$ - else -! + val -$ = if Controls.newOverflow then + Exn.mkOverflow (-!, -?) + else + Exn.wrapOverflow (_prim "WordS16_subCheck": int * int -> int;) + val - = if Controls.detectOverflow then -$ else -! + val remUnsafe = _prim "WordS16_rem": int * int -> int; val < = _prim "WordS16_lt": int * int -> bool; @@ -392,35 +402,40 @@ structure Int32 = IntWordConv.zextdFromInt32ToWord32 sizeInBits val precision = SOME sizeInBits - val +? = _prim "WordS32_addCheck": int * int -> bool; + val +? = _prim "WordS32_addCheckP": int * int -> bool; val +! = _prim "Word32_add": int * int -> int; - val +$ = fn (x, y) => if +? (x,y) then raise Overflow else +! (x,y) - val + = - if Controls.detectOverflow - then +$ - else +! - val *? = _prim "WordS32_mulCheck": int * int -> bool; + val +$ = if Controls.newOverflow then + Exn.mkOverflow (+!, +?) + else + Exn.wrapOverflow (_prim "WordS32_addCheck": int * int -> int;) + val + = if Controls.detectOverflow then +$ else +! + + val *? = _prim "WordS32_mulCheckP": int * int -> bool; val *! = _prim "WordS32_mul": int * int -> int; - val *$ = fn (x, y) => if *? (x,y) then raise Overflow else *! (x,y) - val * = - if Controls.detectOverflow - then *$ - else *! - val ~? = _prim "Word32_negCheck": int -> bool; + val *$ = if Controls.newOverflow then + Exn.mkOverflow ( *!, *? ) + else + Exn.wrapOverflow (_prim "WordS32_mulCheck": int * int -> int;) + val * = if Controls.detectOverflow then *$ else *! + + val ~? = _prim "Word32_negCheckP": int -> bool; val ~! = _prim "Word32_neg": int -> int; - val ~$ = fn x => if ~? x then raise Overflow else ~! x - val ~ = - if Controls.detectOverflow - then ~$ - else ~! + val ~$ = if Controls.newOverflow then + Exn.mkOverflow (~!, ~?) + else + Exn.wrapOverflow (_prim "Word32_negCheck": int -> int;) + val ~ = if Controls.detectOverflow then ~$ else ~! + val quotUnsafe = _prim "WordS32_quot": int * int -> int; - val -? = _prim "WordS32_subCheck": int * int -> bool; + + val -? = _prim "WordS32_subCheckP": int * int -> bool; val -! = _prim "Word32_sub": int * int -> int; - val -$ = fn (x, y) => if -? (x,y) then raise Overflow else -! (x,y) - val - = - if Controls.detectOverflow - then -$ - else -! + val -$ = if Controls.newOverflow then + Exn.mkOverflow (-!, -?) + else + Exn.wrapOverflow (_prim "WordS32_subCheck": int * int -> int;) + val - = if Controls.detectOverflow then -$ else -! + val remUnsafe = _prim "WordS32_rem": int * int -> int; val < = _prim "WordS32_lt": int * int -> bool; @@ -443,35 +458,40 @@ structure Int64 = IntWordConv.zextdFromInt32ToWord32 sizeInBits val precision = SOME sizeInBits - val +? = _prim "WordS64_addCheck": int * int -> bool; + val +? = _prim "WordS64_addCheckP": int * int -> bool; val +! = _prim "Word64_add": int * int -> int; - val +$ = fn (x, y) => if +? (x,y) then raise Overflow else +! (x,y) - val + = - if Controls.detectOverflow - then +$ - else +! - val *? = _prim "WordS64_mulCheck": int * int -> bool; + val +$ = if Controls.newOverflow then + Exn.mkOverflow (+!, +?) + else + Exn.wrapOverflow (_prim "WordS64_addCheck": int * int -> int;) + val + = if Controls.detectOverflow then +$ else +! + + val *? = _prim "WordS64_mulCheckP": int * int -> bool; val *! = _prim "WordS64_mul": int * int -> int; - val *$ = fn (x, y) => if *? (x,y) then raise Overflow else *! (x,y) - val * = - if Controls.detectOverflow - then *$ - else *! - val ~? = _prim "Word64_negCheck": int -> bool; + val *$ = if Controls.newOverflow then + Exn.mkOverflow ( *!, *? ) + else + Exn.wrapOverflow (_prim "WordS64_mulCheck": int * int -> int;) + val * = if Controls.detectOverflow then *$ else *! + + val ~? = _prim "Word64_negCheckP": int -> bool; val ~! = _prim "Word64_neg": int -> int; - val ~$ = fn x => if ~? x then raise Overflow else ~! x - val ~ = - if Controls.detectOverflow - then ~$ - else ~! + val ~$ = if Controls.newOverflow then + Exn.mkOverflow (~!, ~?) + else + Exn.wrapOverflow (_prim "Word64_negCheck": int -> int;) + val ~ = if Controls.detectOverflow then ~$ else ~! + val quotUnsafe = _prim "WordS64_quot": int * int -> int; - val -? = _prim "WordS64_subCheck": int * int -> bool; + + val -? = _prim "WordS64_subCheckP": int * int -> bool; val -! = _prim "Word64_sub": int * int -> int; - val -$ = fn (x, y) => if -? (x,y) then raise Overflow else -! (x,y) - val - = - if Controls.detectOverflow - then -$ - else -! + val -$ = if Controls.newOverflow then + Exn.mkOverflow (-!, -?) + else + Exn.wrapOverflow (_prim "WordS64_subCheck": int * int -> int;) + val - = if Controls.detectOverflow then -$ else -! + val remUnsafe = _prim "WordS64_rem": int * int -> int; val < = _prim "WordS64_lt": int * int -> bool; diff --git a/basis-library/primitive/prim1.sml b/basis-library/primitive/prim1.sml index 9541d5002d..18251dc73f 100644 --- a/basis-library/primitive/prim1.sml +++ b/basis-library/primitive/prim1.sml @@ -32,6 +32,7 @@ structure Controls = struct val debug = _command_line_const "MLton.debug": bool = false; val detectOverflow = _command_line_const "MLton.detectOverflow": bool = true; + val newOverflow = _command_line_const "MLton.newOverflow": bool = false; val safe = _command_line_const "MLton.safe": bool = true; val bufSize = _command_line_const "TextIO.bufSize": Int32.int = 4096; end @@ -52,6 +53,8 @@ structure Exn = exception Span exception Subscript + val mkOverflow: ('a -> 'b) * ('a -> bool) -> ('a -> 'b) = + fn (!, ?) => fn a => if ? a then raise Overflow else ! a val wrapOverflow: ('a -> 'b) -> ('a -> 'b) = fn f => fn a => f a handle PrimOverflow => raise Overflow end From f9e1cb671f4d5c27578eb14c7a6c5a98f81508b4 Mon Sep 17 00:00:00 2001 From: Daman Morris Date: Thu, 31 May 2018 10:49:27 -0400 Subject: [PATCH 05/57] Add minimal backend support for new primitives --- basis-library/primitive/basis-ffi.sml | 48 ++++++++++++------------- mlton/atoms/prim.fun | 38 +++++++++++++++++++- mlton/atoms/prim.sig | 4 +++ mlton/backend/ssa-to-rssa.fun | 17 +++++++++ mlton/codegen/c-codegen/c-codegen.fun | 8 +++++ runtime/basis-ffi.h | 48 ++++++++++++------------- runtime/basis/Word/Word-check.h | 52 +++++++++++++-------------- runtime/gen/basis-ffi.def | 48 ++++++++++++------------- runtime/gen/basis-ffi.h | 48 ++++++++++++------------- runtime/gen/basis-ffi.sml | 48 ++++++++++++------------- 10 files changed, 212 insertions(+), 147 deletions(-) diff --git a/basis-library/primitive/basis-ffi.sml b/basis-library/primitive/basis-ffi.sml index 53a3b4413a..cd74bcd57e 100644 --- a/basis-library/primitive/basis-ffi.sml +++ b/basis-library/primitive/basis-ffi.sml @@ -1207,7 +1207,7 @@ val xorb = _import "Word8_xorb" private : Word8.t * Word8.t -> Word8.t; end structure WordS16 = struct -val addCheckOverflows = _import "WordS16_addCheckOverflows" private : Int16.t * Int16.t -> Bool.t; +val addCheckP = _import "WordS16_addCheckP" private : Int16.t * Int16.t -> Bool.t; val extdToWord16 = _import "WordS16_extdToWord16" private : Int16.t -> Word16.t; val extdToWord32 = _import "WordS16_extdToWord32" private : Int16.t -> Word32.t; val extdToWord64 = _import "WordS16_extdToWord64" private : Int16.t -> Word64.t; @@ -1217,18 +1217,18 @@ val gt = _import "WordS16_gt" private : Int16.t * Int16.t -> Bool.t; val le = _import "WordS16_le" private : Int16.t * Int16.t -> Bool.t; val lt = _import "WordS16_lt" private : Int16.t * Int16.t -> Bool.t; val mul = _import "WordS16_mul" private : Int16.t * Int16.t -> Int16.t; -val mulCheckOverflows = _import "WordS16_mulCheckOverflows" private : Int16.t * Int16.t -> Bool.t; -val negCheckOverflows = _import "WordS16_negCheckOverflows" private : Int16.t -> Bool.t; +val mulCheckP = _import "WordS16_mulCheckP" private : Int16.t * Int16.t -> Bool.t; +val negCheckP = _import "WordS16_negCheckP" private : Int16.t -> Bool.t; val quot = _import "WordS16_quot" private : Int16.t * Int16.t -> Int16.t; val rem = _import "WordS16_rem" private : Int16.t * Int16.t -> Int16.t; val rndToReal32 = _import "WordS16_rndToReal32" private : Int16.t -> Real32.t; val rndToReal64 = _import "WordS16_rndToReal64" private : Int16.t -> Real64.t; val rshift = _import "WordS16_rshift" private : Int16.t * Word32.t -> Int16.t; -val subCheckOverflows = _import "WordS16_subCheckOverflows" private : Int16.t * Int16.t -> Bool.t; +val subCheckP = _import "WordS16_subCheckP" private : Int16.t * Int16.t -> Bool.t; end structure WordS32 = struct -val addCheckOverflows = _import "WordS32_addCheckOverflows" private : Int32.t * Int32.t -> Bool.t; +val addCheckP = _import "WordS32_addCheckP" private : Int32.t * Int32.t -> Bool.t; val extdToWord16 = _import "WordS32_extdToWord16" private : Int32.t -> Word16.t; val extdToWord32 = _import "WordS32_extdToWord32" private : Int32.t -> Word32.t; val extdToWord64 = _import "WordS32_extdToWord64" private : Int32.t -> Word64.t; @@ -1238,18 +1238,18 @@ val gt = _import "WordS32_gt" private : Int32.t * Int32.t -> Bool.t; val le = _import "WordS32_le" private : Int32.t * Int32.t -> Bool.t; val lt = _import "WordS32_lt" private : Int32.t * Int32.t -> Bool.t; val mul = _import "WordS32_mul" private : Int32.t * Int32.t -> Int32.t; -val mulCheckOverflows = _import "WordS32_mulCheckOverflows" private : Int32.t * Int32.t -> Bool.t; -val negCheckOverflows = _import "WordS32_negCheckOverflows" private : Int32.t -> Bool.t; +val mulCheckP = _import "WordS32_mulCheckP" private : Int32.t * Int32.t -> Bool.t; +val negCheckP = _import "WordS32_negCheckP" private : Int32.t -> Bool.t; val quot = _import "WordS32_quot" private : Int32.t * Int32.t -> Int32.t; val rem = _import "WordS32_rem" private : Int32.t * Int32.t -> Int32.t; val rndToReal32 = _import "WordS32_rndToReal32" private : Int32.t -> Real32.t; val rndToReal64 = _import "WordS32_rndToReal64" private : Int32.t -> Real64.t; val rshift = _import "WordS32_rshift" private : Int32.t * Word32.t -> Int32.t; -val subCheckOverflows = _import "WordS32_subCheckOverflows" private : Int32.t * Int32.t -> Bool.t; +val subCheckP = _import "WordS32_subCheckP" private : Int32.t * Int32.t -> Bool.t; end structure WordS64 = struct -val addCheckOverflows = _import "WordS64_addCheckOverflows" private : Int64.t * Int64.t -> Bool.t; +val addCheckP = _import "WordS64_addCheckP" private : Int64.t * Int64.t -> Bool.t; val extdToWord16 = _import "WordS64_extdToWord16" private : Int64.t -> Word16.t; val extdToWord32 = _import "WordS64_extdToWord32" private : Int64.t -> Word32.t; val extdToWord64 = _import "WordS64_extdToWord64" private : Int64.t -> Word64.t; @@ -1259,18 +1259,18 @@ val gt = _import "WordS64_gt" private : Int64.t * Int64.t -> Bool.t; val le = _import "WordS64_le" private : Int64.t * Int64.t -> Bool.t; val lt = _import "WordS64_lt" private : Int64.t * Int64.t -> Bool.t; val mul = _import "WordS64_mul" private : Int64.t * Int64.t -> Int64.t; -val mulCheckOverflows = _import "WordS64_mulCheckOverflows" private : Int64.t * Int64.t -> Bool.t; -val negCheckOverflows = _import "WordS64_negCheckOverflows" private : Int64.t -> Bool.t; +val mulCheckP = _import "WordS64_mulCheckP" private : Int64.t * Int64.t -> Bool.t; +val negCheckP = _import "WordS64_negCheckP" private : Int64.t -> Bool.t; val quot = _import "WordS64_quot" private : Int64.t * Int64.t -> Int64.t; val rem = _import "WordS64_rem" private : Int64.t * Int64.t -> Int64.t; val rndToReal32 = _import "WordS64_rndToReal32" private : Int64.t -> Real32.t; val rndToReal64 = _import "WordS64_rndToReal64" private : Int64.t -> Real64.t; val rshift = _import "WordS64_rshift" private : Int64.t * Word32.t -> Int64.t; -val subCheckOverflows = _import "WordS64_subCheckOverflows" private : Int64.t * Int64.t -> Bool.t; +val subCheckP = _import "WordS64_subCheckP" private : Int64.t * Int64.t -> Bool.t; end structure WordS8 = struct -val addCheckOverflows = _import "WordS8_addCheckOverflows" private : Int8.t * Int8.t -> Bool.t; +val addCheckP = _import "WordS8_addCheckP" private : Int8.t * Int8.t -> Bool.t; val extdToWord16 = _import "WordS8_extdToWord16" private : Int8.t -> Word16.t; val extdToWord32 = _import "WordS8_extdToWord32" private : Int8.t -> Word32.t; val extdToWord64 = _import "WordS8_extdToWord64" private : Int8.t -> Word64.t; @@ -1280,18 +1280,18 @@ val gt = _import "WordS8_gt" private : Int8.t * Int8.t -> Bool.t; val le = _import "WordS8_le" private : Int8.t * Int8.t -> Bool.t; val lt = _import "WordS8_lt" private : Int8.t * Int8.t -> Bool.t; val mul = _import "WordS8_mul" private : Int8.t * Int8.t -> Int8.t; -val mulCheckOverflows = _import "WordS8_mulCheckOverflows" private : Int8.t * Int8.t -> Bool.t; -val negCheckOverflows = _import "WordS8_negCheckOverflows" private : Int8.t -> Bool.t; +val mulCheckP = _import "WordS8_mulCheckP" private : Int8.t * Int8.t -> Bool.t; +val negCheckP = _import "WordS8_negCheckP" private : Int8.t -> Bool.t; val quot = _import "WordS8_quot" private : Int8.t * Int8.t -> Int8.t; val rem = _import "WordS8_rem" private : Int8.t * Int8.t -> Int8.t; val rndToReal32 = _import "WordS8_rndToReal32" private : Int8.t -> Real32.t; val rndToReal64 = _import "WordS8_rndToReal64" private : Int8.t -> Real64.t; val rshift = _import "WordS8_rshift" private : Int8.t * Word32.t -> Int8.t; -val subCheckOverflows = _import "WordS8_subCheckOverflows" private : Int8.t * Int8.t -> Bool.t; +val subCheckP = _import "WordS8_subCheckP" private : Int8.t * Int8.t -> Bool.t; end structure WordU16 = struct -val addCheckOverflows = _import "WordU16_addCheckOverflows" private : Word16.t * Word16.t -> Bool.t; +val addCheckP = _import "WordU16_addCheckP" private : Word16.t * Word16.t -> Bool.t; val extdToWord16 = _import "WordU16_extdToWord16" private : Word16.t -> Word16.t; val extdToWord32 = _import "WordU16_extdToWord32" private : Word16.t -> Word32.t; val extdToWord64 = _import "WordU16_extdToWord64" private : Word16.t -> Word64.t; @@ -1301,7 +1301,7 @@ val gt = _import "WordU16_gt" private : Word16.t * Word16.t -> Bool.t; val le = _import "WordU16_le" private : Word16.t * Word16.t -> Bool.t; val lt = _import "WordU16_lt" private : Word16.t * Word16.t -> Bool.t; val mul = _import "WordU16_mul" private : Word16.t * Word16.t -> Word16.t; -val mulCheckOverflows = _import "WordU16_mulCheckOverflows" private : Word16.t * Word16.t -> Bool.t; +val mulCheckP = _import "WordU16_mulCheckP" private : Word16.t * Word16.t -> Bool.t; val quot = _import "WordU16_quot" private : Word16.t * Word16.t -> Word16.t; val rem = _import "WordU16_rem" private : Word16.t * Word16.t -> Word16.t; val rndToReal32 = _import "WordU16_rndToReal32" private : Word16.t -> Real32.t; @@ -1310,7 +1310,7 @@ val rshift = _import "WordU16_rshift" private : Word16.t * Word32.t -> Word16.t; end structure WordU32 = struct -val addCheckOverflows = _import "WordU32_addCheckOverflows" private : Word32.t * Word32.t -> Bool.t; +val addCheckP = _import "WordU32_addCheckP" private : Word32.t * Word32.t -> Bool.t; val extdToWord16 = _import "WordU32_extdToWord16" private : Word32.t -> Word16.t; val extdToWord32 = _import "WordU32_extdToWord32" private : Word32.t -> Word32.t; val extdToWord64 = _import "WordU32_extdToWord64" private : Word32.t -> Word64.t; @@ -1320,7 +1320,7 @@ val gt = _import "WordU32_gt" private : Word32.t * Word32.t -> Bool.t; val le = _import "WordU32_le" private : Word32.t * Word32.t -> Bool.t; val lt = _import "WordU32_lt" private : Word32.t * Word32.t -> Bool.t; val mul = _import "WordU32_mul" private : Word32.t * Word32.t -> Word32.t; -val mulCheckOverflows = _import "WordU32_mulCheckOverflows" private : Word32.t * Word32.t -> Bool.t; +val mulCheckP = _import "WordU32_mulCheckP" private : Word32.t * Word32.t -> Bool.t; val quot = _import "WordU32_quot" private : Word32.t * Word32.t -> Word32.t; val rem = _import "WordU32_rem" private : Word32.t * Word32.t -> Word32.t; val rndToReal32 = _import "WordU32_rndToReal32" private : Word32.t -> Real32.t; @@ -1329,7 +1329,7 @@ val rshift = _import "WordU32_rshift" private : Word32.t * Word32.t -> Word32.t; end structure WordU64 = struct -val addCheckOverflows = _import "WordU64_addCheckOverflows" private : Word64.t * Word64.t -> Bool.t; +val addCheckP = _import "WordU64_addCheckP" private : Word64.t * Word64.t -> Bool.t; val extdToWord16 = _import "WordU64_extdToWord16" private : Word64.t -> Word16.t; val extdToWord32 = _import "WordU64_extdToWord32" private : Word64.t -> Word32.t; val extdToWord64 = _import "WordU64_extdToWord64" private : Word64.t -> Word64.t; @@ -1339,7 +1339,7 @@ val gt = _import "WordU64_gt" private : Word64.t * Word64.t -> Bool.t; val le = _import "WordU64_le" private : Word64.t * Word64.t -> Bool.t; val lt = _import "WordU64_lt" private : Word64.t * Word64.t -> Bool.t; val mul = _import "WordU64_mul" private : Word64.t * Word64.t -> Word64.t; -val mulCheckOverflows = _import "WordU64_mulCheckOverflows" private : Word64.t * Word64.t -> Bool.t; +val mulCheckP = _import "WordU64_mulCheckP" private : Word64.t * Word64.t -> Bool.t; val quot = _import "WordU64_quot" private : Word64.t * Word64.t -> Word64.t; val rem = _import "WordU64_rem" private : Word64.t * Word64.t -> Word64.t; val rndToReal32 = _import "WordU64_rndToReal32" private : Word64.t -> Real32.t; @@ -1348,7 +1348,7 @@ val rshift = _import "WordU64_rshift" private : Word64.t * Word32.t -> Word64.t; end structure WordU8 = struct -val addCheckOverflows = _import "WordU8_addCheckOverflows" private : Word8.t * Word8.t -> Bool.t; +val addCheckP = _import "WordU8_addCheckP" private : Word8.t * Word8.t -> Bool.t; val extdToWord16 = _import "WordU8_extdToWord16" private : Word8.t -> Word16.t; val extdToWord32 = _import "WordU8_extdToWord32" private : Word8.t -> Word32.t; val extdToWord64 = _import "WordU8_extdToWord64" private : Word8.t -> Word64.t; @@ -1358,7 +1358,7 @@ val gt = _import "WordU8_gt" private : Word8.t * Word8.t -> Bool.t; val le = _import "WordU8_le" private : Word8.t * Word8.t -> Bool.t; val lt = _import "WordU8_lt" private : Word8.t * Word8.t -> Bool.t; val mul = _import "WordU8_mul" private : Word8.t * Word8.t -> Word8.t; -val mulCheckOverflows = _import "WordU8_mulCheckOverflows" private : Word8.t * Word8.t -> Bool.t; +val mulCheckP = _import "WordU8_mulCheckP" private : Word8.t * Word8.t -> Bool.t; val quot = _import "WordU8_quot" private : Word8.t * Word8.t -> Word8.t; val rem = _import "WordU8_rem" private : Word8.t * Word8.t -> Word8.t; val rndToReal32 = _import "WordU8_rndToReal32" private : Word8.t -> Real32.t; diff --git a/mlton/atoms/prim.fun b/mlton/atoms/prim.fun index 9b63b18247..b3e55782be 100644 --- a/mlton/atoms/prim.fun +++ b/mlton/atoms/prim.fun @@ -167,6 +167,7 @@ datatype 'a t = | Weak_new (* to rssa (as runtime C fn) *) | Word_add of WordSize.t (* codegen *) | Word_addCheck of WordSize.t * {signed: bool} (* codegen *) + | Word_addCheckP of WordSize.t * {signed: bool} (* codegen *) | Word_andb of WordSize.t (* codegen *) | Word_castToReal of WordSize.t * RealSize.t (* codegen *) | Word_equal of WordSize.t (* codegen *) @@ -175,8 +176,10 @@ datatype 'a t = | Word_lt of WordSize.t * {signed: bool} (* codegen *) | Word_mul of WordSize.t * {signed: bool} (* codegen *) | Word_mulCheck of WordSize.t * {signed: bool} (* codegen *) + | Word_mulCheckP of WordSize.t * {signed: bool} (* codegen *) | Word_neg of WordSize.t (* codegen *) | Word_negCheck of WordSize.t (* codegen *) + | Word_negCheckP of WordSize.t (* codegen *) | Word_notb of WordSize.t (* codegen *) | Word_orb of WordSize.t (* codegen *) | Word_quot of WordSize.t * {signed: bool} (* codegen *) @@ -187,6 +190,7 @@ datatype 'a t = | Word_rshift of WordSize.t * {signed: bool} (* codegen *) | Word_sub of WordSize.t (* codegen *) | Word_subCheck of WordSize.t * {signed: bool} (* codegen *) + | Word_subCheckP of WordSize.t * {signed: bool} (* codegen *) | Word_toIntInf (* to rssa *) | Word_xorb of WordSize.t (* codegen *) | WordVector_toIntInf (* to rssa *) @@ -344,6 +348,7 @@ fun toString (n: 'a t): string = | WordVector_toIntInf => "WordVector_toIntInf" | Word_add s => word (s, "add") | Word_addCheck (s, sg) => wordS (s, sg, "addCheck") + | Word_addCheckP (s, sg) => wordS (s, sg, "addCheckP") | Word_andb s => word (s, "andb") | Word_castToReal (s1, s2) => cast (wordC, realC, s1, s2) | Word_equal s => word (s, "equal") @@ -352,8 +357,10 @@ fun toString (n: 'a t): string = | Word_lt (s, sg) => wordS (s, sg, "lt") | Word_mul (s, sg) => wordS (s, sg, "mul") | Word_mulCheck (s, sg) => wordS (s, sg, "mulCheck") + | Word_mulCheckP (s, sg) => wordS (s, sg, "mulCheckP") | Word_neg s => word (s, "neg") | Word_negCheck s => word (s, "negCheck") + | Word_negCheckP s => word (s, "negCheckP") | Word_notb s => word (s, "notb") | Word_orb s => word (s, "orb") | Word_quot (s, sg) => wordS (s, sg, "quot") @@ -364,6 +371,7 @@ fun toString (n: 'a t): string = | Word_rshift (s, sg) => wordS (s, sg, "rshift") | Word_sub s => word (s, "sub") | Word_subCheck (s, sg) => wordS (s, sg, "subCheck") + | Word_subCheckP (s, sg) => wordS (s, sg, "subCheckP") | Word_toIntInf => "Word_toIntInf" | Word_xorb s => word (s, "xorb") | World_save => "World_save" @@ -671,6 +679,7 @@ val map: 'a t * ('a -> 'b) -> 'b t = | Weak_new => Weak_new | Word_add z => Word_add z | Word_addCheck z => Word_addCheck z + | Word_addCheckP z => Word_addCheckP z | Word_andb z => Word_andb z | Word_castToReal z => Word_castToReal z | Word_equal z => Word_equal z @@ -679,8 +688,10 @@ val map: 'a t * ('a -> 'b) -> 'b t = | Word_lt z => Word_lt z | Word_mul z => Word_mul z | Word_mulCheck z => Word_mulCheck z + | Word_mulCheckP z => Word_mulCheckP z | Word_neg z => Word_neg z | Word_negCheck z => Word_negCheck z + | Word_negCheckP z => Word_negCheckP z | Word_notb z => Word_notb z | Word_orb z => Word_orb z | Word_quot z => Word_quot z @@ -691,6 +702,7 @@ val map: 'a t * ('a -> 'b) -> 'b t = | Word_rshift z => Word_rshift z | Word_sub z => Word_sub z | Word_subCheck z => Word_subCheck z + | Word_subCheckP z => Word_subCheckP z | Word_toIntInf => Word_toIntInf | Word_xorb z => Word_xorb z | WordVector_toIntInf => WordVector_toIntInf @@ -767,6 +779,7 @@ val vectorLength = Vector_length val vectorSub = Vector_sub val wordAdd = Word_add val wordAddCheck = Word_addCheck +val wordAddCheckP = Word_addCheckP val wordAndb = Word_andb val wordCastToReal = Word_castToReal val wordEqual = Word_equal @@ -776,6 +789,7 @@ val wordLt = Word_lt val wordMul = Word_mul val wordNeg = Word_neg val wordNegCheck = Word_negCheck +val wordNegCheckP = Word_negCheckP val wordNotb = Word_notb val wordOrb = Word_orb val wordQuot = Word_quot @@ -792,10 +806,12 @@ val isCommutative = | Real_qequal _ => true | Word_add _ => true | Word_addCheck _ => true + | Word_addCheckP _ => true | Word_andb _ => true | Word_equal _ => true | Word_mul _ => true | Word_mulCheck _ => true + | Word_mulCheckP _ => true | Word_orb _ => true | Word_xorb _ => true | _ => false @@ -933,6 +949,7 @@ val kind: 'a t -> Kind.t = | WordVector_toIntInf => Functional | Word_add _ => Functional | Word_addCheck _ => SideEffect + | Word_addCheckP _ => Functional | Word_andb _ => Functional | Word_castToReal _ => Functional | Word_equal _ => Functional @@ -941,8 +958,10 @@ val kind: 'a t -> Kind.t = | Word_lt _ => Functional | Word_mul _ => Functional | Word_mulCheck _ => SideEffect + | Word_mulCheckP _ => Functional | Word_neg _ => Functional | Word_negCheck _ => SideEffect + | Word_negCheckP _ => Functional | Word_notb _ => Functional | Word_orb _ => Functional | Word_quot _ => Functional @@ -953,6 +972,7 @@ val kind: 'a t -> Kind.t = | Word_rshift _ => Functional | Word_sub _ => Functional | Word_subCheck _ => SideEffect + | Word_subCheckP _ => Functional | Word_toIntInf => Functional | Word_xorb _ => Functional | World_save => SideEffect @@ -995,13 +1015,16 @@ local val sg = {signed = signed} in List.map ([Word_addCheck, + Word_addCheckP, Word_lt, Word_mul, Word_mulCheck, + Word_mulCheckP, Word_quot, Word_rem, Word_rshift, - Word_subCheck], + Word_subCheck, + Word_subCheckP], fn p => p (s, sg)) end @@ -1012,6 +1035,7 @@ local (Word_lshift s), (Word_neg s), (Word_negCheck s), + (Word_negCheckP s), (Word_notb s), (Word_orb s), (Word_rol s), @@ -1243,6 +1267,13 @@ fun 'a checkApp (prim: 'a t, val realUnary = make real val wordUnary = make word end + local + fun make f s = let val t = f s + in noTargs (fn () => (oneArg t, bool)) + end + in + val wordUnaryP = make word + end local fun make f s = let val t = f s in noTargs (fn () => (twoArgs (t, t), t)) @@ -1258,6 +1289,7 @@ fun 'a checkApp (prim: 'a t, in val realCompare = make real val wordCompare = make word + val wordBinaryP = make word end val cint = word (WordSize.cint ()) val compareRes = word WordSize.compareRes @@ -1435,6 +1467,7 @@ fun 'a checkApp (prim: 'a t, noTargs (fn () => (oneArg (vector bigIntInfWord), intInf)) | Word_add s => wordBinary s | Word_addCheck (s, _) => wordBinary s + | Word_addCheckP (s, _) => wordBinaryP s | Word_andb s => wordBinary s | Word_castToReal (s, s') => noTargs (fn () => (oneArg (word s), real s')) @@ -1445,8 +1478,10 @@ fun 'a checkApp (prim: 'a t, | Word_lt (s, _) => wordCompare s | Word_mul (s, _) => wordBinary s | Word_mulCheck (s, _) => wordBinary s + | Word_mulCheckP (s, _) => wordBinaryP s | Word_neg s => wordUnary s | Word_negCheck s => wordUnary s + | Word_negCheckP s => wordUnaryP s | Word_notb s => wordUnary s | Word_orb s => wordBinary s | Word_quot (s, _) => wordBinary s @@ -1458,6 +1493,7 @@ fun 'a checkApp (prim: 'a t, | Word_rshift (s, _) => wordShift s | Word_sub s => wordBinary s | Word_subCheck (s, _) => wordBinary s + | Word_subCheckP (s, _) => wordBinaryP s | Word_toIntInf => noTargs (fn () => (oneArg smallIntInfWord, intInf)) | Word_xorb s => wordBinary s | World_save => noTargs (fn () => (oneArg string, unit)) diff --git a/mlton/atoms/prim.sig b/mlton/atoms/prim.sig index 08adc45dfb..98f0fabe79 100644 --- a/mlton/atoms/prim.sig +++ b/mlton/atoms/prim.sig @@ -159,6 +159,7 @@ signature PRIM = | Weak_new (* to rssa (as runtime C fn) *) | Word_add of WordSize.t (* codegen *) | Word_addCheck of WordSize.t * {signed: bool} (* codegen *) + | Word_addCheckP of WordSize.t * {signed: bool} (* codegen *) | Word_andb of WordSize.t (* codegen *) | Word_castToReal of WordSize.t * RealSize.t (* codegen *) | Word_equal of WordSize.t (* codegen *) @@ -167,8 +168,10 @@ signature PRIM = | Word_lt of WordSize.t * {signed: bool} (* codegen *) | Word_mul of WordSize.t * {signed: bool} (* codegen *) | Word_mulCheck of WordSize.t * {signed: bool} (* codegen *) + | Word_mulCheckP of WordSize.t * {signed: bool} (* codegen *) | Word_neg of WordSize.t (* codegen *) | Word_negCheck of WordSize.t (* codegen *) + | Word_negCheckP of WordSize.t (* codegen *) | Word_notb of WordSize.t (* codegen *) | Word_orb of WordSize.t (* codegen *) | Word_quot of WordSize.t * {signed: bool} (* codegen *) @@ -179,6 +182,7 @@ signature PRIM = | Word_rshift of WordSize.t * {signed: bool} (* codegen *) | Word_sub of WordSize.t (* codegen *) | Word_subCheck of WordSize.t * {signed: bool} (* codegen *) + | Word_subCheckP of WordSize.t * {signed: bool} (* codegen *) | Word_toIntInf (* to rssa *) | Word_xorb of WordSize.t (* codegen *) | WordVector_toIntInf (* to rssa *) diff --git a/mlton/backend/ssa-to-rssa.fun b/mlton/backend/ssa-to-rssa.fun index e7894e4fe8..4a59a6fa80 100644 --- a/mlton/backend/ssa-to-rssa.fun +++ b/mlton/backend/ssa-to-rssa.fun @@ -476,11 +476,24 @@ structure Name = prototype = (Vector.new (n, ct), SOME CType.bool), return = Type.bool} end + fun makeP n (s, sg) = + let + val t = word s + val ct = CType.word (s, sg) + in + vanilla {args = Vector.new (n, t), + name = name, + prototype = (Vector.new (n, ct), SOME CType.bool), + return = Type.bool} + end + in val wordBinary = make 2 val wordBinaryOverflows = makeOverflows 2 + val wordBinaryP = makeP 2 val wordUnary = make 1 val wordUnaryOverflows = makeOverflows 1 + val wordUnaryP = makeP 1 end fun wordCompare (s, sg) = let @@ -551,6 +564,7 @@ structure Name = | Thread_returnToC => CFunction.returnToC () | Word_add s => wordBinary (s, {signed = false}) | Word_addCheck (s, sg) => wordBinaryOverflows (s, sg) + | Word_addCheckP (s, sg) => wordBinaryP (s, sg) | Word_andb s => wordBinary (s, {signed = false}) | Word_castToReal (s1, s2) => coerce (word s1, wordCType (s1, {signed = false}), @@ -563,8 +577,10 @@ structure Name = | Word_lt z => wordCompare z | Word_mul z => wordBinary z | Word_mulCheck (s, sg) => wordBinaryOverflows (s, sg) + | Word_mulCheckP (s, sg) => wordBinaryP (s, sg) | Word_neg s => wordUnary (s, {signed = true}) | Word_negCheck s => wordUnaryOverflows (s, {signed = true}) + | Word_negCheckP s => wordUnaryP (s, {signed = true}) | Word_notb s => wordUnary (s, {signed = false}) | Word_orb s => wordBinary (s, {signed = false}) | Word_quot z => wordBinary z @@ -578,6 +594,7 @@ structure Name = | Word_rshift z => wordShift z | Word_sub s => wordBinary (s, {signed = false}) | Word_subCheck (s, sg) => wordBinaryOverflows (s, sg) + | Word_subCheckP (s, sg) => wordBinaryP (s, sg) | _ => Error.bug "SsaToRssa.Name.cFunctionRaise" end diff --git a/mlton/codegen/c-codegen/c-codegen.fun b/mlton/codegen/c-codegen/c-codegen.fun index 5aa881215e..68d1b3ca15 100644 --- a/mlton/codegen/c-codegen/c-codegen.fun +++ b/mlton/codegen/c-codegen/c-codegen.fun @@ -207,6 +207,7 @@ fun implementsPrim (p: 'a Prim.t): bool = | Real_sub _ => true | Word_add _ => true | Word_addCheck _ => true + | Word_addCheckP _ => true | Word_andb _ => true | Word_castToReal _ => true | Word_equal _ => true @@ -215,8 +216,10 @@ fun implementsPrim (p: 'a Prim.t): bool = | Word_lt _ => true | Word_mul _ => true | Word_mulCheck _ => true + | Word_mulCheckP _ => true | Word_neg _ => true | Word_negCheck _ => true + | Word_negCheckP _ => true | Word_notb _ => true | Word_orb _ => true | Word_quot (_, {signed}) => not signed @@ -227,6 +230,7 @@ fun implementsPrim (p: 'a Prim.t): bool = | Word_rshift _ => true | Word_sub _ => true | Word_subCheck _ => true + | Word_subCheckP _ => true | Word_xorb _ => true | _ => false end @@ -1014,6 +1018,10 @@ fun output {program as Machine.Program.T {chunks, else ""] | Word_mulCheck _ => Prim.toString prim | Word_negCheck _ => Prim.toString prim + | Word_addCheckP _ => Prim.toString prim + | Word_mulCheckP _ => Prim.toString prim + | Word_negCheckP _ => Prim.toString prim + | Word_subCheckP _ => Prim.toString prim | Word_subCheck _ => concat [Prim.toString prim, if const0 () diff --git a/runtime/basis-ffi.h b/runtime/basis-ffi.h index 41f4df17be..0772b62891 100644 --- a/runtime/basis-ffi.h +++ b/runtime/basis-ffi.h @@ -982,7 +982,7 @@ MLTON_CODEGEN_STATIC_INLINE Word8_t Word8_rol(Word8_t,Word32_t); MLTON_CODEGEN_STATIC_INLINE Word8_t Word8_ror(Word8_t,Word32_t); MLTON_CODEGEN_STATIC_INLINE Word8_t Word8_sub(Word8_t,Word8_t); MLTON_CODEGEN_STATIC_INLINE Word8_t Word8_xorb(Word8_t,Word8_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordS16_addCheckOverflows(Int16_t,Int16_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordS16_addCheckP(Int16_t,Int16_t); MLTON_CODEGEN_STATIC_INLINE Word16_t WordS16_extdToWord16(Int16_t); MLTON_CODEGEN_STATIC_INLINE Word32_t WordS16_extdToWord32(Int16_t); MLTON_CODEGEN_STATIC_INLINE Word64_t WordS16_extdToWord64(Int16_t); @@ -992,15 +992,15 @@ MLTON_CODEGEN_STATIC_INLINE Bool_t WordS16_gt(Int16_t,Int16_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordS16_le(Int16_t,Int16_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordS16_lt(Int16_t,Int16_t); MLTON_CODEGEN_STATIC_INLINE Int16_t WordS16_mul(Int16_t,Int16_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordS16_mulCheckOverflows(Int16_t,Int16_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordS16_negCheckOverflows(Int16_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordS16_mulCheckP(Int16_t,Int16_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordS16_negCheckP(Int16_t); MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) Int16_t WordS16_quot(Int16_t,Int16_t); MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) Int16_t WordS16_rem(Int16_t,Int16_t); PRIVATE Real32_t WordS16_rndToReal32(Int16_t); PRIVATE Real64_t WordS16_rndToReal64(Int16_t); MLTON_CODEGEN_STATIC_INLINE Int16_t WordS16_rshift(Int16_t,Word32_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordS16_subCheckOverflows(Int16_t,Int16_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordS32_addCheckOverflows(Int32_t,Int32_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordS16_subCheckP(Int16_t,Int16_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordS32_addCheckP(Int32_t,Int32_t); MLTON_CODEGEN_STATIC_INLINE Word16_t WordS32_extdToWord16(Int32_t); MLTON_CODEGEN_STATIC_INLINE Word32_t WordS32_extdToWord32(Int32_t); MLTON_CODEGEN_STATIC_INLINE Word64_t WordS32_extdToWord64(Int32_t); @@ -1010,15 +1010,15 @@ MLTON_CODEGEN_STATIC_INLINE Bool_t WordS32_gt(Int32_t,Int32_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordS32_le(Int32_t,Int32_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordS32_lt(Int32_t,Int32_t); MLTON_CODEGEN_STATIC_INLINE Int32_t WordS32_mul(Int32_t,Int32_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordS32_mulCheckOverflows(Int32_t,Int32_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordS32_negCheckOverflows(Int32_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordS32_mulCheckP(Int32_t,Int32_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordS32_negCheckP(Int32_t); MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) Int32_t WordS32_quot(Int32_t,Int32_t); MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) Int32_t WordS32_rem(Int32_t,Int32_t); PRIVATE Real32_t WordS32_rndToReal32(Int32_t); PRIVATE Real64_t WordS32_rndToReal64(Int32_t); MLTON_CODEGEN_STATIC_INLINE Int32_t WordS32_rshift(Int32_t,Word32_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordS32_subCheckOverflows(Int32_t,Int32_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordS64_addCheckOverflows(Int64_t,Int64_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordS32_subCheckP(Int32_t,Int32_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordS64_addCheckP(Int64_t,Int64_t); MLTON_CODEGEN_STATIC_INLINE Word16_t WordS64_extdToWord16(Int64_t); MLTON_CODEGEN_STATIC_INLINE Word32_t WordS64_extdToWord32(Int64_t); MLTON_CODEGEN_STATIC_INLINE Word64_t WordS64_extdToWord64(Int64_t); @@ -1028,15 +1028,15 @@ MLTON_CODEGEN_STATIC_INLINE Bool_t WordS64_gt(Int64_t,Int64_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordS64_le(Int64_t,Int64_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordS64_lt(Int64_t,Int64_t); MLTON_CODEGEN_STATIC_INLINE Int64_t WordS64_mul(Int64_t,Int64_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordS64_mulCheckOverflows(Int64_t,Int64_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordS64_negCheckOverflows(Int64_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordS64_mulCheckP(Int64_t,Int64_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordS64_negCheckP(Int64_t); MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) Int64_t WordS64_quot(Int64_t,Int64_t); MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) Int64_t WordS64_rem(Int64_t,Int64_t); PRIVATE Real32_t WordS64_rndToReal32(Int64_t); PRIVATE Real64_t WordS64_rndToReal64(Int64_t); MLTON_CODEGEN_STATIC_INLINE Int64_t WordS64_rshift(Int64_t,Word32_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordS64_subCheckOverflows(Int64_t,Int64_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordS8_addCheckOverflows(Int8_t,Int8_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordS64_subCheckP(Int64_t,Int64_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordS8_addCheckP(Int8_t,Int8_t); MLTON_CODEGEN_STATIC_INLINE Word16_t WordS8_extdToWord16(Int8_t); MLTON_CODEGEN_STATIC_INLINE Word32_t WordS8_extdToWord32(Int8_t); MLTON_CODEGEN_STATIC_INLINE Word64_t WordS8_extdToWord64(Int8_t); @@ -1046,15 +1046,15 @@ MLTON_CODEGEN_STATIC_INLINE Bool_t WordS8_gt(Int8_t,Int8_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordS8_le(Int8_t,Int8_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordS8_lt(Int8_t,Int8_t); MLTON_CODEGEN_STATIC_INLINE Int8_t WordS8_mul(Int8_t,Int8_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordS8_mulCheckOverflows(Int8_t,Int8_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordS8_negCheckOverflows(Int8_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordS8_mulCheckP(Int8_t,Int8_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordS8_negCheckP(Int8_t); MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) Int8_t WordS8_quot(Int8_t,Int8_t); MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) Int8_t WordS8_rem(Int8_t,Int8_t); PRIVATE Real32_t WordS8_rndToReal32(Int8_t); PRIVATE Real64_t WordS8_rndToReal64(Int8_t); MLTON_CODEGEN_STATIC_INLINE Int8_t WordS8_rshift(Int8_t,Word32_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordS8_subCheckOverflows(Int8_t,Int8_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordU16_addCheckOverflows(Word16_t,Word16_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordS8_subCheckP(Int8_t,Int8_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordU16_addCheckP(Word16_t,Word16_t); MLTON_CODEGEN_STATIC_INLINE Word16_t WordU16_extdToWord16(Word16_t); MLTON_CODEGEN_STATIC_INLINE Word32_t WordU16_extdToWord32(Word16_t); MLTON_CODEGEN_STATIC_INLINE Word64_t WordU16_extdToWord64(Word16_t); @@ -1064,13 +1064,13 @@ MLTON_CODEGEN_STATIC_INLINE Bool_t WordU16_gt(Word16_t,Word16_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordU16_le(Word16_t,Word16_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordU16_lt(Word16_t,Word16_t); MLTON_CODEGEN_STATIC_INLINE Word16_t WordU16_mul(Word16_t,Word16_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordU16_mulCheckOverflows(Word16_t,Word16_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordU16_mulCheckP(Word16_t,Word16_t); MLTON_CODEGEN_STATIC_INLINE Word16_t WordU16_quot(Word16_t,Word16_t); MLTON_CODEGEN_STATIC_INLINE Word16_t WordU16_rem(Word16_t,Word16_t); PRIVATE Real32_t WordU16_rndToReal32(Word16_t); PRIVATE Real64_t WordU16_rndToReal64(Word16_t); MLTON_CODEGEN_STATIC_INLINE Word16_t WordU16_rshift(Word16_t,Word32_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordU32_addCheckOverflows(Word32_t,Word32_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordU32_addCheckP(Word32_t,Word32_t); MLTON_CODEGEN_STATIC_INLINE Word16_t WordU32_extdToWord16(Word32_t); MLTON_CODEGEN_STATIC_INLINE Word32_t WordU32_extdToWord32(Word32_t); MLTON_CODEGEN_STATIC_INLINE Word64_t WordU32_extdToWord64(Word32_t); @@ -1080,13 +1080,13 @@ MLTON_CODEGEN_STATIC_INLINE Bool_t WordU32_gt(Word32_t,Word32_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordU32_le(Word32_t,Word32_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordU32_lt(Word32_t,Word32_t); MLTON_CODEGEN_STATIC_INLINE Word32_t WordU32_mul(Word32_t,Word32_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordU32_mulCheckOverflows(Word32_t,Word32_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordU32_mulCheckP(Word32_t,Word32_t); MLTON_CODEGEN_STATIC_INLINE Word32_t WordU32_quot(Word32_t,Word32_t); MLTON_CODEGEN_STATIC_INLINE Word32_t WordU32_rem(Word32_t,Word32_t); PRIVATE Real32_t WordU32_rndToReal32(Word32_t); PRIVATE Real64_t WordU32_rndToReal64(Word32_t); MLTON_CODEGEN_STATIC_INLINE Word32_t WordU32_rshift(Word32_t,Word32_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordU64_addCheckOverflows(Word64_t,Word64_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordU64_addCheckP(Word64_t,Word64_t); MLTON_CODEGEN_STATIC_INLINE Word16_t WordU64_extdToWord16(Word64_t); MLTON_CODEGEN_STATIC_INLINE Word32_t WordU64_extdToWord32(Word64_t); MLTON_CODEGEN_STATIC_INLINE Word64_t WordU64_extdToWord64(Word64_t); @@ -1096,13 +1096,13 @@ MLTON_CODEGEN_STATIC_INLINE Bool_t WordU64_gt(Word64_t,Word64_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordU64_le(Word64_t,Word64_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordU64_lt(Word64_t,Word64_t); MLTON_CODEGEN_STATIC_INLINE Word64_t WordU64_mul(Word64_t,Word64_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordU64_mulCheckOverflows(Word64_t,Word64_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordU64_mulCheckP(Word64_t,Word64_t); MLTON_CODEGEN_STATIC_INLINE Word64_t WordU64_quot(Word64_t,Word64_t); MLTON_CODEGEN_STATIC_INLINE Word64_t WordU64_rem(Word64_t,Word64_t); PRIVATE Real32_t WordU64_rndToReal32(Word64_t); PRIVATE Real64_t WordU64_rndToReal64(Word64_t); MLTON_CODEGEN_STATIC_INLINE Word64_t WordU64_rshift(Word64_t,Word32_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordU8_addCheckOverflows(Word8_t,Word8_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordU8_addCheckP(Word8_t,Word8_t); MLTON_CODEGEN_STATIC_INLINE Word16_t WordU8_extdToWord16(Word8_t); MLTON_CODEGEN_STATIC_INLINE Word32_t WordU8_extdToWord32(Word8_t); MLTON_CODEGEN_STATIC_INLINE Word64_t WordU8_extdToWord64(Word8_t); @@ -1112,7 +1112,7 @@ MLTON_CODEGEN_STATIC_INLINE Bool_t WordU8_gt(Word8_t,Word8_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordU8_le(Word8_t,Word8_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordU8_lt(Word8_t,Word8_t); MLTON_CODEGEN_STATIC_INLINE Word8_t WordU8_mul(Word8_t,Word8_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordU8_mulCheckOverflows(Word8_t,Word8_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordU8_mulCheckP(Word8_t,Word8_t); MLTON_CODEGEN_STATIC_INLINE Word8_t WordU8_quot(Word8_t,Word8_t); MLTON_CODEGEN_STATIC_INLINE Word8_t WordU8_rem(Word8_t,Word8_t); PRIVATE Real32_t WordU8_rndToReal32(Word8_t); diff --git a/runtime/basis/Word/Word-check.h b/runtime/basis/Word/Word-check.h index 290cca29ec..83a8f5e139 100644 --- a/runtime/basis/Word/Word-check.h +++ b/runtime/basis/Word/Word-check.h @@ -77,7 +77,7 @@ WordU_addCheckBody(size, c, x, doOverflow, doSuccess) /* #define WordU_mulCheckBody(small, large, x, y, doOverflow, doSuccess) \ */ /* Word_mulCheckBody(U##small, U##large, x, y, doOverflow, doSuccess) */ -#define WordS_negCheckBody(size, x, doOverflow, doSuccess) \ +#define Word_negCheckBody(size, x, doOverflow, doSuccess) \ do { \ if (x == WordS##size##_min) { \ doOverflow; \ @@ -111,48 +111,48 @@ WordU_addCheckBody(size, c, x, doOverflow, doSuccess) WordS_subCheckBodyCX(size, x, y, doOverflow, doSuccess) -#define WordS_addCheckOverflows(size) \ +#define WordS_addCheckP(size) \ MLTON_CODEGEN_STATIC_INLINE \ - Bool WordS##size##_addCheckOverflows (WordS##size x, WordS##size y) { \ + Bool WordS##size##_addCheckP (WordS##size x, WordS##size y) { \ WordS_addCheckBody(size, x, y, return TRUE, return FALSE); \ } -#define WordU_addCheckOverflows(size) \ +#define WordU_addCheckP(size) \ MLTON_CODEGEN_STATIC_INLINE \ - Bool WordU##size##_addCheckOverflows (WordU##size x, WordU##size y) { \ + Bool WordU##size##_addCheckP (WordU##size x, WordU##size y) { \ WordU_addCheckBody(size, x, y, return TRUE, return FALSE); \ } -#define WordS_mulCheckOverflows(size) \ +#define WordS_mulCheckP(size) \ MLTON_CODEGEN_STATIC_INLINE \ - Bool WordS##size##_mulCheckOverflows (WordS##size x, WordS##size y) { \ + Bool WordS##size##_mulCheckP (WordS##size x, WordS##size y) { \ WordS_mulCheckBody(size, x, y, return TRUE, return FALSE); \ } -#define WordU_mulCheckOverflows(size) \ +#define WordU_mulCheckP(size) \ MLTON_CODEGEN_STATIC_INLINE \ - Bool WordU##size##_mulCheckOverflows (WordU##size x, WordU##size y) { \ + Bool WordU##size##_mulCheckP (WordU##size x, WordU##size y) { \ WordU_mulCheckBody(size, x, y, return TRUE, return FALSE); \ } -#define WordS_negCheckOverflows(size) \ +#define Word_negCheckP(size) \ MLTON_CODEGEN_STATIC_INLINE \ - Bool WordS##size##_negCheckOverflows (WordS##size x) { \ - WordS_negCheckBody(size, x, return TRUE, return FALSE); \ + Bool Word##size##_negCheckP (WordS##size x) { \ + Word_negCheckBody(size, x, return TRUE, return FALSE); \ } -#define WordS_subCheckOverflows(size) \ +#define WordS_subCheckP(size) \ MLTON_CODEGEN_STATIC_INLINE \ - Bool WordS##size##_subCheckOverflows (WordS##size x, WordS##size y) { \ + Bool WordS##size##_subCheckP (WordS##size x, WordS##size y) { \ WordS_subCheckBody(size, x, y, return TRUE, return FALSE); \ } #define all(size) \ -WordS_addCheckOverflows(size) \ -WordU_addCheckOverflows(size) \ -WordS_mulCheckOverflows(size) \ -WordU_mulCheckOverflows(size) \ -WordS_negCheckOverflows(size) \ -WordS_subCheckOverflows(size) +WordS_addCheckP(size) \ +WordU_addCheckP(size) \ +WordS_mulCheckP(size) \ +WordU_mulCheckP(size) \ +Word_negCheckP(size) \ +WordS_subCheckP(size) all(8) all(16) @@ -160,9 +160,9 @@ all(32) all(64) #undef all -#undef WordS_subCheckOverflows -#undef WordS_negCheckOverflows -#undef WordU_mulCheckOverflows -#undef WordS_mulCheckOverflows -#undef WordU_addCheckOverflows -#undef WordS_addCheckOverflows +#undef WordS_subCheckP +#undef WordS_negCheckP +#undef WordU_mulCheckP +#undef WordS_mulCheckP +#undef WordU_addCheckP +#undef WordS_addCheckP diff --git a/runtime/gen/basis-ffi.def b/runtime/gen/basis-ffi.def index 8a38c5c71a..7cb0d47bd1 100644 --- a/runtime/gen/basis-ffi.def +++ b/runtime/gen/basis-ffi.def @@ -979,7 +979,7 @@ Word8.rol = _import MLTON_CODEGEN_STATIC_INLINE : Word8.t * Word32.t -> Word8.t Word8.ror = _import MLTON_CODEGEN_STATIC_INLINE : Word8.t * Word32.t -> Word8.t Word8.sub = _import MLTON_CODEGEN_STATIC_INLINE : Word8.t * Word8.t -> Word8.t Word8.xorb = _import MLTON_CODEGEN_STATIC_INLINE : Word8.t * Word8.t -> Word8.t -WordS16.addCheckOverflows = _import MLTON_CODEGEN_STATIC_INLINE : Int16.t * Int16.t -> Bool.t +WordS16.addCheckP = _import MLTON_CODEGEN_STATIC_INLINE : Int16.t * Int16.t -> Bool.t WordS16.extdToWord16 = _import MLTON_CODEGEN_STATIC_INLINE : Int16.t -> Word16.t WordS16.extdToWord32 = _import MLTON_CODEGEN_STATIC_INLINE : Int16.t -> Word32.t WordS16.extdToWord64 = _import MLTON_CODEGEN_STATIC_INLINE : Int16.t -> Word64.t @@ -989,15 +989,15 @@ WordS16.gt = _import MLTON_CODEGEN_STATIC_INLINE : Int16.t * Int16.t -> Bool.t WordS16.le = _import MLTON_CODEGEN_STATIC_INLINE : Int16.t * Int16.t -> Bool.t WordS16.lt = _import MLTON_CODEGEN_STATIC_INLINE : Int16.t * Int16.t -> Bool.t WordS16.mul = _import MLTON_CODEGEN_STATIC_INLINE : Int16.t * Int16.t -> Int16.t -WordS16.mulCheckOverflows = _import MLTON_CODEGEN_STATIC_INLINE : Int16.t * Int16.t -> Bool.t -WordS16.negCheckOverflows = _import MLTON_CODEGEN_STATIC_INLINE : Int16.t -> Bool.t +WordS16.mulCheckP = _import MLTON_CODEGEN_STATIC_INLINE : Int16.t * Int16.t -> Bool.t +WordS16.negCheckP = _import MLTON_CODEGEN_STATIC_INLINE : Int16.t -> Bool.t WordS16.quot = _import MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) : Int16.t * Int16.t -> Int16.t WordS16.rem = _import MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) : Int16.t * Int16.t -> Int16.t WordS16.rndToReal32 = _import PRIVATE : Int16.t -> Real32.t WordS16.rndToReal64 = _import PRIVATE : Int16.t -> Real64.t WordS16.rshift = _import MLTON_CODEGEN_STATIC_INLINE : Int16.t * Word32.t -> Int16.t -WordS16.subCheckOverflows = _import MLTON_CODEGEN_STATIC_INLINE : Int16.t * Int16.t -> Bool.t -WordS32.addCheckOverflows = _import MLTON_CODEGEN_STATIC_INLINE : Int32.t * Int32.t -> Bool.t +WordS16.subCheckP = _import MLTON_CODEGEN_STATIC_INLINE : Int16.t * Int16.t -> Bool.t +WordS32.addCheckP = _import MLTON_CODEGEN_STATIC_INLINE : Int32.t * Int32.t -> Bool.t WordS32.extdToWord16 = _import MLTON_CODEGEN_STATIC_INLINE : Int32.t -> Word16.t WordS32.extdToWord32 = _import MLTON_CODEGEN_STATIC_INLINE : Int32.t -> Word32.t WordS32.extdToWord64 = _import MLTON_CODEGEN_STATIC_INLINE : Int32.t -> Word64.t @@ -1007,15 +1007,15 @@ WordS32.gt = _import MLTON_CODEGEN_STATIC_INLINE : Int32.t * Int32.t -> Bool.t WordS32.le = _import MLTON_CODEGEN_STATIC_INLINE : Int32.t * Int32.t -> Bool.t WordS32.lt = _import MLTON_CODEGEN_STATIC_INLINE : Int32.t * Int32.t -> Bool.t WordS32.mul = _import MLTON_CODEGEN_STATIC_INLINE : Int32.t * Int32.t -> Int32.t -WordS32.mulCheckOverflows = _import MLTON_CODEGEN_STATIC_INLINE : Int32.t * Int32.t -> Bool.t -WordS32.negCheckOverflows = _import MLTON_CODEGEN_STATIC_INLINE : Int32.t -> Bool.t +WordS32.mulCheckP = _import MLTON_CODEGEN_STATIC_INLINE : Int32.t * Int32.t -> Bool.t +WordS32.negCheckP = _import MLTON_CODEGEN_STATIC_INLINE : Int32.t -> Bool.t WordS32.quot = _import MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) : Int32.t * Int32.t -> Int32.t WordS32.rem = _import MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) : Int32.t * Int32.t -> Int32.t WordS32.rndToReal32 = _import PRIVATE : Int32.t -> Real32.t WordS32.rndToReal64 = _import PRIVATE : Int32.t -> Real64.t WordS32.rshift = _import MLTON_CODEGEN_STATIC_INLINE : Int32.t * Word32.t -> Int32.t -WordS32.subCheckOverflows = _import MLTON_CODEGEN_STATIC_INLINE : Int32.t * Int32.t -> Bool.t -WordS64.addCheckOverflows = _import MLTON_CODEGEN_STATIC_INLINE : Int64.t * Int64.t -> Bool.t +WordS32.subCheckP = _import MLTON_CODEGEN_STATIC_INLINE : Int32.t * Int32.t -> Bool.t +WordS64.addCheckP = _import MLTON_CODEGEN_STATIC_INLINE : Int64.t * Int64.t -> Bool.t WordS64.extdToWord16 = _import MLTON_CODEGEN_STATIC_INLINE : Int64.t -> Word16.t WordS64.extdToWord32 = _import MLTON_CODEGEN_STATIC_INLINE : Int64.t -> Word32.t WordS64.extdToWord64 = _import MLTON_CODEGEN_STATIC_INLINE : Int64.t -> Word64.t @@ -1025,15 +1025,15 @@ WordS64.gt = _import MLTON_CODEGEN_STATIC_INLINE : Int64.t * Int64.t -> Bool.t WordS64.le = _import MLTON_CODEGEN_STATIC_INLINE : Int64.t * Int64.t -> Bool.t WordS64.lt = _import MLTON_CODEGEN_STATIC_INLINE : Int64.t * Int64.t -> Bool.t WordS64.mul = _import MLTON_CODEGEN_STATIC_INLINE : Int64.t * Int64.t -> Int64.t -WordS64.mulCheckOverflows = _import MLTON_CODEGEN_STATIC_INLINE : Int64.t * Int64.t -> Bool.t -WordS64.negCheckOverflows = _import MLTON_CODEGEN_STATIC_INLINE : Int64.t -> Bool.t +WordS64.mulCheckP = _import MLTON_CODEGEN_STATIC_INLINE : Int64.t * Int64.t -> Bool.t +WordS64.negCheckP = _import MLTON_CODEGEN_STATIC_INLINE : Int64.t -> Bool.t WordS64.quot = _import MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) : Int64.t * Int64.t -> Int64.t WordS64.rem = _import MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) : Int64.t * Int64.t -> Int64.t WordS64.rndToReal32 = _import PRIVATE : Int64.t -> Real32.t WordS64.rndToReal64 = _import PRIVATE : Int64.t -> Real64.t WordS64.rshift = _import MLTON_CODEGEN_STATIC_INLINE : Int64.t * Word32.t -> Int64.t -WordS64.subCheckOverflows = _import MLTON_CODEGEN_STATIC_INLINE : Int64.t * Int64.t -> Bool.t -WordS8.addCheckOverflows = _import MLTON_CODEGEN_STATIC_INLINE : Int8.t * Int8.t -> Bool.t +WordS64.subCheckP = _import MLTON_CODEGEN_STATIC_INLINE : Int64.t * Int64.t -> Bool.t +WordS8.addCheckP = _import MLTON_CODEGEN_STATIC_INLINE : Int8.t * Int8.t -> Bool.t WordS8.extdToWord16 = _import MLTON_CODEGEN_STATIC_INLINE : Int8.t -> Word16.t WordS8.extdToWord32 = _import MLTON_CODEGEN_STATIC_INLINE : Int8.t -> Word32.t WordS8.extdToWord64 = _import MLTON_CODEGEN_STATIC_INLINE : Int8.t -> Word64.t @@ -1043,15 +1043,15 @@ WordS8.gt = _import MLTON_CODEGEN_STATIC_INLINE : Int8.t * Int8.t -> Bool.t WordS8.le = _import MLTON_CODEGEN_STATIC_INLINE : Int8.t * Int8.t -> Bool.t WordS8.lt = _import MLTON_CODEGEN_STATIC_INLINE : Int8.t * Int8.t -> Bool.t WordS8.mul = _import MLTON_CODEGEN_STATIC_INLINE : Int8.t * Int8.t -> Int8.t -WordS8.mulCheckOverflows = _import MLTON_CODEGEN_STATIC_INLINE : Int8.t * Int8.t -> Bool.t -WordS8.negCheckOverflows = _import MLTON_CODEGEN_STATIC_INLINE : Int8.t -> Bool.t +WordS8.mulCheckP = _import MLTON_CODEGEN_STATIC_INLINE : Int8.t * Int8.t -> Bool.t +WordS8.negCheckP = _import MLTON_CODEGEN_STATIC_INLINE : Int8.t -> Bool.t WordS8.quot = _import MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) : Int8.t * Int8.t -> Int8.t WordS8.rem = _import MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) : Int8.t * Int8.t -> Int8.t WordS8.rndToReal32 = _import PRIVATE : Int8.t -> Real32.t WordS8.rndToReal64 = _import PRIVATE : Int8.t -> Real64.t WordS8.rshift = _import MLTON_CODEGEN_STATIC_INLINE : Int8.t * Word32.t -> Int8.t -WordS8.subCheckOverflows = _import MLTON_CODEGEN_STATIC_INLINE : Int8.t * Int8.t -> Bool.t -WordU16.addCheckOverflows = _import MLTON_CODEGEN_STATIC_INLINE : Word16.t * Word16.t -> Bool.t +WordS8.subCheckP = _import MLTON_CODEGEN_STATIC_INLINE : Int8.t * Int8.t -> Bool.t +WordU16.addCheckP = _import MLTON_CODEGEN_STATIC_INLINE : Word16.t * Word16.t -> Bool.t WordU16.extdToWord16 = _import MLTON_CODEGEN_STATIC_INLINE : Word16.t -> Word16.t WordU16.extdToWord32 = _import MLTON_CODEGEN_STATIC_INLINE : Word16.t -> Word32.t WordU16.extdToWord64 = _import MLTON_CODEGEN_STATIC_INLINE : Word16.t -> Word64.t @@ -1061,13 +1061,13 @@ WordU16.gt = _import MLTON_CODEGEN_STATIC_INLINE : Word16.t * Word16.t -> Bool.t WordU16.le = _import MLTON_CODEGEN_STATIC_INLINE : Word16.t * Word16.t -> Bool.t WordU16.lt = _import MLTON_CODEGEN_STATIC_INLINE : Word16.t * Word16.t -> Bool.t WordU16.mul = _import MLTON_CODEGEN_STATIC_INLINE : Word16.t * Word16.t -> Word16.t -WordU16.mulCheckOverflows = _import MLTON_CODEGEN_STATIC_INLINE : Word16.t * Word16.t -> Bool.t +WordU16.mulCheckP = _import MLTON_CODEGEN_STATIC_INLINE : Word16.t * Word16.t -> Bool.t WordU16.quot = _import MLTON_CODEGEN_STATIC_INLINE : Word16.t * Word16.t -> Word16.t WordU16.rem = _import MLTON_CODEGEN_STATIC_INLINE : Word16.t * Word16.t -> Word16.t WordU16.rndToReal32 = _import PRIVATE : Word16.t -> Real32.t WordU16.rndToReal64 = _import PRIVATE : Word16.t -> Real64.t WordU16.rshift = _import MLTON_CODEGEN_STATIC_INLINE : Word16.t * Word32.t -> Word16.t -WordU32.addCheckOverflows = _import MLTON_CODEGEN_STATIC_INLINE : Word32.t * Word32.t -> Bool.t +WordU32.addCheckP = _import MLTON_CODEGEN_STATIC_INLINE : Word32.t * Word32.t -> Bool.t WordU32.extdToWord16 = _import MLTON_CODEGEN_STATIC_INLINE : Word32.t -> Word16.t WordU32.extdToWord32 = _import MLTON_CODEGEN_STATIC_INLINE : Word32.t -> Word32.t WordU32.extdToWord64 = _import MLTON_CODEGEN_STATIC_INLINE : Word32.t -> Word64.t @@ -1077,13 +1077,13 @@ WordU32.gt = _import MLTON_CODEGEN_STATIC_INLINE : Word32.t * Word32.t -> Bool.t WordU32.le = _import MLTON_CODEGEN_STATIC_INLINE : Word32.t * Word32.t -> Bool.t WordU32.lt = _import MLTON_CODEGEN_STATIC_INLINE : Word32.t * Word32.t -> Bool.t WordU32.mul = _import MLTON_CODEGEN_STATIC_INLINE : Word32.t * Word32.t -> Word32.t -WordU32.mulCheckOverflows = _import MLTON_CODEGEN_STATIC_INLINE : Word32.t * Word32.t -> Bool.t +WordU32.mulCheckP = _import MLTON_CODEGEN_STATIC_INLINE : Word32.t * Word32.t -> Bool.t WordU32.quot = _import MLTON_CODEGEN_STATIC_INLINE : Word32.t * Word32.t -> Word32.t WordU32.rem = _import MLTON_CODEGEN_STATIC_INLINE : Word32.t * Word32.t -> Word32.t WordU32.rndToReal32 = _import PRIVATE : Word32.t -> Real32.t WordU32.rndToReal64 = _import PRIVATE : Word32.t -> Real64.t WordU32.rshift = _import MLTON_CODEGEN_STATIC_INLINE : Word32.t * Word32.t -> Word32.t -WordU64.addCheckOverflows = _import MLTON_CODEGEN_STATIC_INLINE : Word64.t * Word64.t -> Bool.t +WordU64.addCheckP = _import MLTON_CODEGEN_STATIC_INLINE : Word64.t * Word64.t -> Bool.t WordU64.extdToWord16 = _import MLTON_CODEGEN_STATIC_INLINE : Word64.t -> Word16.t WordU64.extdToWord32 = _import MLTON_CODEGEN_STATIC_INLINE : Word64.t -> Word32.t WordU64.extdToWord64 = _import MLTON_CODEGEN_STATIC_INLINE : Word64.t -> Word64.t @@ -1093,13 +1093,13 @@ WordU64.gt = _import MLTON_CODEGEN_STATIC_INLINE : Word64.t * Word64.t -> Bool.t WordU64.le = _import MLTON_CODEGEN_STATIC_INLINE : Word64.t * Word64.t -> Bool.t WordU64.lt = _import MLTON_CODEGEN_STATIC_INLINE : Word64.t * Word64.t -> Bool.t WordU64.mul = _import MLTON_CODEGEN_STATIC_INLINE : Word64.t * Word64.t -> Word64.t -WordU64.mulCheckOverflows = _import MLTON_CODEGEN_STATIC_INLINE : Word64.t * Word64.t -> Bool.t +WordU64.mulCheckP = _import MLTON_CODEGEN_STATIC_INLINE : Word64.t * Word64.t -> Bool.t WordU64.quot = _import MLTON_CODEGEN_STATIC_INLINE : Word64.t * Word64.t -> Word64.t WordU64.rem = _import MLTON_CODEGEN_STATIC_INLINE : Word64.t * Word64.t -> Word64.t WordU64.rndToReal32 = _import PRIVATE : Word64.t -> Real32.t WordU64.rndToReal64 = _import PRIVATE : Word64.t -> Real64.t WordU64.rshift = _import MLTON_CODEGEN_STATIC_INLINE : Word64.t * Word32.t -> Word64.t -WordU8.addCheckOverflows = _import MLTON_CODEGEN_STATIC_INLINE : Word8.t * Word8.t -> Bool.t +WordU8.addCheckP = _import MLTON_CODEGEN_STATIC_INLINE : Word8.t * Word8.t -> Bool.t WordU8.extdToWord16 = _import MLTON_CODEGEN_STATIC_INLINE : Word8.t -> Word16.t WordU8.extdToWord32 = _import MLTON_CODEGEN_STATIC_INLINE : Word8.t -> Word32.t WordU8.extdToWord64 = _import MLTON_CODEGEN_STATIC_INLINE : Word8.t -> Word64.t @@ -1109,7 +1109,7 @@ WordU8.gt = _import MLTON_CODEGEN_STATIC_INLINE : Word8.t * Word8.t -> Bool.t WordU8.le = _import MLTON_CODEGEN_STATIC_INLINE : Word8.t * Word8.t -> Bool.t WordU8.lt = _import MLTON_CODEGEN_STATIC_INLINE : Word8.t * Word8.t -> Bool.t WordU8.mul = _import MLTON_CODEGEN_STATIC_INLINE : Word8.t * Word8.t -> Word8.t -WordU8.mulCheckOverflows = _import MLTON_CODEGEN_STATIC_INLINE : Word8.t * Word8.t -> Bool.t +WordU8.mulCheckP = _import MLTON_CODEGEN_STATIC_INLINE : Word8.t * Word8.t -> Bool.t WordU8.quot = _import MLTON_CODEGEN_STATIC_INLINE : Word8.t * Word8.t -> Word8.t WordU8.rem = _import MLTON_CODEGEN_STATIC_INLINE : Word8.t * Word8.t -> Word8.t WordU8.rndToReal32 = _import PRIVATE : Word8.t -> Real32.t diff --git a/runtime/gen/basis-ffi.h b/runtime/gen/basis-ffi.h index 41f4df17be..0772b62891 100644 --- a/runtime/gen/basis-ffi.h +++ b/runtime/gen/basis-ffi.h @@ -982,7 +982,7 @@ MLTON_CODEGEN_STATIC_INLINE Word8_t Word8_rol(Word8_t,Word32_t); MLTON_CODEGEN_STATIC_INLINE Word8_t Word8_ror(Word8_t,Word32_t); MLTON_CODEGEN_STATIC_INLINE Word8_t Word8_sub(Word8_t,Word8_t); MLTON_CODEGEN_STATIC_INLINE Word8_t Word8_xorb(Word8_t,Word8_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordS16_addCheckOverflows(Int16_t,Int16_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordS16_addCheckP(Int16_t,Int16_t); MLTON_CODEGEN_STATIC_INLINE Word16_t WordS16_extdToWord16(Int16_t); MLTON_CODEGEN_STATIC_INLINE Word32_t WordS16_extdToWord32(Int16_t); MLTON_CODEGEN_STATIC_INLINE Word64_t WordS16_extdToWord64(Int16_t); @@ -992,15 +992,15 @@ MLTON_CODEGEN_STATIC_INLINE Bool_t WordS16_gt(Int16_t,Int16_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordS16_le(Int16_t,Int16_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordS16_lt(Int16_t,Int16_t); MLTON_CODEGEN_STATIC_INLINE Int16_t WordS16_mul(Int16_t,Int16_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordS16_mulCheckOverflows(Int16_t,Int16_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordS16_negCheckOverflows(Int16_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordS16_mulCheckP(Int16_t,Int16_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordS16_negCheckP(Int16_t); MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) Int16_t WordS16_quot(Int16_t,Int16_t); MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) Int16_t WordS16_rem(Int16_t,Int16_t); PRIVATE Real32_t WordS16_rndToReal32(Int16_t); PRIVATE Real64_t WordS16_rndToReal64(Int16_t); MLTON_CODEGEN_STATIC_INLINE Int16_t WordS16_rshift(Int16_t,Word32_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordS16_subCheckOverflows(Int16_t,Int16_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordS32_addCheckOverflows(Int32_t,Int32_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordS16_subCheckP(Int16_t,Int16_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordS32_addCheckP(Int32_t,Int32_t); MLTON_CODEGEN_STATIC_INLINE Word16_t WordS32_extdToWord16(Int32_t); MLTON_CODEGEN_STATIC_INLINE Word32_t WordS32_extdToWord32(Int32_t); MLTON_CODEGEN_STATIC_INLINE Word64_t WordS32_extdToWord64(Int32_t); @@ -1010,15 +1010,15 @@ MLTON_CODEGEN_STATIC_INLINE Bool_t WordS32_gt(Int32_t,Int32_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordS32_le(Int32_t,Int32_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordS32_lt(Int32_t,Int32_t); MLTON_CODEGEN_STATIC_INLINE Int32_t WordS32_mul(Int32_t,Int32_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordS32_mulCheckOverflows(Int32_t,Int32_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordS32_negCheckOverflows(Int32_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordS32_mulCheckP(Int32_t,Int32_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordS32_negCheckP(Int32_t); MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) Int32_t WordS32_quot(Int32_t,Int32_t); MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) Int32_t WordS32_rem(Int32_t,Int32_t); PRIVATE Real32_t WordS32_rndToReal32(Int32_t); PRIVATE Real64_t WordS32_rndToReal64(Int32_t); MLTON_CODEGEN_STATIC_INLINE Int32_t WordS32_rshift(Int32_t,Word32_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordS32_subCheckOverflows(Int32_t,Int32_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordS64_addCheckOverflows(Int64_t,Int64_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordS32_subCheckP(Int32_t,Int32_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordS64_addCheckP(Int64_t,Int64_t); MLTON_CODEGEN_STATIC_INLINE Word16_t WordS64_extdToWord16(Int64_t); MLTON_CODEGEN_STATIC_INLINE Word32_t WordS64_extdToWord32(Int64_t); MLTON_CODEGEN_STATIC_INLINE Word64_t WordS64_extdToWord64(Int64_t); @@ -1028,15 +1028,15 @@ MLTON_CODEGEN_STATIC_INLINE Bool_t WordS64_gt(Int64_t,Int64_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordS64_le(Int64_t,Int64_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordS64_lt(Int64_t,Int64_t); MLTON_CODEGEN_STATIC_INLINE Int64_t WordS64_mul(Int64_t,Int64_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordS64_mulCheckOverflows(Int64_t,Int64_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordS64_negCheckOverflows(Int64_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordS64_mulCheckP(Int64_t,Int64_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordS64_negCheckP(Int64_t); MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) Int64_t WordS64_quot(Int64_t,Int64_t); MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) Int64_t WordS64_rem(Int64_t,Int64_t); PRIVATE Real32_t WordS64_rndToReal32(Int64_t); PRIVATE Real64_t WordS64_rndToReal64(Int64_t); MLTON_CODEGEN_STATIC_INLINE Int64_t WordS64_rshift(Int64_t,Word32_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordS64_subCheckOverflows(Int64_t,Int64_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordS8_addCheckOverflows(Int8_t,Int8_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordS64_subCheckP(Int64_t,Int64_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordS8_addCheckP(Int8_t,Int8_t); MLTON_CODEGEN_STATIC_INLINE Word16_t WordS8_extdToWord16(Int8_t); MLTON_CODEGEN_STATIC_INLINE Word32_t WordS8_extdToWord32(Int8_t); MLTON_CODEGEN_STATIC_INLINE Word64_t WordS8_extdToWord64(Int8_t); @@ -1046,15 +1046,15 @@ MLTON_CODEGEN_STATIC_INLINE Bool_t WordS8_gt(Int8_t,Int8_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordS8_le(Int8_t,Int8_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordS8_lt(Int8_t,Int8_t); MLTON_CODEGEN_STATIC_INLINE Int8_t WordS8_mul(Int8_t,Int8_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordS8_mulCheckOverflows(Int8_t,Int8_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordS8_negCheckOverflows(Int8_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordS8_mulCheckP(Int8_t,Int8_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordS8_negCheckP(Int8_t); MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) Int8_t WordS8_quot(Int8_t,Int8_t); MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) Int8_t WordS8_rem(Int8_t,Int8_t); PRIVATE Real32_t WordS8_rndToReal32(Int8_t); PRIVATE Real64_t WordS8_rndToReal64(Int8_t); MLTON_CODEGEN_STATIC_INLINE Int8_t WordS8_rshift(Int8_t,Word32_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordS8_subCheckOverflows(Int8_t,Int8_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordU16_addCheckOverflows(Word16_t,Word16_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordS8_subCheckP(Int8_t,Int8_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordU16_addCheckP(Word16_t,Word16_t); MLTON_CODEGEN_STATIC_INLINE Word16_t WordU16_extdToWord16(Word16_t); MLTON_CODEGEN_STATIC_INLINE Word32_t WordU16_extdToWord32(Word16_t); MLTON_CODEGEN_STATIC_INLINE Word64_t WordU16_extdToWord64(Word16_t); @@ -1064,13 +1064,13 @@ MLTON_CODEGEN_STATIC_INLINE Bool_t WordU16_gt(Word16_t,Word16_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordU16_le(Word16_t,Word16_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordU16_lt(Word16_t,Word16_t); MLTON_CODEGEN_STATIC_INLINE Word16_t WordU16_mul(Word16_t,Word16_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordU16_mulCheckOverflows(Word16_t,Word16_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordU16_mulCheckP(Word16_t,Word16_t); MLTON_CODEGEN_STATIC_INLINE Word16_t WordU16_quot(Word16_t,Word16_t); MLTON_CODEGEN_STATIC_INLINE Word16_t WordU16_rem(Word16_t,Word16_t); PRIVATE Real32_t WordU16_rndToReal32(Word16_t); PRIVATE Real64_t WordU16_rndToReal64(Word16_t); MLTON_CODEGEN_STATIC_INLINE Word16_t WordU16_rshift(Word16_t,Word32_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordU32_addCheckOverflows(Word32_t,Word32_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordU32_addCheckP(Word32_t,Word32_t); MLTON_CODEGEN_STATIC_INLINE Word16_t WordU32_extdToWord16(Word32_t); MLTON_CODEGEN_STATIC_INLINE Word32_t WordU32_extdToWord32(Word32_t); MLTON_CODEGEN_STATIC_INLINE Word64_t WordU32_extdToWord64(Word32_t); @@ -1080,13 +1080,13 @@ MLTON_CODEGEN_STATIC_INLINE Bool_t WordU32_gt(Word32_t,Word32_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordU32_le(Word32_t,Word32_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordU32_lt(Word32_t,Word32_t); MLTON_CODEGEN_STATIC_INLINE Word32_t WordU32_mul(Word32_t,Word32_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordU32_mulCheckOverflows(Word32_t,Word32_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordU32_mulCheckP(Word32_t,Word32_t); MLTON_CODEGEN_STATIC_INLINE Word32_t WordU32_quot(Word32_t,Word32_t); MLTON_CODEGEN_STATIC_INLINE Word32_t WordU32_rem(Word32_t,Word32_t); PRIVATE Real32_t WordU32_rndToReal32(Word32_t); PRIVATE Real64_t WordU32_rndToReal64(Word32_t); MLTON_CODEGEN_STATIC_INLINE Word32_t WordU32_rshift(Word32_t,Word32_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordU64_addCheckOverflows(Word64_t,Word64_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordU64_addCheckP(Word64_t,Word64_t); MLTON_CODEGEN_STATIC_INLINE Word16_t WordU64_extdToWord16(Word64_t); MLTON_CODEGEN_STATIC_INLINE Word32_t WordU64_extdToWord32(Word64_t); MLTON_CODEGEN_STATIC_INLINE Word64_t WordU64_extdToWord64(Word64_t); @@ -1096,13 +1096,13 @@ MLTON_CODEGEN_STATIC_INLINE Bool_t WordU64_gt(Word64_t,Word64_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordU64_le(Word64_t,Word64_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordU64_lt(Word64_t,Word64_t); MLTON_CODEGEN_STATIC_INLINE Word64_t WordU64_mul(Word64_t,Word64_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordU64_mulCheckOverflows(Word64_t,Word64_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordU64_mulCheckP(Word64_t,Word64_t); MLTON_CODEGEN_STATIC_INLINE Word64_t WordU64_quot(Word64_t,Word64_t); MLTON_CODEGEN_STATIC_INLINE Word64_t WordU64_rem(Word64_t,Word64_t); PRIVATE Real32_t WordU64_rndToReal32(Word64_t); PRIVATE Real64_t WordU64_rndToReal64(Word64_t); MLTON_CODEGEN_STATIC_INLINE Word64_t WordU64_rshift(Word64_t,Word32_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordU8_addCheckOverflows(Word8_t,Word8_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordU8_addCheckP(Word8_t,Word8_t); MLTON_CODEGEN_STATIC_INLINE Word16_t WordU8_extdToWord16(Word8_t); MLTON_CODEGEN_STATIC_INLINE Word32_t WordU8_extdToWord32(Word8_t); MLTON_CODEGEN_STATIC_INLINE Word64_t WordU8_extdToWord64(Word8_t); @@ -1112,7 +1112,7 @@ MLTON_CODEGEN_STATIC_INLINE Bool_t WordU8_gt(Word8_t,Word8_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordU8_le(Word8_t,Word8_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordU8_lt(Word8_t,Word8_t); MLTON_CODEGEN_STATIC_INLINE Word8_t WordU8_mul(Word8_t,Word8_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordU8_mulCheckOverflows(Word8_t,Word8_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t WordU8_mulCheckP(Word8_t,Word8_t); MLTON_CODEGEN_STATIC_INLINE Word8_t WordU8_quot(Word8_t,Word8_t); MLTON_CODEGEN_STATIC_INLINE Word8_t WordU8_rem(Word8_t,Word8_t); PRIVATE Real32_t WordU8_rndToReal32(Word8_t); diff --git a/runtime/gen/basis-ffi.sml b/runtime/gen/basis-ffi.sml index 53a3b4413a..cd74bcd57e 100644 --- a/runtime/gen/basis-ffi.sml +++ b/runtime/gen/basis-ffi.sml @@ -1207,7 +1207,7 @@ val xorb = _import "Word8_xorb" private : Word8.t * Word8.t -> Word8.t; end structure WordS16 = struct -val addCheckOverflows = _import "WordS16_addCheckOverflows" private : Int16.t * Int16.t -> Bool.t; +val addCheckP = _import "WordS16_addCheckP" private : Int16.t * Int16.t -> Bool.t; val extdToWord16 = _import "WordS16_extdToWord16" private : Int16.t -> Word16.t; val extdToWord32 = _import "WordS16_extdToWord32" private : Int16.t -> Word32.t; val extdToWord64 = _import "WordS16_extdToWord64" private : Int16.t -> Word64.t; @@ -1217,18 +1217,18 @@ val gt = _import "WordS16_gt" private : Int16.t * Int16.t -> Bool.t; val le = _import "WordS16_le" private : Int16.t * Int16.t -> Bool.t; val lt = _import "WordS16_lt" private : Int16.t * Int16.t -> Bool.t; val mul = _import "WordS16_mul" private : Int16.t * Int16.t -> Int16.t; -val mulCheckOverflows = _import "WordS16_mulCheckOverflows" private : Int16.t * Int16.t -> Bool.t; -val negCheckOverflows = _import "WordS16_negCheckOverflows" private : Int16.t -> Bool.t; +val mulCheckP = _import "WordS16_mulCheckP" private : Int16.t * Int16.t -> Bool.t; +val negCheckP = _import "WordS16_negCheckP" private : Int16.t -> Bool.t; val quot = _import "WordS16_quot" private : Int16.t * Int16.t -> Int16.t; val rem = _import "WordS16_rem" private : Int16.t * Int16.t -> Int16.t; val rndToReal32 = _import "WordS16_rndToReal32" private : Int16.t -> Real32.t; val rndToReal64 = _import "WordS16_rndToReal64" private : Int16.t -> Real64.t; val rshift = _import "WordS16_rshift" private : Int16.t * Word32.t -> Int16.t; -val subCheckOverflows = _import "WordS16_subCheckOverflows" private : Int16.t * Int16.t -> Bool.t; +val subCheckP = _import "WordS16_subCheckP" private : Int16.t * Int16.t -> Bool.t; end structure WordS32 = struct -val addCheckOverflows = _import "WordS32_addCheckOverflows" private : Int32.t * Int32.t -> Bool.t; +val addCheckP = _import "WordS32_addCheckP" private : Int32.t * Int32.t -> Bool.t; val extdToWord16 = _import "WordS32_extdToWord16" private : Int32.t -> Word16.t; val extdToWord32 = _import "WordS32_extdToWord32" private : Int32.t -> Word32.t; val extdToWord64 = _import "WordS32_extdToWord64" private : Int32.t -> Word64.t; @@ -1238,18 +1238,18 @@ val gt = _import "WordS32_gt" private : Int32.t * Int32.t -> Bool.t; val le = _import "WordS32_le" private : Int32.t * Int32.t -> Bool.t; val lt = _import "WordS32_lt" private : Int32.t * Int32.t -> Bool.t; val mul = _import "WordS32_mul" private : Int32.t * Int32.t -> Int32.t; -val mulCheckOverflows = _import "WordS32_mulCheckOverflows" private : Int32.t * Int32.t -> Bool.t; -val negCheckOverflows = _import "WordS32_negCheckOverflows" private : Int32.t -> Bool.t; +val mulCheckP = _import "WordS32_mulCheckP" private : Int32.t * Int32.t -> Bool.t; +val negCheckP = _import "WordS32_negCheckP" private : Int32.t -> Bool.t; val quot = _import "WordS32_quot" private : Int32.t * Int32.t -> Int32.t; val rem = _import "WordS32_rem" private : Int32.t * Int32.t -> Int32.t; val rndToReal32 = _import "WordS32_rndToReal32" private : Int32.t -> Real32.t; val rndToReal64 = _import "WordS32_rndToReal64" private : Int32.t -> Real64.t; val rshift = _import "WordS32_rshift" private : Int32.t * Word32.t -> Int32.t; -val subCheckOverflows = _import "WordS32_subCheckOverflows" private : Int32.t * Int32.t -> Bool.t; +val subCheckP = _import "WordS32_subCheckP" private : Int32.t * Int32.t -> Bool.t; end structure WordS64 = struct -val addCheckOverflows = _import "WordS64_addCheckOverflows" private : Int64.t * Int64.t -> Bool.t; +val addCheckP = _import "WordS64_addCheckP" private : Int64.t * Int64.t -> Bool.t; val extdToWord16 = _import "WordS64_extdToWord16" private : Int64.t -> Word16.t; val extdToWord32 = _import "WordS64_extdToWord32" private : Int64.t -> Word32.t; val extdToWord64 = _import "WordS64_extdToWord64" private : Int64.t -> Word64.t; @@ -1259,18 +1259,18 @@ val gt = _import "WordS64_gt" private : Int64.t * Int64.t -> Bool.t; val le = _import "WordS64_le" private : Int64.t * Int64.t -> Bool.t; val lt = _import "WordS64_lt" private : Int64.t * Int64.t -> Bool.t; val mul = _import "WordS64_mul" private : Int64.t * Int64.t -> Int64.t; -val mulCheckOverflows = _import "WordS64_mulCheckOverflows" private : Int64.t * Int64.t -> Bool.t; -val negCheckOverflows = _import "WordS64_negCheckOverflows" private : Int64.t -> Bool.t; +val mulCheckP = _import "WordS64_mulCheckP" private : Int64.t * Int64.t -> Bool.t; +val negCheckP = _import "WordS64_negCheckP" private : Int64.t -> Bool.t; val quot = _import "WordS64_quot" private : Int64.t * Int64.t -> Int64.t; val rem = _import "WordS64_rem" private : Int64.t * Int64.t -> Int64.t; val rndToReal32 = _import "WordS64_rndToReal32" private : Int64.t -> Real32.t; val rndToReal64 = _import "WordS64_rndToReal64" private : Int64.t -> Real64.t; val rshift = _import "WordS64_rshift" private : Int64.t * Word32.t -> Int64.t; -val subCheckOverflows = _import "WordS64_subCheckOverflows" private : Int64.t * Int64.t -> Bool.t; +val subCheckP = _import "WordS64_subCheckP" private : Int64.t * Int64.t -> Bool.t; end structure WordS8 = struct -val addCheckOverflows = _import "WordS8_addCheckOverflows" private : Int8.t * Int8.t -> Bool.t; +val addCheckP = _import "WordS8_addCheckP" private : Int8.t * Int8.t -> Bool.t; val extdToWord16 = _import "WordS8_extdToWord16" private : Int8.t -> Word16.t; val extdToWord32 = _import "WordS8_extdToWord32" private : Int8.t -> Word32.t; val extdToWord64 = _import "WordS8_extdToWord64" private : Int8.t -> Word64.t; @@ -1280,18 +1280,18 @@ val gt = _import "WordS8_gt" private : Int8.t * Int8.t -> Bool.t; val le = _import "WordS8_le" private : Int8.t * Int8.t -> Bool.t; val lt = _import "WordS8_lt" private : Int8.t * Int8.t -> Bool.t; val mul = _import "WordS8_mul" private : Int8.t * Int8.t -> Int8.t; -val mulCheckOverflows = _import "WordS8_mulCheckOverflows" private : Int8.t * Int8.t -> Bool.t; -val negCheckOverflows = _import "WordS8_negCheckOverflows" private : Int8.t -> Bool.t; +val mulCheckP = _import "WordS8_mulCheckP" private : Int8.t * Int8.t -> Bool.t; +val negCheckP = _import "WordS8_negCheckP" private : Int8.t -> Bool.t; val quot = _import "WordS8_quot" private : Int8.t * Int8.t -> Int8.t; val rem = _import "WordS8_rem" private : Int8.t * Int8.t -> Int8.t; val rndToReal32 = _import "WordS8_rndToReal32" private : Int8.t -> Real32.t; val rndToReal64 = _import "WordS8_rndToReal64" private : Int8.t -> Real64.t; val rshift = _import "WordS8_rshift" private : Int8.t * Word32.t -> Int8.t; -val subCheckOverflows = _import "WordS8_subCheckOverflows" private : Int8.t * Int8.t -> Bool.t; +val subCheckP = _import "WordS8_subCheckP" private : Int8.t * Int8.t -> Bool.t; end structure WordU16 = struct -val addCheckOverflows = _import "WordU16_addCheckOverflows" private : Word16.t * Word16.t -> Bool.t; +val addCheckP = _import "WordU16_addCheckP" private : Word16.t * Word16.t -> Bool.t; val extdToWord16 = _import "WordU16_extdToWord16" private : Word16.t -> Word16.t; val extdToWord32 = _import "WordU16_extdToWord32" private : Word16.t -> Word32.t; val extdToWord64 = _import "WordU16_extdToWord64" private : Word16.t -> Word64.t; @@ -1301,7 +1301,7 @@ val gt = _import "WordU16_gt" private : Word16.t * Word16.t -> Bool.t; val le = _import "WordU16_le" private : Word16.t * Word16.t -> Bool.t; val lt = _import "WordU16_lt" private : Word16.t * Word16.t -> Bool.t; val mul = _import "WordU16_mul" private : Word16.t * Word16.t -> Word16.t; -val mulCheckOverflows = _import "WordU16_mulCheckOverflows" private : Word16.t * Word16.t -> Bool.t; +val mulCheckP = _import "WordU16_mulCheckP" private : Word16.t * Word16.t -> Bool.t; val quot = _import "WordU16_quot" private : Word16.t * Word16.t -> Word16.t; val rem = _import "WordU16_rem" private : Word16.t * Word16.t -> Word16.t; val rndToReal32 = _import "WordU16_rndToReal32" private : Word16.t -> Real32.t; @@ -1310,7 +1310,7 @@ val rshift = _import "WordU16_rshift" private : Word16.t * Word32.t -> Word16.t; end structure WordU32 = struct -val addCheckOverflows = _import "WordU32_addCheckOverflows" private : Word32.t * Word32.t -> Bool.t; +val addCheckP = _import "WordU32_addCheckP" private : Word32.t * Word32.t -> Bool.t; val extdToWord16 = _import "WordU32_extdToWord16" private : Word32.t -> Word16.t; val extdToWord32 = _import "WordU32_extdToWord32" private : Word32.t -> Word32.t; val extdToWord64 = _import "WordU32_extdToWord64" private : Word32.t -> Word64.t; @@ -1320,7 +1320,7 @@ val gt = _import "WordU32_gt" private : Word32.t * Word32.t -> Bool.t; val le = _import "WordU32_le" private : Word32.t * Word32.t -> Bool.t; val lt = _import "WordU32_lt" private : Word32.t * Word32.t -> Bool.t; val mul = _import "WordU32_mul" private : Word32.t * Word32.t -> Word32.t; -val mulCheckOverflows = _import "WordU32_mulCheckOverflows" private : Word32.t * Word32.t -> Bool.t; +val mulCheckP = _import "WordU32_mulCheckP" private : Word32.t * Word32.t -> Bool.t; val quot = _import "WordU32_quot" private : Word32.t * Word32.t -> Word32.t; val rem = _import "WordU32_rem" private : Word32.t * Word32.t -> Word32.t; val rndToReal32 = _import "WordU32_rndToReal32" private : Word32.t -> Real32.t; @@ -1329,7 +1329,7 @@ val rshift = _import "WordU32_rshift" private : Word32.t * Word32.t -> Word32.t; end structure WordU64 = struct -val addCheckOverflows = _import "WordU64_addCheckOverflows" private : Word64.t * Word64.t -> Bool.t; +val addCheckP = _import "WordU64_addCheckP" private : Word64.t * Word64.t -> Bool.t; val extdToWord16 = _import "WordU64_extdToWord16" private : Word64.t -> Word16.t; val extdToWord32 = _import "WordU64_extdToWord32" private : Word64.t -> Word32.t; val extdToWord64 = _import "WordU64_extdToWord64" private : Word64.t -> Word64.t; @@ -1339,7 +1339,7 @@ val gt = _import "WordU64_gt" private : Word64.t * Word64.t -> Bool.t; val le = _import "WordU64_le" private : Word64.t * Word64.t -> Bool.t; val lt = _import "WordU64_lt" private : Word64.t * Word64.t -> Bool.t; val mul = _import "WordU64_mul" private : Word64.t * Word64.t -> Word64.t; -val mulCheckOverflows = _import "WordU64_mulCheckOverflows" private : Word64.t * Word64.t -> Bool.t; +val mulCheckP = _import "WordU64_mulCheckP" private : Word64.t * Word64.t -> Bool.t; val quot = _import "WordU64_quot" private : Word64.t * Word64.t -> Word64.t; val rem = _import "WordU64_rem" private : Word64.t * Word64.t -> Word64.t; val rndToReal32 = _import "WordU64_rndToReal32" private : Word64.t -> Real32.t; @@ -1348,7 +1348,7 @@ val rshift = _import "WordU64_rshift" private : Word64.t * Word32.t -> Word64.t; end structure WordU8 = struct -val addCheckOverflows = _import "WordU8_addCheckOverflows" private : Word8.t * Word8.t -> Bool.t; +val addCheckP = _import "WordU8_addCheckP" private : Word8.t * Word8.t -> Bool.t; val extdToWord16 = _import "WordU8_extdToWord16" private : Word8.t -> Word16.t; val extdToWord32 = _import "WordU8_extdToWord32" private : Word8.t -> Word32.t; val extdToWord64 = _import "WordU8_extdToWord64" private : Word8.t -> Word64.t; @@ -1358,7 +1358,7 @@ val gt = _import "WordU8_gt" private : Word8.t * Word8.t -> Bool.t; val le = _import "WordU8_le" private : Word8.t * Word8.t -> Bool.t; val lt = _import "WordU8_lt" private : Word8.t * Word8.t -> Bool.t; val mul = _import "WordU8_mul" private : Word8.t * Word8.t -> Word8.t; -val mulCheckOverflows = _import "WordU8_mulCheckOverflows" private : Word8.t * Word8.t -> Bool.t; +val mulCheckP = _import "WordU8_mulCheckP" private : Word8.t * Word8.t -> Bool.t; val quot = _import "WordU8_quot" private : Word8.t * Word8.t -> Word8.t; val rem = _import "WordU8_rem" private : Word8.t * Word8.t -> Word8.t; val rndToReal32 = _import "WordU8_rndToReal32" private : Word8.t -> Real32.t; From 7bb41e562077d76ae5f1930554ae13b7ba68ea65 Mon Sep 17 00:00:00 2001 From: Daman Morris Date: Thu, 31 May 2018 14:19:09 -0400 Subject: [PATCH 06/57] Remove unnecessary cases of Arith transfers --- mlton/codegen/c-codegen/c-codegen.fun | 4 ---- 1 file changed, 4 deletions(-) diff --git a/mlton/codegen/c-codegen/c-codegen.fun b/mlton/codegen/c-codegen/c-codegen.fun index 68d1b3ca15..26e444309a 100644 --- a/mlton/codegen/c-codegen/c-codegen.fun +++ b/mlton/codegen/c-codegen/c-codegen.fun @@ -1018,10 +1018,6 @@ fun output {program as Machine.Program.T {chunks, else ""] | Word_mulCheck _ => Prim.toString prim | Word_negCheck _ => Prim.toString prim - | Word_addCheckP _ => Prim.toString prim - | Word_mulCheckP _ => Prim.toString prim - | Word_negCheckP _ => Prim.toString prim - | Word_subCheckP _ => Prim.toString prim | Word_subCheck _ => concat [Prim.toString prim, if const0 () From 81d8cf8e77f85b43aff9e5b09b1518340c62156f Mon Sep 17 00:00:00 2001 From: Daman Morris Date: Tue, 12 Jun 2018 13:43:16 -0400 Subject: [PATCH 07/57] Add support for new primitives in amd64 codegen --- include/amd64-main.h | 1 + mlton/backend/rep-type.fun | 14 ++ .../amd64-codegen/amd64-mlton-basic.fun | 7 + .../amd64-codegen/amd64-mlton-basic.sig | 1 + mlton/codegen/amd64-codegen/amd64-mlton.fun | 196 ++++++++++++++++++ 5 files changed, 219 insertions(+) diff --git a/include/amd64-main.h b/include/amd64-main.h index f47be6dac3..81954b50e9 100644 --- a/include/amd64-main.h +++ b/include/amd64-main.h @@ -26,6 +26,7 @@ PRIVATE Word64 indexTemp; PRIVATE Word64 raTemp1; PRIVATE Word64 spill[32]; PRIVATE Word64 stackTopTemp; +PRIVATE Word64 overflowCheckTemp; #ifndef DEBUG_AMD64CODEGEN #define DEBUG_AMD64CODEGEN FALSE diff --git a/mlton/backend/rep-type.fun b/mlton/backend/rep-type.fun index d3d2761427..273c0e40da 100644 --- a/mlton/backend/rep-type.fun +++ b/mlton/backend/rep-type.fun @@ -571,12 +571,22 @@ fun checkPrimApp {args, prim, result} = val realUnary = make real val wordUnary = make wordOrBitsOrSeq end + local + fun make f s = let val t = f s in done ([t], SOME bool) end + in + val wordUnaryP = make wordOrBitsOrSeq + end local fun make f s = let val t = f s in done ([t, t], SOME t) end in val realBinary = make real val wordBinary = make wordOrBitsOrSeq end + local + fun make f s = let val t = f s in done ([t, t], SOME bool) end + in + val wordBinaryP = make wordOrBitsOrSeq + end local fun make f s = let val t = f s in done ([t, t], SOME bool) end in @@ -631,6 +641,7 @@ fun checkPrimApp {args, prim, result} = | Thread_returnToC => done ([], NONE) | Word_add s => wordBinary s | Word_addCheck (s, _) => wordBinary s + | Word_addCheckP (s, _) => wordBinaryP s | Word_andb s => wordBinary s | Word_castToReal (s, s') => done ([word s], SOME (real s')) | Word_equal s => (wordCompare s) orelse objptrCompare @@ -640,8 +651,10 @@ fun checkPrimApp {args, prim, result} = | Word_lt (s, _) => wordCompare s | Word_mul (s, _) => wordBinary s | Word_mulCheck (s, _) => wordBinary s + | Word_mulCheckP (s, _) => wordBinaryP s | Word_neg s => wordUnary s | Word_negCheck s => wordUnary s + | Word_negCheckP s => wordUnaryP s | Word_notb s => wordUnary s | Word_orb s => wordBinary s | Word_quot (s, _) => wordBinary s @@ -652,6 +665,7 @@ fun checkPrimApp {args, prim, result} = | Word_rshift (s, _) => wordShift s | Word_sub s => wordBinary s | Word_subCheck (s, _) => wordBinary s + | Word_subCheckP (s, _) => wordBinaryP s | Word_xorb s => wordBinary s | _ => Error.bug (concat ["RepType.checkPrimApp got strange prim: ", Prim.toString prim]) diff --git a/mlton/codegen/amd64-codegen/amd64-mlton-basic.fun b/mlton/codegen/amd64-codegen/amd64-mlton-basic.fun index 78feef44ee..99281b83aa 100644 --- a/mlton/codegen/amd64-codegen/amd64-mlton-basic.fun +++ b/mlton/codegen/amd64-codegen/amd64-mlton-basic.fun @@ -231,6 +231,13 @@ struct class = Classes.StaticTemp} fun fpeqTempContentsOperand size = Operand.memloc (fpeqTempContents size) + val overflowCheckTemp = Label.fromString "overflowCheckTemp" + fun overflowCheckTempContents size + = makeContents {base = Immediate.label overflowCheckTemp, + size = size, + class = Classes.StaticTemp} + fun overflowCheckTempContentsOperand size + = Operand.memloc (overflowCheckTempContents size) local fun make prefix = diff --git a/mlton/codegen/amd64-codegen/amd64-mlton-basic.sig b/mlton/codegen/amd64-codegen/amd64-mlton-basic.sig index 2fa7281202..3977e62261 100644 --- a/mlton/codegen/amd64-codegen/amd64-mlton-basic.sig +++ b/mlton/codegen/amd64-codegen/amd64-mlton-basic.sig @@ -90,6 +90,7 @@ signature AMD64_MLTON_BASIC = val applyFFTempXmmRegArgContents : amd64.Size.t * int -> amd64.MemLoc.t val fpcvtTempContentsOperand : amd64.Operand.t val fpeqTempContentsOperand : amd64.Size.t -> amd64.Operand.t + val overflowCheckTempContentsOperand : amd64.Size.t -> amd64.Operand.t (* Static arrays defined in main.h and amd64-main.h *) val local_base : amd64.CType.t -> amd64.Label.t diff --git a/mlton/codegen/amd64-codegen/amd64-mlton.fun b/mlton/codegen/amd64-codegen/amd64-mlton.fun index e1232f241d..df0cbe539e 100644 --- a/mlton/codegen/amd64-codegen/amd64-mlton.fun +++ b/mlton/codegen/amd64-codegen/amd64-mlton.fun @@ -82,6 +82,7 @@ struct | Thread_returnToC => false | Word_add _ => true | Word_addCheck _ => true + | Word_addCheckP _ => true | Word_andb _ => true | Word_castToReal _ => true | Word_equal _ => true @@ -90,8 +91,10 @@ struct | Word_lt _ => true | Word_mul _ => true | Word_mulCheck _ => true + | Word_mulCheckP _ => true | Word_neg _ => true | Word_negCheck _ => true + | Word_negCheckP _ => true | Word_notb _ => true | Word_orb _ => true | Word_quot _ => true @@ -102,6 +105,7 @@ struct | Word_rshift _ => true | Word_sub _ => true | Word_subCheck _ => true + | Word_subCheckP _ => true | Word_xorb _ => true | _ => false end @@ -245,6 +249,61 @@ struct transfer = NONE}] end + fun binalcc (oper, condition) + = let + val ((src1,src1size), + (src2,src2size)) = getSrc2 () + val (dst,dstsize) = getDst1 () + val (tmp,tmpsize) = (overflowCheckTempContentsOperand src1size, + src1size) + val _ + = Assert.assert + ("amd64MLton.prim: binalcc, src1size/src2size", + fn () => src1size = src2size) + + (* Reverse src1/src2 when src1 and src2 are temporaries + * and the oper is commutative. + *) + val (src1,src2) + = if (oper = Instruction.ADD) + orelse + (oper = Instruction.ADC) + orelse + (oper = Instruction.AND) + orelse + (oper = Instruction.OR) + orelse + (oper = Instruction.XOR) + then case (Operand.deMemloc src1, Operand.deMemloc src2) + of (SOME memloc_src1, SOME memloc_src2) + => if amd64Liveness.track memloc_src1 + andalso + amd64Liveness.track memloc_src2 + then (src2,src1) + else (src1,src2) + | _ => (src1,src2) + else (src1,src2) + in + AppendList.fromList + [Block.mkBlock' + {entry = NONE, + statements + = [Assembly.instruction_mov + {dst = tmp, + src = src1, + size = src1size}, + Assembly.instruction_binal + {oper = oper, + dst = tmp, + src = src2, + size = src1size}, + Assembly.instruction_setcc + {condition = condition, + dst = dst, + size = dstsize}], + transfer = NONE}] + end + fun pmd oper = let val ((src1,src1size), @@ -289,6 +348,55 @@ struct transfer = NONE}] end + fun pmdcc (oper, condition) + = let + val ((src1,src1size), + (src2,src2size)) = getSrc2 () + val (dst,dstsize) = getDst1 () + val (tmp,tmpsize) = (overflowCheckTempContentsOperand src1size, + src1size) + val _ + = Assert.assert + ("amd64MLton.prim: pmdcc, src1size/src2size", + fn () => src1size = src2size) + + (* Reverse src1/src2 when src1 and src2 are temporaries + * and the oper is commutative. + *) + val (src1,src2) + = if (oper = Instruction.IMUL) + orelse + (oper = Instruction.MUL) + then case (Operand.deMemloc src1, Operand.deMemloc src2) + of (SOME memloc_src1, SOME memloc_src2) + => if amd64Liveness.track memloc_src1 + andalso + amd64Liveness.track memloc_src2 + then (src2,src1) + else (src1,src2) + | _ => (src1,src2) + else (src1,src2) + in + AppendList.fromList + [Block.mkBlock' + {entry = NONE, + statements + = [Assembly.instruction_mov + {dst = tmp, + src = src1, + size = src1size}, + Assembly.instruction_pmd + {oper = oper, + dst = tmp, + src = src2, + size = tmpsize}, + Assembly.instruction_setcc + {condition = condition, + dst = dst, + size = dstsize}], + transfer = NONE}] + end + fun imul2 () = let val ((src1,src1size), @@ -328,6 +436,50 @@ struct transfer = NONE}] end + fun imul2cc condition + = let + val ((src1,src1size), + (src2,src2size)) = getSrc2 () + val (dst,dstsize) = getDst1 () + val (tmp,tmpsize) = (overflowCheckTempContentsOperand src1size, + src1size) + val _ + = Assert.assert + ("amd64MLton.prim: imul2cc, src1size/src2size", + fn () => src1size = src2size) + + (* Reverse src1/src2 when src1 and src2 are temporaries + * and the oper is commutative. + *) + val (src1,src2) + = case (Operand.deMemloc src1, Operand.deMemloc src2) + of (SOME memloc_src1, SOME memloc_src2) + => if amd64Liveness.track memloc_src1 + andalso + amd64Liveness.track memloc_src2 + then (src2,src1) + else (src1,src2) + | _ => (src1,src2) + in + AppendList.fromList + [Block.mkBlock' + {entry = NONE, + statements + = [Assembly.instruction_mov + {dst = tmp, + src = src1, + size = src1size}, + Assembly.instruction_imul2 + {dst = tmp, + src = src2, + size = tmpsize}, + Assembly.instruction_setcc + {dst = dst, + condition = condition, + size = dstsize}], + transfer = NONE}] + end + fun unal oper = let val (src,srcsize) = getSrc1 () @@ -352,6 +504,32 @@ struct transfer = NONE}] end + fun unalcc (oper, condition) + = let + val (src,srcsize) = getSrc1 () + val (dst,dstsize) = getDst1 () + val (tmp,tmpsize) = (overflowCheckTempContentsOperand srcsize, + srcsize) + in + AppendList.fromList + [Block.mkBlock' + {entry = NONE, + statements + = [Assembly.instruction_mov + {dst = tmp, + src = src, + size = srcsize}, + Assembly.instruction_unal + {oper = oper, + dst = tmp, + size = tmpsize}, + Assembly.instruction_setcc + {condition = condition, + dst = dst, + size = dstsize}], + transfer = NONE}] + end + fun sral oper = let val (dst,dstsize) = getDst1 () @@ -650,6 +828,9 @@ struct transfer = NONE})) end else (AppendList.empty,AppendList.empty) + + fun flag {signed} = + if signed then Instruction.O else Instruction.C in AppendList.appends [comment_begin, @@ -1032,6 +1213,7 @@ struct end | Real_sub _ => sse_binas Instruction.SSE_SUBS | Word_add _ => binal Instruction.ADD + | Word_addCheckP (_, sg) => binalcc (Instruction.ADD, flag sg) | Word_andb _ => binal Instruction.AND | Word_castToReal _ => sse_movd () | Word_equal _ => cmp Instruction.E @@ -1045,7 +1227,20 @@ struct | W16 => imul2 () | W32 => imul2 () | W64 => imul2 ()) + | Word_mulCheckP (s, sg) => + let + val {signed} = sg + in + case WordSize.prim s of + W8 => pmdcc (if signed then Instruction.IMUL + else Instruction.MUL, + flag sg) + | W16 => imul2cc (flag sg) + | W32 => imul2cc (flag sg) + | W64 => imul2cc (flag sg) + end | Word_neg _ => unal Instruction.NEG + | Word_negCheckP _ => unalcc (Instruction.NEG, Instruction.O) | Word_notb _ => unal Instruction.NOT | Word_orb _ => binal Instruction.OR | Word_quot (_, {signed}) => @@ -1110,6 +1305,7 @@ struct | Word_rshift (_, {signed}) => sral (if signed then Instruction.SAR else Instruction.SHR) | Word_sub _ => binal Instruction.SUB + | Word_subCheckP (_, sg) => binalcc (Instruction.SUB, flag sg) | Word_extdToWord (s, s', {signed}) => let val b = WordSize.bits s From efef5dc466fc33349f374380bccbeac3b7a38949 Mon Sep 17 00:00:00 2001 From: Daman Morris Date: Mon, 25 Jun 2018 16:19:18 -0400 Subject: [PATCH 08/57] Use GCC builtins for overflow checking --- runtime/basis/Word/Word-check.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/runtime/basis/Word/Word-check.h b/runtime/basis/Word/Word-check.h index 83a8f5e139..1e95861f37 100644 --- a/runtime/basis/Word/Word-check.h +++ b/runtime/basis/Word/Word-check.h @@ -114,36 +114,36 @@ WordS_subCheckBodyCX(size, x, y, doOverflow, doSuccess) #define WordS_addCheckP(size) \ MLTON_CODEGEN_STATIC_INLINE \ Bool WordS##size##_addCheckP (WordS##size x, WordS##size y) { \ - WordS_addCheckBody(size, x, y, return TRUE, return FALSE); \ + return __builtin_add_overflow_p (x, y, (WordS##size) 0); \ } #define WordU_addCheckP(size) \ MLTON_CODEGEN_STATIC_INLINE \ Bool WordU##size##_addCheckP (WordU##size x, WordU##size y) { \ - WordU_addCheckBody(size, x, y, return TRUE, return FALSE); \ + return __builtin_add_overflow_p (x, y, (WordU##size) 0); \ } #define WordS_mulCheckP(size) \ MLTON_CODEGEN_STATIC_INLINE \ Bool WordS##size##_mulCheckP (WordS##size x, WordS##size y) { \ - WordS_mulCheckBody(size, x, y, return TRUE, return FALSE); \ + return __builtin_mul_overflow_p (x, y, (WordS##size) 0); \ } #define WordU_mulCheckP(size) \ MLTON_CODEGEN_STATIC_INLINE \ Bool WordU##size##_mulCheckP (WordU##size x, WordU##size y) { \ - WordU_mulCheckBody(size, x, y, return TRUE, return FALSE); \ + return __builtin_mul_overflow_p (x, y, (WordU##size) 0); \ } #define Word_negCheckP(size) \ MLTON_CODEGEN_STATIC_INLINE \ Bool Word##size##_negCheckP (WordS##size x) { \ - Word_negCheckBody(size, x, return TRUE, return FALSE); \ + return x == WordS##size##_min; \ } #define WordS_subCheckP(size) \ MLTON_CODEGEN_STATIC_INLINE \ Bool WordS##size##_subCheckP (WordS##size x, WordS##size y) { \ - WordS_subCheckBody(size, x, y, return TRUE, return FALSE); \ + return __builtin_sub_overflow_p (x, y, (WordS##size) 0); \ } #define all(size) \ From b05ba132b1f07ea37b24d3ad5344a208c0eeb45b Mon Sep 17 00:00:00 2001 From: Daman Morris Date: Mon, 25 Jun 2018 17:33:59 -0400 Subject: [PATCH 09/57] Add support for LLVM codegen --- mlton/codegen/llvm-codegen/llvm-codegen.fun | 39 +++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/mlton/codegen/llvm-codegen/llvm-codegen.fun b/mlton/codegen/llvm-codegen/llvm-codegen.fun index 6663991bbe..5a2f549f09 100644 --- a/mlton/codegen/llvm-codegen/llvm-codegen.fun +++ b/mlton/codegen/llvm-codegen/llvm-codegen.fun @@ -153,6 +153,7 @@ fun implementsPrim (p: 'a Prim.t): bool = | Thread_returnToC => false | Word_add _ => true | Word_addCheck _ => true + | Word_addCheckP _ => true | Word_andb _ => true | Word_castToReal _ => true | Word_equal _ => true @@ -170,8 +171,10 @@ fun implementsPrim (p: 'a Prim.t): bool = *) not (WordSize.equals (ws, WordSize.word64)) | _ => true) + | Word_mulCheckP _ => true (* TODO? *) | Word_neg _ => true | Word_negCheck _ => true + | Word_negCheckP _ => true | Word_notb _ => true | Word_orb _ => true | Word_quot _ => true @@ -182,6 +185,7 @@ fun implementsPrim (p: 'a Prim.t): bool = | Word_rshift _ => true | Word_sub _ => true | Word_subCheck _ => true + | Word_subCheckP _ => true | Word_xorb _ => true | _ => false end @@ -624,6 +628,21 @@ and getOperandValue (cxt, operand) = fun outputPrim (prim, res, argty, arg0, arg1, arg2) = let datatype z = datatype Prim.Name.t + + fun mkoverflowp (ws, intrinsic) = + let + val tmp1 = nextLLVMReg () + val tmp2 = nextLLVMReg () + val ty = llws ws + val oper = concat ["\t", tmp1, " = call {", ty, ", i1} @llvm.", + intrinsic, ".with.overflow.", llwsInt ws, "(", ty, + " ", arg0, ", ", ty, " ", arg1, ")\n"] + val extr = concat ["\t", tmp2, " = extractvalue {", ty, ", i1} ", tmp1, + ", 1\n"] + val ext = mkconv (res, "zext", "i1", tmp2, "%Word32") + in + (concat [oper, extr, ext], "%Word32") + end in case Prim.name prim of CPointer_add => @@ -799,6 +818,8 @@ fun outputPrim (prim, res, argty, arg0, arg1, arg2) = in (inst, concat ["{", ty, ", i1}"]) end + | Word_addCheckP (ws, {signed}) => + mkoverflowp (ws, if signed then "sadd" else "uadd") | Word_andb ws => (mkinst (res, "and", llws ws, arg0, arg1), llws ws) | Word_castToReal (ws, rs) => (case rs of @@ -846,6 +867,8 @@ fun outputPrim (prim, res, argty, arg0, arg1, arg2) = in (inst, concat ["{", ty, ", i1}"]) end + | Word_mulCheckP (ws, {signed}) => + mkoverflowp (ws, if signed then "smul" else "umul") | Word_neg ws => (mkinst (res, "sub", llws ws, "0", arg0), llws ws) | Word_negCheck ws => let @@ -856,6 +879,20 @@ fun outputPrim (prim, res, argty, arg0, arg1, arg2) = in (inst, resTy) end + | Word_negCheckP ws => + let + val ty = llws ws + val tmp1 = nextLLVMReg () + val tmp2 = nextLLVMReg () + val oper = concat ["\t", tmp1, " = call {", ty, + ", i1} @llvm.ssub.with.overflow.", llwsInt ws, + "(", ty, " 0, ", ty, " ", arg0, ")\n"] + val extr = concat ["\t", tmp2 , " = extractvalue {", ty, ", i1}", + tmp1, ", 1\n"] + val ext = mkconv (res, "zext", "i1", tmp2, "%Word32") + in + (concat [oper, extr, ext], "%Word32") + end | Word_notb ws => (mkinst (res, "xor", llws ws, arg0, "-1"), llws ws) | Word_orb ws => (mkinst (res, "or", llws ws, arg0, arg1), llws ws) | Word_quot (ws, {signed}) => @@ -913,6 +950,8 @@ fun outputPrim (prim, res, argty, arg0, arg1, arg2) = in (inst, concat ["{", ty, ", i1}"]) end + | Word_subCheckP (ws, {signed}) => + mkoverflowp (ws, if signed then "ssub" else "usub") | Word_xorb ws => (mkinst (res, "xor", llws ws, arg0, arg1), llws ws) | _ => Error.bug "LLVM Codegen: Unsupported operation in outputPrim" end From 819ddffb974a7a7efd737f15cf2cff4efa56aefe Mon Sep 17 00:00:00 2001 From: Daman Morris Date: Fri, 29 Jun 2018 12:59:57 -0400 Subject: [PATCH 10/57] Refactor checked word primitives for C codegen A previous change introduced the use of GCC builtins for overflow checking with the `newOverflow` flavor of checked primitive operations. However, these builtins are compatible only with GCC versions 7 and above, so to improve backwards compatibility a compatibility layer is added using the older builtins for legacy GCC versions. In addition, since much of the code for the new and old primitive operations was shared, this shared code is pulled into the compatibility layer (provided as `_overflow_b` macros). --- runtime/basis/Word/Word-check.h | 169 +++++++++++++++----------------- 1 file changed, 81 insertions(+), 88 deletions(-) diff --git a/runtime/basis/Word/Word-check.h b/runtime/basis/Word/Word-check.h index 1e95861f37..818f5f00e6 100644 --- a/runtime/basis/Word/Word-check.h +++ b/runtime/basis/Word/Word-check.h @@ -1,102 +1,93 @@ - -#define WordS_addCheckBody(size, x, y, doOverflow, doSuccess) \ +#if __GNUC__ < 7 +#define add_overflow_b(x, y, size, onOverflow, onSuccess) \ do { \ - if (x >= 0) { \ - if (y > WordS##size##_max - x) { \ - doOverflow; \ - } \ - } else if (y < WordS##size##_min - x) { \ - doOverflow; \ + WordS##size res; \ + if (__builtin_add_overflow(x, y, &res)) { \ + onOverflow; \ } \ - doSuccess; \ + onSuccess; \ } while (0) -#define WordS_addCheckBodyCX(size, c, x, doOverflow, doSuccess) \ -WordS_addCheckBody(size, c, x, doOverflow, doSuccess) - -#define WordU_addCheckBody(size, x, y, doOverflow, doSuccess) \ +#define sub_overflow_b(x, y, size, onOverflow, onSuccess) \ do { \ - if (y > Word##size##_max - x) { \ - doOverflow; \ + WordS##size res; \ + if (__builtin_sub_overflow(x, y, &res)) { \ + onOverflow; \ } \ - doSuccess; \ + onSuccess; \ } while (0) -#define WordU_addCheckBodyCX(size, c, x, doOverflow, doSuccess) \ -WordU_addCheckBody(size, c, x, doOverflow, doSuccess) - -#define WordS_mulCheckBody(size, x, y, doOverflow, doSuccess) \ +#define mul_overflow_b(x, y, size, onOverflow, onSuccess) \ do { \ - if ((x == (WordS##size)0) || (y == (WordS##size)0)) { \ - } else \ - if (x > (WordS## size)0) { \ - if (y > (WordS##size)0) { \ - if (x > WordS##size##_quot (WordS##size##_max, y)) { \ - doOverflow; \ - } \ - } else /* (y < (WordS##size)0) */ { \ - if (y < WordS##size##_quot (WordS##size##_min, x)) { \ - doOverflow; \ - } \ - } \ - } else /* (x < (WordS##size)0) */ { \ - if (y > (WordS##size)0) { \ - if (x < WordS##size##_quot (WordS##size##_min, y)) { \ - doOverflow; \ - } \ - } else /* (y < (WordS##size)0) */ { \ - if (y < WordS##size##_quot (WordS##size##_max, x)) { \ - doOverflow; \ - } \ - } \ + WordS##size res; \ + if (__builtin_mul_overflow(x, y, &res)) { \ + onOverflow; \ } \ - doSuccess; \ + onSuccess; \ } while (0) -// #undef WordS_mulCheckBody -#define WordU_mulCheckBody(size, x, y, doOverflow, doSuccess) \ +#else +#define add_overflow_b(x, y, size, onOverflow, onSuccess) \ do { \ - if ((x == (WordU##size)0) || (y == (WordU##size)0)) { \ - } else \ - if (x > WordU##size##_quot (Word##size##_max, y)) { \ - doOverflow; \ + if (__builtin_add_overflow_p(x, y, (WordS##size) 0)) { \ + onOverflow; \ } \ - doSuccess; \ + onSuccess; \ } while (0) -// #undef WordU_mulCheckBody -/* #define Word_mulCheckBody(small, large, x, y, doOverflow, doSuccess) \ */ -/* do { \ */ -/* Word##large tmp; \ */ -/* Word##small res; \ */ -/* tmp = ((Word##large)x) * ((Word##large)y); \ */ -/* res = (Word##small)tmp; \ */ -/* if (tmp != res) { \ */ -/* doOverflow; \ */ -/* } \ */ -/* doSuccess; \ */ -/* } while (0) */ -/* #define WordS_mulCheckBody(small, large, x, y, doOverflow, doSuccess) \ */ -/* Word_mulCheckBody(S##small, S##large, x, y, doOverflow, doSuccess) */ -/* #define WordU_mulCheckBody(small, large, x, y, doOverflow, doSuccess) \ */ -/* Word_mulCheckBody(U##small, U##large, x, y, doOverflow, doSuccess) */ - -#define Word_negCheckBody(size, x, doOverflow, doSuccess) \ +#define sub_overflow_b(x, y, size, onOverflow, onSuccess) \ do { \ - if (x == WordS##size##_min) { \ - doOverflow; \ + if (__builtin_sub_overflow_p(x, y, (WordS##size) 0)) { \ + onOverflow; \ } \ - doSuccess; \ + onSuccess; \ } while (0) - -#define WordS_subCheckBodyCX(size, c, x, doOverflow, doSuccess) \ +#define mul_overflow_b(x, y, size, onOverflow, onSuccess) \ do { \ - if (c >= 0) { \ - if (x < c - WordS##size##_max) { \ - doOverflow; \ - } \ - } else if (x > c - WordS##size##_min) { \ - doOverflow; \ + if (__builtin_mul_overflow_p(x, y, (WordS##size) 0)) { \ + onOverflow; \ } \ - doSuccess; \ + onSuccess; \ } while (0) +#endif +#define neg_overflow_b(x, size, onOverflow, onSuccess) \ + do { \ + if (x == WordS##size##_min) { \ + onOverflow; \ + } \ + onSuccess; \ + } while (0) \ + +/** + * Old-style overflow operators + */ + +#define WordS_addCheckBody(size, x, y, doOverflow, doSuccess) \ + add_overflow_b(x, y, size, doOverflow, doSuccess) +#define WordS_addCheckBodyCX(size, c, x, doOverflow, doSuccess) \ + WordS_addCheckBody(size, c, x, doOverflow, doSuccess) + +#define WordU_addCheckBody(size, x, y, doOverflow, doSuccess) \ + add_overflow_b(x, y, size, doOverflow, doSuccess) +#define WordU_addCheckBodyCX(size, c, x, doOverflow, doSuccess) \ + WordU_addCheckBody(size, c, x, doOverflow, doSuccess) + +#define WordS_mulCheckBody(size, x, y, doOverflow, doSuccess) \ + mul_overflow_b(x, y, size, doOverflow, doSuccess) + +#define WordU_mulCheckBody(size, x, y, doOverflow, doSuccess) \ + mul_overflow_b(x, y, size, doOverflow, doSuccess) + +#define WordS_negCheckBody(size, x, doOverflow, doSuccess) \ + neg_overflow_b(x, y, size, doOverflow, doSuccess) + +#define WordS_subCheckBody(size, x, y, doOverflow, doSuccess) \ + sub_overflow_b(x, y, size, doOverflow, doSuccess) +#define WordS_subCheckBodyCX(size, c, x, doOverflow, doSuccess) \ + WordS_subCheckBody(size, c, x, doOverflow, doSuccess) + #define WordS_subCheckBodyXC(size, x, c, doOverflow, doSuccess) \ + WordS_subCheckBody(size, x, c, doOverflow, doSuccess) + +/* + * Old WordS_subCheckBodyXC: + * do { \ if (c <= 0) { \ if (x > WordS##size##_max + c) { \ @@ -107,43 +98,45 @@ WordU_addCheckBody(size, c, x, doOverflow, doSuccess) } \ doSuccess; \ } while (0) -#define WordS_subCheckBody(size, x, y, doOverflow, doSuccess) \ -WordS_subCheckBodyCX(size, x, y, doOverflow, doSuccess) + */ +/** + * New-style overflow operators + */ #define WordS_addCheckP(size) \ MLTON_CODEGEN_STATIC_INLINE \ Bool WordS##size##_addCheckP (WordS##size x, WordS##size y) { \ - return __builtin_add_overflow_p (x, y, (WordS##size) 0); \ + add_overflow_b(x, y, size, return TRUE, return FALSE); \ } #define WordU_addCheckP(size) \ MLTON_CODEGEN_STATIC_INLINE \ Bool WordU##size##_addCheckP (WordU##size x, WordU##size y) { \ - return __builtin_add_overflow_p (x, y, (WordU##size) 0); \ + add_overflow_b(x, y, size, return TRUE, return FALSE); \ } #define WordS_mulCheckP(size) \ MLTON_CODEGEN_STATIC_INLINE \ Bool WordS##size##_mulCheckP (WordS##size x, WordS##size y) { \ - return __builtin_mul_overflow_p (x, y, (WordS##size) 0); \ + mul_overflow_b(x, y, size, return TRUE, return FALSE); \ } #define WordU_mulCheckP(size) \ MLTON_CODEGEN_STATIC_INLINE \ Bool WordU##size##_mulCheckP (WordU##size x, WordU##size y) { \ - return __builtin_mul_overflow_p (x, y, (WordU##size) 0); \ + mul_overflow_b(x, y, size, return TRUE, return FALSE); \ } #define Word_negCheckP(size) \ MLTON_CODEGEN_STATIC_INLINE \ Bool Word##size##_negCheckP (WordS##size x) { \ - return x == WordS##size##_min; \ + neg_overflow_b(x, size, return TRUE, return FALSE); \ } #define WordS_subCheckP(size) \ MLTON_CODEGEN_STATIC_INLINE \ Bool WordS##size##_subCheckP (WordS##size x, WordS##size y) { \ - return __builtin_sub_overflow_p (x, y, (WordS##size) 0); \ + sub_overflow_b(x, y, size, return TRUE, return FALSE); \ } #define all(size) \ From 8de2d7c8e0d8c38ff9c1da2adf7d891d9615fd43 Mon Sep 17 00:00:00 2001 From: Daman Morris Date: Fri, 29 Jun 2018 13:12:56 -0400 Subject: [PATCH 11/57] Correct typo in `neg_overflow_b` application --- runtime/basis/Word/Word-check.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/basis/Word/Word-check.h b/runtime/basis/Word/Word-check.h index 818f5f00e6..4748ab468d 100644 --- a/runtime/basis/Word/Word-check.h +++ b/runtime/basis/Word/Word-check.h @@ -75,7 +75,7 @@ mul_overflow_b(x, y, size, doOverflow, doSuccess) #define WordS_negCheckBody(size, x, doOverflow, doSuccess) \ - neg_overflow_b(x, y, size, doOverflow, doSuccess) + neg_overflow_b(x, size, doOverflow, doSuccess) #define WordS_subCheckBody(size, x, y, doOverflow, doSuccess) \ sub_overflow_b(x, y, size, doOverflow, doSuccess) From edafb83a08375e983f5875382d64d2434f2202fd Mon Sep 17 00:00:00 2001 From: Daman Morris Date: Thu, 5 Jul 2018 12:46:40 -0400 Subject: [PATCH 12/57] Add overflowCheckTemp storage for x86 codegen --- include/x86-main.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/x86-main.h b/include/x86-main.h index c1790a755d..0c2175d6c9 100644 --- a/include/x86-main.h +++ b/include/x86-main.h @@ -21,6 +21,7 @@ PRIVATE Word32 divTemp; PRIVATE Word32 fildTemp; PRIVATE Word32 fpswTemp; PRIVATE Word32 indexTemp; +PRIVATE Word32 overflowCheckTemp; PRIVATE Word32 raTemp1; PRIVATE Real64 raTemp2; PRIVATE Real64 realTemp1D; From 87ea212512fe78bede4180522dc566247431e420 Mon Sep 17 00:00:00 2001 From: Daman Morris Date: Thu, 5 Jul 2018 14:23:20 -0400 Subject: [PATCH 13/57] Make negCheckP use `0-x` for bounds checking --- runtime/basis/Word/Word-check.h | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/runtime/basis/Word/Word-check.h b/runtime/basis/Word/Word-check.h index 4748ab468d..62d0eecd6d 100644 --- a/runtime/basis/Word/Word-check.h +++ b/runtime/basis/Word/Word-check.h @@ -47,12 +47,7 @@ } while (0) #endif #define neg_overflow_b(x, size, onOverflow, onSuccess) \ - do { \ - if (x == WordS##size##_min) { \ - onOverflow; \ - } \ - onSuccess; \ - } while (0) \ + sub_overflow_b(0, x, size, onOverflow, onSuccess) /** * Old-style overflow operators From 4a32966ddd6b0e86e9bda3eeeccb3807658b25c8 Mon Sep 17 00:00:00 2001 From: Daman Morris Date: Fri, 6 Jul 2018 13:46:05 -0400 Subject: [PATCH 14/57] Add support for x86 codegen --- mlton/codegen/x86-codegen/x86-mlton-basic.fun | 8 + mlton/codegen/x86-codegen/x86-mlton-basic.sig | 1 + mlton/codegen/x86-codegen/x86-mlton.fun | 350 ++++++++++++++++++ 3 files changed, 359 insertions(+) diff --git a/mlton/codegen/x86-codegen/x86-mlton-basic.fun b/mlton/codegen/x86-codegen/x86-mlton-basic.fun index d80bd298bd..63b480c8c4 100644 --- a/mlton/codegen/x86-codegen/x86-mlton-basic.fun +++ b/mlton/codegen/x86-codegen/x86-mlton-basic.fun @@ -190,6 +190,14 @@ struct val applyFFTempArgContentsOperand = Operand.memloc applyFFTempArgContents + val overflowCheckTemp = Label.fromString "overflowCheckTemp" + fun overflowCheckTempContents size + = makeContents {base = Immediate.label overflowCheckTemp, + size = size, + class = Classes.StaticTemp} + fun overflowCheckTempContentsOperand size + = Operand.memloc (overflowCheckTempContents size) + val realTemp1D = Label.fromString "realTemp1D" val realTemp1ContentsD = makeContents {base = Immediate.label realTemp1D, diff --git a/mlton/codegen/x86-codegen/x86-mlton-basic.sig b/mlton/codegen/x86-codegen/x86-mlton-basic.sig index 4f649f5b68..d163d3a7c0 100644 --- a/mlton/codegen/x86-codegen/x86-mlton-basic.sig +++ b/mlton/codegen/x86-codegen/x86-mlton-basic.sig @@ -88,6 +88,7 @@ signature X86_MLTON_BASIC = (* Static temps defined in x86-main.h *) val applyFFTempFunContentsOperand : x86.Operand.t val applyFFTempArgContentsOperand : x86.Operand.t + val overflowCheckTempContentsOperand : x86.Size.t -> x86.Operand.t val realTemp1ContentsOperand : x86.Size.t -> x86.Operand.t val realTemp2ContentsOperand : x86.Size.t -> x86.Operand.t val realTemp3ContentsOperand : x86.Size.t -> x86.Operand.t diff --git a/mlton/codegen/x86-codegen/x86-mlton.fun b/mlton/codegen/x86-codegen/x86-mlton.fun index e32fa930fe..8e5ac5fbda 100644 --- a/mlton/codegen/x86-codegen/x86-mlton.fun +++ b/mlton/codegen/x86-codegen/x86-mlton.fun @@ -81,6 +81,7 @@ struct | Thread_returnToC => false | Word_add _ => true | Word_addCheck _ => true + | Word_addCheckP _ => true | Word_andb _ => true | Word_castToReal _ => false (* !! *) | Word_equal s => w32168 s @@ -89,8 +90,10 @@ struct | Word_lt (s, _) => w32168 s | Word_mul (s, _) => w32168 s | Word_mulCheck (s, _) => w32168 s + | Word_mulCheckP (s, _) => w32168 s | Word_neg _ => true | Word_negCheck _ => true + | Word_negCheckP _ => true | Word_notb _ => true | Word_orb _ => true | Word_quot (s, _) => w32168 s @@ -101,6 +104,7 @@ struct | Word_rshift (s, _) => w32168 s | Word_sub _ => true | Word_subCheck _ => true + | Word_subCheckP _ => true | Word_xorb _ => true | _ => false end @@ -251,6 +255,61 @@ struct transfer = NONE}] end + fun binalcc (oper, condition) + = let + val ((src1,src1size), + (src2,src2size)) = getSrc2 () + val (dst,dstsize) = getDst1 () + val (tmp,tmpsize) = (overflowCheckTempContentsOperand src1size, + src1size) + val _ + = Assert.assert + ("x86MLton.prim: binal, src1size/src2size", + fn () => src1size = src2size) + + (* Reverse src1/src2 when src1 and src2 are temporaries + * and the oper is commutative. + *) + val (src1,src2) + = if (oper = Instruction.ADD) + orelse + (oper = Instruction.ADC) + orelse + (oper = Instruction.AND) + orelse + (oper = Instruction.OR) + orelse + (oper = Instruction.XOR) + then case (Operand.deMemloc src1, Operand.deMemloc src2) + of (SOME memloc_src1, SOME memloc_src2) + => if x86Liveness.track memloc_src1 + andalso + x86Liveness.track memloc_src2 + then (src2,src1) + else (src1,src2) + | _ => (src1,src2) + else (src1,src2) + in + AppendList.fromList + [Block.mkBlock' + {entry = NONE, + statements + = [Assembly.instruction_mov + {dst = tmp, + src = src1, + size = src1size}, + Assembly.instruction_binal + {oper = oper, + dst = tmp, + src = src2, + size = tmpsize}, + Assembly.instruction_setcc + {condition = condition, + dst = dst, + size = dstsize}], + transfer = NONE}] + end + fun binal64 (oper1, oper2) = let val ((src1,src1size), @@ -311,6 +370,39 @@ struct transfer = NONE}] end + fun binal64cc (oper, condition) + = let + val ((src1,src1size), _, + (src3,src3size), _) = getSrc4 () + val (dst,dstsize) = getDst1 () + val (tmp,tmpsize) = (overflowCheckTempContentsOperand src1size, + src1size) + val _ + = Assert.assert + ("x86MLton.prim: binal64cc, src1size/src3size", + fn () => src1size = src3size) + in + AppendList.fromList + [Block.mkBlock' + {entry = NONE, + statements + = [Assembly.instruction_mov + {dst = tmp, + src = src1, + size = tmpsize}, + Assembly.instruction_binal + {oper = oper, + dst = tmp, + src = src3, + size = tmpsize}, + Assembly.instruction_setcc + {condition = condition, + dst = dst, + size = dstsize}], + transfer = NONE}] + end + + fun pmd oper = let val ((src1,src1size), @@ -355,6 +447,56 @@ struct transfer = NONE}] end + fun pmdcc (oper, condition) + = let + val ((src1,src1size), + (src2,src2size)) = getSrc2 () + val (dst,dstsize) = getDst1 () + val (tmp,tmpsize) = (overflowCheckTempContentsOperand src1size, + src1size) + val _ + = Assert.assert + ("x86MLton.prim: pmdcc, src1size/src2size", + fn () => src1size = src2size) + + (* Reverse src1/src2 when src1 and src2 are temporaries + * and the oper is commutative. + *) + val (src1,src2) + = if (oper = Instruction.IMUL) + orelse + (oper = Instruction.MUL) + then case (Operand.deMemloc src1, Operand.deMemloc src2) + of (SOME memloc_src1, SOME memloc_src2) + => if x86Liveness.track memloc_src1 + andalso + x86Liveness.track memloc_src2 + then (src2,src1) + else (src1,src2) + | _ => (src1,src2) + else (src1,src2) + in + AppendList.fromList + [Block.mkBlock' + {entry = NONE, + statements + = [Assembly.instruction_mov + {dst = tmp, + src = src1, + size = tmpsize}, + Assembly.instruction_pmd + {oper = oper, + dst = tmp, + src = src2, + size = tmpsize}, + Assembly.instruction_setcc + {condition = condition, + dst = dst, + size = dstsize}], + transfer = NONE}] + end + + fun imul2 () = let val ((src1,src1size), @@ -394,6 +536,120 @@ struct transfer = NONE}] end + fun imul2cc condition + = let + val ((src1,src1size), + (src2,src2size)) = getSrc2 () + val (dst,dstsize) = getDst1 () + val (tmp,tmpsize) = (overflowCheckTempContentsOperand src1size, + src1size) + val _ + = Assert.assert + ("x86MLton.prim: imul2, src1size/src2size", + fn () => src1size = src2size) + + (* Reverse src1/src2 when src1 and src2 are temporaries + * and the oper is commutative. + *) + val (src1,src2) + = case (Operand.deMemloc src1, Operand.deMemloc src2) + of (SOME memloc_src1, SOME memloc_src2) + => if x86Liveness.track memloc_src1 + andalso + x86Liveness.track memloc_src2 + then (src2,src1) + else (src1,src2) + | _ => (src1,src2) + in + AppendList.fromList + [Block.mkBlock' + {entry = NONE, + statements + = [Assembly.instruction_mov + {dst = tmp, + src = src1, + size = tmpsize}, + Assembly.instruction_imul2 + {dst = tmp, + src = src2, + size = tmpsize}, + Assembly.instruction_setcc + {condition = condition, + dst = dst, + size = dstsize}], + transfer = NONE}] + end + + fun negalcc () + = let + val (src,srcsize) = getSrc1 () + val (dst,dstsize) = getDst1 () + val (tmp,tmpsize) = (overflowCheckTempContentsOperand srcsize, + srcsize) + in + AppendList.fromList + [Block.mkBlock' + {entry = NONE, + statements + = [Assembly.instruction_mov + {dst = tmp, + src = Operand.immediate_zero, + size = tmpsize}, + Assembly.instruction_binal + {oper = Instruction.SUB, + dst = tmp, + src = src, + size = srcsize}, + Assembly.instruction_setcc + {condition = Instruction.O, + dst = dst, + size = dstsize}], + transfer = NONE}] + end + + fun negal64cc () + = let + val ((src1,src1size), + (src2,src2size)) = getSrc2 () + val (dst,dstsize) = getDst1 () + val (tmp,tmpsize) = (overflowCheckTempContentsOperand src1size, + src1size) + val _ + = Assert.assert + ("x86MLton.prim: negal64cc, src1size/src2size", + fn () => src1size = src2size) + val tdst1 = wordTemp1ContentsOperand src1size + val tdst2 = wordTemp1ContentsOperand src2size + in + AppendList.fromList + [Block.mkBlock' + {entry = NONE, + statements + = [Assembly.instruction_mov + {dst = tdst1, + src = Operand.immediate_zero, + size = src1size}, + Assembly.instruction_mov + {dst = tdst2, + src = Operand.immediate_zero, + size = src2size}, + Assembly.instruction_binal + {oper = Instruction.SUB, + dst = tdst1, + src = src1, + size = src1size}, + Assembly.instruction_binal + {oper = Instruction.SBB, + dst = tdst2, + src = src2, + size = src2size}, + Assembly.instruction_setcc + {condition = Instruction.O, + dst = dst, + size = dstsize}], + transfer = NONE}] + end + fun unal oper = let val (src,srcsize) = getSrc1 () @@ -418,6 +674,32 @@ struct transfer = NONE}] end + fun unalcc (oper, condition) + = let + val (src,srcsize) = getSrc1 () + val (dst,dstsize) = getDst1 () + val (tmp,tmpsize) = (overflowCheckTempContentsOperand srcsize, + srcsize) + in + AppendList.fromList + [Block.mkBlock' + {entry = NONE, + statements + = [Assembly.instruction_mov + {dst = tmp, + src = src, + size = tmpsize}, + Assembly.instruction_unal + {oper = oper, + dst = tmp, + size = tmpsize}, + Assembly.instruction_setcc + {condition = condition, + dst = dst, + size = dstsize}], + transfer = NONE}] + end + fun unal64 (oper, mk) = let val ((src1,src1size),(src2,src2size)) = getSrc2 () @@ -462,6 +744,33 @@ struct transfer = NONE}] end + fun unal64cc (oper, condition) + = let + val ((src1,src1size),_) = getSrc2 () + val (dst,dstsize) = getDst1 () + val (tmp,tmpsize) = (overflowCheckTempContentsOperand src1size, + src1size) + in + AppendList.fromList + [Block.mkBlock' + {entry = NONE, + statements + = [Assembly.instruction_mov + {dst = tmp, + src = src1, + size = src1size}, + Assembly.instruction_unal + {oper = oper, + dst = tmp, + size = tmpsize}, + Assembly.instruction_setcc + {condition = condition, + dst = dst, + size = dstsize}], + transfer = NONE}] + end + + fun sral oper = let val (dst,dstsize) = getDst1 () @@ -704,6 +1013,9 @@ struct | W16 => sral i | W32 => sral i | W64 => Error.bug "x86MLton.prim: shift, W64" + + fun flag {signed} = + if signed then x86.Instruction.O else x86.Instruction.C in AppendList.appends [comment_begin, @@ -1342,6 +1654,16 @@ struct | W16 => binal Instruction.ADD | W32 => binal Instruction.ADD | W64 => binal64 (Instruction.ADD, Instruction.ADC)) + | Word_addCheckP (s, sg) => + let + val cond = flag sg + in + case WordSize.prim s of + W8 => binalcc (Instruction.ADD, cond) + | W16 => binalcc (Instruction.ADD, cond) + | W32 => binalcc (Instruction.ADD, cond) + | W64 => binal64cc (Instruction.ADD, cond) + end | Word_andb s => bitop (s, Instruction.AND) | Word_equal _ => cmp Instruction.E | Word_lshift s => shift (s, Instruction.SHL) @@ -1354,6 +1676,18 @@ struct | W16 => imul2 () | W32 => imul2 () | W64 => Error.bug "x86MLton.prim: Word_mul, W64") + | Word_mulCheckP (s, {signed}) => + let + val cond = flag {signed = signed} + in + case WordSize.prim s of + W8 => pmdcc (if signed + then Instruction.IMUL + else Instruction.MUL, cond) + | W16 => imul2cc cond + | W32 => imul2cc cond + | W64 => Error.bug "x86MLton.prim: Word_mulCheckP, W64" + end | Word_neg s => (case WordSize.prim s of W8 => unal Instruction.NEG @@ -1365,6 +1699,12 @@ struct oper = Instruction.ADC, src = Operand.immediate_zero, size = dstsize}])) + | Word_negCheckP s => + (case WordSize.prim s of + W8 => negalcc () + | W16 => negalcc () + | W32 => negalcc () + | W64 => negal64cc ()) | Word_notb s => (case WordSize.prim s of W8 => unal Instruction.NOT @@ -1386,6 +1726,16 @@ struct | W16 => binal Instruction.SUB | W32 => binal Instruction.SUB | W64 => binal64 (Instruction.SUB, Instruction.SBB)) + | Word_subCheckP (s, sg) => + let + val cond = flag sg + in + case WordSize.prim s of + W8 => binalcc (Instruction.SUB, cond) + | W16 => binalcc (Instruction.SUB, cond) + | W32 => binalcc (Instruction.SUB, cond) + | W64 => binal64cc (Instruction.SUB, cond) + end | Word_rndToReal (s, s', _) => let fun default () = From a68f2092b582f866a83c120e08b7230d881879bc Mon Sep 17 00:00:00 2001 From: Daman Morris Date: Mon, 9 Jul 2018 09:58:46 -0400 Subject: [PATCH 15/57] Use GCC builtins in implementation of word prims --- runtime/basis/Word/Word-ops.h | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/runtime/basis/Word/Word-ops.h b/runtime/basis/Word/Word-ops.h index 7ab3bd1198..1b85201b13 100644 --- a/runtime/basis/Word/Word-ops.h +++ b/runtime/basis/Word/Word-ops.h @@ -5,10 +5,22 @@ return w1 op w2; \ } +#define binaryBuiltin(kind, name, builtin) \ + MLTON_CODEGEN_STATIC_INLINE \ + Word##kind Word##kind##_##name (Word##kind w1, Word##kind w2) { \ + Word##kind res; \ + __builtin_##builtin##_overflow(w1, w2, &res); \ + return res; \ + } + #define bothBinary(size, name, op) \ binary (S##size, name, op) \ binary (U##size, name, op) +#define bothBinaryBuiltin(size, name, builtin) \ + binaryBuiltin(S##size, name, builtin) \ + binaryBuiltin(U##size, name, builtin) + #define compare(kind, name, op) \ MLTON_CODEGEN_STATIC_INLINE \ Bool Word##kind##_##name (Word##kind w1, Word##kind w2) { \ @@ -62,7 +74,7 @@ compare (U##size, name, op) } #define all(size) \ -binary (size, add, +) \ +binaryBuiltin (size, add, add) \ binary (size, andb, &) \ compare (size, equal, ==) \ bothCompare (size, ge, >=) \ @@ -70,7 +82,7 @@ bothCompare (size, gt, >) \ bothCompare (size, le, <=) \ shift (size, lshift, <<) \ bothCompare (size, lt, <) \ -bothBinary (size, mul, *) \ +bothBinaryBuiltin (size, mul, mul) \ unary (size, neg, -) \ unary (size, notb, ~) \ /* WordS_quot and WordS_rem can't be inlined with the C-codegen, \ @@ -89,7 +101,7 @@ ror(size) \ */ \ shift (S##size, rshift, >>) \ shift (U##size, rshift, >>) \ -binary (size, sub, -) \ +binaryBuiltin (size, sub, sub) \ binary (size, xorb, ^) all (8) From 1822eb4aa877c31b1f58155ced4f6285f5d426ea Mon Sep 17 00:00:00 2001 From: Daman Morris Date: Tue, 10 Jul 2018 11:34:18 -0400 Subject: [PATCH 16/57] Add support for new primitives in redundantTests --- mlton/ssa/redundant-tests.fun | 152 +++++++++++++++++++++++++--------- 1 file changed, 115 insertions(+), 37 deletions(-) diff --git a/mlton/ssa/redundant-tests.fun b/mlton/ssa/redundant-tests.fun index 773834ff0f..93ea0785c3 100644 --- a/mlton/ssa/redundant-tests.fun +++ b/mlton/ssa/redundant-tests.fun @@ -147,8 +147,8 @@ fun transform (Program.T {globals, datatypes, functions, main}) = exp = ConApp {con = c, args = Vector.new0 ()}}) end in - val (trueVar, t) = make Con.truee - val (falseVar, f) = make Con.falsee + val (trueVar, trueStmt) = make Con.truee + val (falseVar, falseStmt) = make Con.falsee end local val statements = ref [] @@ -169,7 +169,8 @@ fun transform (Program.T {globals, datatypes, functions, main}) = end) val ones = Vector.fromList (!statements) end - val globals = Vector.concat [Vector.new2 (t, f), ones, globals] + val globals = Vector.concat [Vector.new2 (trueStmt, falseStmt), ones, + globals] val shrink = shrinkFunction {globals = globals} val numSimplified = ref 0 fun simplifyFunction f = @@ -363,6 +364,113 @@ fun transform (Program.T {globals, datatypes, functions, main}) = | Unknown => statement) | _ => statement) end) + fun add1Eligible (x: Var.t, s: WordSize.t, sg) = + isFact (label, fn Fact.T {lhs, rel, rhs} => + case (lhs, rel, rhs) of + (Oper.Var x', Rel.LT sg', _) => + Var.equals (x, x') + andalso sg = sg' + | (Oper.Var x', Rel.LE sg', + Oper.Const c) => + Var.equals (x, x') + andalso sg = sg' + andalso + (case c of + Const.Word w => + WordX.lt + (w, WordX.max (s, sg), sg) + | _ => Error.bug "RedundantTests.add1: strange fact") + | _ => false) + fun sub1Eligible (x: Var.t, s: WordSize.t, sg) = + isFact (label, fn Fact.T {lhs, rel, rhs} => + case (lhs, rel, rhs) of + (_, Rel.LT sg', Oper.Var x') => + Var.equals (x, x') + andalso sg = sg' + | (Oper.Const c, Rel.LE sg', + Oper.Var x') => + Var.equals (x, x') + andalso sg = sg' + andalso + (case c of + Const.Word w => + WordX.gt + (w, WordX.min (s, sg), sg) + | _ => Error.bug "RedundantTests.sub1: strange fact") + | _ => false) + val statements = + Vector.map + (statements, + fn statement as Statement.T {exp, var, ...} => + case exp of + Exp.PrimApp {args, prim, ...} => + let + open Prim.Name + fun doit x = + (Int.inc numSimplified + ; Control.diagnostic + (fn () => + let open Layout + in seq [Option.layout Var.layout var, + str " ~> ", + Var.layout x] + end) + ; Statement.T {var = var, ty = Type.bool, + exp = Var x}) + fun falsee () = doit falseVar + + fun add1 (x: Var.t, s: WordSize.t, sg) = + if add1Eligible (x, s, sg) then falsee () + else statement + fun sub1 (x: Var.t, s: WordSize.t, sg) = + if sub1Eligible (x, s, sg) then falsee () + else statement + + fun add (c: Const.t, x: Var.t, + (s, sg as {signed})) = + case c of + Const.Word i => + if WordX.isOne i + then add1 (x, s, sg) + else if signed andalso WordX.isNegOne i + then sub1 (x, s, sg) + else statement + | _ => Error.bug ("RedundantTests.add: strange const") + in + case Prim.name prim of + Word_addCheckP s => + let + val x1 = Vector.sub (args, 0) + val x2 = Vector.sub (args, 1) + in + case varInfo x1 of + Const c => add (c, x2, s) + | _ => (case varInfo x2 of + Const c => add (c, x1, s) + | _ => statement) + end + | Word_subCheckP (s, sg as {signed}) => + let + val x1 = Vector.sub (args, 0) + val x2 = Vector.sub (args, 1) + in + case varInfo x2 of + Const c => + (case c of + Const.Word i => + if WordX.isOne i + then sub1 (x1, s, sg) + else if signed andalso + WordX.isNegOne i + then + add1 (x1, s, sg) + else statement + | _ => Error.bug ("RedundantTests.sub: strange const")) + | _ => statement + end + | _ => statement + end + | _ => statement) val noChange = (statements, transfer) fun arith (args: Var.t vector, prim: Type.t Prim.t, @@ -388,42 +496,12 @@ fun transform (Program.T {globals, datatypes, functions, main}) = dst = success}) end fun add1 (x: Var.t, s: WordSize.t, sg) = - if isFact (label, fn Fact.T {lhs, rel, rhs} => - case (lhs, rel, rhs) of - (Oper.Var x', Rel.LT sg', _) => - Var.equals (x, x') - andalso sg = sg' - | (Oper.Var x', Rel.LE sg', - Oper.Const c) => - Var.equals (x, x') - andalso sg = sg' - andalso - (case c of - Const.Word w => - WordX.lt - (w, WordX.max (s, sg), sg) - | _ => Error.bug "RedundantTests.add1: strange fact") - | _ => false) - then simplify (Prim.wordAdd s, x, s) + if add1Eligible (x, s, sg) + then simplify (Prim.wordAdd s, x, s) else noChange fun sub1 (x: Var.t, s: WordSize.t, sg) = - if isFact (label, fn Fact.T {lhs, rel, rhs} => - case (lhs, rel, rhs) of - (_, Rel.LT sg', Oper.Var x') => - Var.equals (x, x') - andalso sg = sg' - | (Oper.Const c, Rel.LE sg', - Oper.Var x') => - Var.equals (x, x') - andalso sg = sg' - andalso - (case c of - Const.Word w => - WordX.gt - (w, WordX.min (s, sg), sg) - | _ => Error.bug "RedundantTests.sub1: strange fact") - | _ => false) - then simplify (Prim.wordSub s, x, s) + if sub1Eligible (x, s, sg) + then simplify (Prim.wordSub s, x, s) else noChange fun add (c: Const.t, x: Var.t, (s, sg as {signed})) = case c of From 267504cbd63977e4ad4070580f702e447686e813 Mon Sep 17 00:00:00 2001 From: Daman Morris Date: Tue, 10 Jul 2018 13:50:15 -0400 Subject: [PATCH 17/57] Add arithmetic identity support for newOverflow --- mlton/atoms/prim.fun | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/mlton/atoms/prim.fun b/mlton/atoms/prim.fun index b3e55782be..ec6db4e4ed 100644 --- a/mlton/atoms/prim.fun +++ b/mlton/atoms/prim.fun @@ -1694,6 +1694,18 @@ fun ('a, 'b) apply (p: 'a t, in wordOrOverflow (s, sg, f (conv w, conv w')) end + fun wordOrTrue (s, sg, w) = if WordSize.isInRange (s, w, sg) + then f + else t + fun wcheckp (f: IntInf.t * IntInf.t -> IntInf.t, + (s: WordSize.t, sg as {signed}), + w: WordX.t, + w': WordX.t) = + let + val conv = if signed then WordX.toIntInfX else WordX.toIntInf + in + wordOrTrue (s, sg, f (conv w, conv w')) + end val eq = fn (Word w1, Word w2) => bool (WordX.equals (w1, w2)) | _ => ApplyResult.Unknown @@ -1827,15 +1839,19 @@ fun ('a, 'b) apply (p: 'a t, (if signed then WordX.toIntInfX w else WordX.toIntInf w, s)) | (Word_add _, [Word w1, Word w2]) => word (WordX.add (w1, w2)) | (Word_addCheck s, [Word w1, Word w2]) => wcheck (op +, s, w1, w2) + | (Word_addCheckP s, [Word w1, Word w2]) => wcheckp (op +, s, w1, w2) | (Word_andb _, [Word w1, Word w2]) => word (WordX.andb (w1, w2)) | (Word_equal _, [Word w1, Word w2]) => bool (WordX.equals (w1, w2)) | (Word_lshift _, [Word w1, Word w2]) => word (WordX.lshift (w1, w2)) | (Word_lt s, [Word w1, Word w2]) => wordCmp (WordX.lt, s, w1, w2) | (Word_mul s, [Word w1, Word w2]) => wordS (WordX.mul, s, w1, w2) | (Word_mulCheck s, [Word w1, Word w2]) => wcheck (op *, s, w1, w2) + | (Word_mulCheckP s, [Word w1, Word w2]) => wcheckp (op *, s, w1, w2) | (Word_neg _, [Word w]) => word (WordX.neg w) | (Word_negCheck s, [Word w]) => wordOrOverflow (s, {signed = true}, ~ (WordX.toIntInfX w)) + | (Word_negCheckP s, [Word w]) => + wordOrTrue (s, {signed = true}, ~ (WordX.toIntInfX w)) | (Word_notb _, [Word w]) => word (WordX.notb w) | (Word_orb _, [Word w1, Word w2]) => word (WordX.orb (w1, w2)) | (Word_quot s, [Word w1, Word w2]) => @@ -1852,6 +1868,7 @@ fun ('a, 'b) apply (p: 'a t, wordS (WordX.rshift, s, w1, w2) | (Word_sub _, [Word w1, Word w2]) => word (WordX.sub (w1, w2)) | (Word_subCheck s, [Word w1, Word w2]) => wcheck (op -, s, w1, w2) + | (Word_subCheckP s, [Word w1, Word w2]) => wcheckp (op -, s, w1, w2) | (Word_toIntInf, [Word w]) => (case IntInfRep.smallToIntInf w of NONE => ApplyResult.Unknown @@ -2041,6 +2058,9 @@ fun ('a, 'b) apply (p: 'a t, else Unknown | Word_add _ => add () | Word_addCheck _ => add () + | Word_addCheckP _ => if WordX.isZero w + then f + else Unknown | Word_andb s => if WordX.isZero w then zero s @@ -2054,6 +2074,9 @@ fun ('a, 'b) apply (p: 'a t, else if WordX.isMax (w, sg) then f else Unknown | Word_mul s => mul (s, wordNeg) | Word_mulCheck s => mul (s, wordNegCheck) + | Word_mulCheckP _ => if WordX.isZero w orelse WordX.isOne w + then f + else Unknown | Word_orb _ => if WordX.isZero w then Var x @@ -2089,6 +2112,9 @@ fun ('a, 'b) apply (p: 'a t, shift s | Word_sub s => sub (s, wordNeg) | Word_subCheck s => sub (s, wordNegCheck o #1) + | Word_subCheckP _ => if WordX.isZero w andalso inOrder + then f + else Unknown | Word_xorb s => if WordX.isZero w then Var x From 58eae83e15ec63494a102b3b32abe2f4ccc0d034 Mon Sep 17 00:00:00 2001 From: Daman Morris Date: Tue, 10 Jul 2018 13:53:07 -0400 Subject: [PATCH 18/57] Re-arrange newOverflow operation order Previously, the new overflow-checking primitives were implemented by first checking for overflow and then performing the operation. This change refactors the implementation to instead perform and store the operation first, then check for overflow. This will allow the peephole optimization to be more easily implemented for the new overflow primitives in the native codegens. --- basis-library/primitive/prim1.sml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/basis-library/primitive/prim1.sml b/basis-library/primitive/prim1.sml index 18251dc73f..718548bec8 100644 --- a/basis-library/primitive/prim1.sml +++ b/basis-library/primitive/prim1.sml @@ -54,7 +54,10 @@ structure Exn = exception Subscript val mkOverflow: ('a -> 'b) * ('a -> bool) -> ('a -> 'b) = - fn (!, ?) => fn a => if ? a then raise Overflow else ! a + fn (!, ?) => fn a => + let val r = ! a + in if ? a then raise Overflow else r + end val wrapOverflow: ('a -> 'b) -> ('a -> 'b) = fn f => fn a => f a handle PrimOverflow => raise Overflow end From e6abe7f91eecc78c50873dce427ae1148241dfd4 Mon Sep 17 00:00:00 2001 From: Daman Morris Date: Tue, 10 Jul 2018 13:56:11 -0400 Subject: [PATCH 19/57] Use `0-x` for negation overflow checking in amd64 --- mlton/codegen/amd64-codegen/amd64-mlton.fun | 29 ++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/mlton/codegen/amd64-codegen/amd64-mlton.fun b/mlton/codegen/amd64-codegen/amd64-mlton.fun index df0cbe539e..e4e13590e9 100644 --- a/mlton/codegen/amd64-codegen/amd64-mlton.fun +++ b/mlton/codegen/amd64-codegen/amd64-mlton.fun @@ -504,6 +504,33 @@ struct transfer = NONE}] end + fun negalcc () + = let + val (src,srcsize) = getSrc1 () + val (dst,dstsize) = getDst1 () + val (tmp,tmpsize) = (overflowCheckTempContentsOperand srcsize, + srcsize) + in + AppendList.fromList + [Block.mkBlock' + {entry = NONE, + statements + = [Assembly.instruction_mov + {dst = tmp, + src = Operand.immediate_zero, + size = tmpsize}, + Assembly.instruction_binal + {oper = Instruction.SUB, + dst = tmp, + src = src, + size = srcsize}, + Assembly.instruction_setcc + {condition = Instruction.O, + dst = dst, + size = dstsize}], + transfer = NONE}] + end + fun unalcc (oper, condition) = let val (src,srcsize) = getSrc1 () @@ -1240,7 +1267,7 @@ struct | W64 => imul2cc (flag sg) end | Word_neg _ => unal Instruction.NEG - | Word_negCheckP _ => unalcc (Instruction.NEG, Instruction.O) + | Word_negCheckP _ => negalcc () | Word_notb _ => unal Instruction.NOT | Word_orb _ => binal Instruction.OR | Word_quot (_, {signed}) => From 72cb10ba160b3852acf1c8d36d1a7926bb7ed50e Mon Sep 17 00:00:00 2001 From: Daman Morris Date: Tue, 10 Jul 2018 14:11:35 -0400 Subject: [PATCH 20/57] Remove unused variables --- mlton/atoms/prim.fun | 2 - mlton/codegen/amd64-codegen/amd64-mlton.fun | 44 ++--------- mlton/codegen/x86-codegen/x86-mlton.fun | 86 ++++----------------- 3 files changed, 20 insertions(+), 112 deletions(-) diff --git a/mlton/atoms/prim.fun b/mlton/atoms/prim.fun index ec6db4e4ed..485dc9b10c 100644 --- a/mlton/atoms/prim.fun +++ b/mlton/atoms/prim.fun @@ -779,7 +779,6 @@ val vectorLength = Vector_length val vectorSub = Vector_sub val wordAdd = Word_add val wordAddCheck = Word_addCheck -val wordAddCheckP = Word_addCheckP val wordAndb = Word_andb val wordCastToReal = Word_castToReal val wordEqual = Word_equal @@ -789,7 +788,6 @@ val wordLt = Word_lt val wordMul = Word_mul val wordNeg = Word_neg val wordNegCheck = Word_negCheck -val wordNegCheckP = Word_negCheckP val wordNotb = Word_notb val wordOrb = Word_orb val wordQuot = Word_quot diff --git a/mlton/codegen/amd64-codegen/amd64-mlton.fun b/mlton/codegen/amd64-codegen/amd64-mlton.fun index e4e13590e9..1046b71cf1 100644 --- a/mlton/codegen/amd64-codegen/amd64-mlton.fun +++ b/mlton/codegen/amd64-codegen/amd64-mlton.fun @@ -254,8 +254,7 @@ struct val ((src1,src1size), (src2,src2size)) = getSrc2 () val (dst,dstsize) = getDst1 () - val (tmp,tmpsize) = (overflowCheckTempContentsOperand src1size, - src1size) + val tmp = overflowCheckTempContentsOperand src1size val _ = Assert.assert ("amd64MLton.prim: binalcc, src1size/src2size", @@ -353,8 +352,7 @@ struct val ((src1,src1size), (src2,src2size)) = getSrc2 () val (dst,dstsize) = getDst1 () - val (tmp,tmpsize) = (overflowCheckTempContentsOperand src1size, - src1size) + val tmp = overflowCheckTempContentsOperand src1size val _ = Assert.assert ("amd64MLton.prim: pmdcc, src1size/src2size", @@ -389,7 +387,7 @@ struct {oper = oper, dst = tmp, src = src2, - size = tmpsize}, + size = src1size}, Assembly.instruction_setcc {condition = condition, dst = dst, @@ -441,8 +439,7 @@ struct val ((src1,src1size), (src2,src2size)) = getSrc2 () val (dst,dstsize) = getDst1 () - val (tmp,tmpsize) = (overflowCheckTempContentsOperand src1size, - src1size) + val tmp = overflowCheckTempContentsOperand src1size val _ = Assert.assert ("amd64MLton.prim: imul2cc, src1size/src2size", @@ -472,7 +469,7 @@ struct Assembly.instruction_imul2 {dst = tmp, src = src2, - size = tmpsize}, + size = src1size}, Assembly.instruction_setcc {dst = dst, condition = condition, @@ -508,8 +505,7 @@ struct = let val (src,srcsize) = getSrc1 () val (dst,dstsize) = getDst1 () - val (tmp,tmpsize) = (overflowCheckTempContentsOperand srcsize, - srcsize) + val tmp = overflowCheckTempContentsOperand srcsize in AppendList.fromList [Block.mkBlock' @@ -518,7 +514,7 @@ struct = [Assembly.instruction_mov {dst = tmp, src = Operand.immediate_zero, - size = tmpsize}, + size = srcsize}, Assembly.instruction_binal {oper = Instruction.SUB, dst = tmp, @@ -531,32 +527,6 @@ struct transfer = NONE}] end - fun unalcc (oper, condition) - = let - val (src,srcsize) = getSrc1 () - val (dst,dstsize) = getDst1 () - val (tmp,tmpsize) = (overflowCheckTempContentsOperand srcsize, - srcsize) - in - AppendList.fromList - [Block.mkBlock' - {entry = NONE, - statements - = [Assembly.instruction_mov - {dst = tmp, - src = src, - size = srcsize}, - Assembly.instruction_unal - {oper = oper, - dst = tmp, - size = tmpsize}, - Assembly.instruction_setcc - {condition = condition, - dst = dst, - size = dstsize}], - transfer = NONE}] - end - fun sral oper = let val (dst,dstsize) = getDst1 () diff --git a/mlton/codegen/x86-codegen/x86-mlton.fun b/mlton/codegen/x86-codegen/x86-mlton.fun index 8e5ac5fbda..0ea34a553e 100644 --- a/mlton/codegen/x86-codegen/x86-mlton.fun +++ b/mlton/codegen/x86-codegen/x86-mlton.fun @@ -260,8 +260,7 @@ struct val ((src1,src1size), (src2,src2size)) = getSrc2 () val (dst,dstsize) = getDst1 () - val (tmp,tmpsize) = (overflowCheckTempContentsOperand src1size, - src1size) + val tmp = overflowCheckTempContentsOperand src1size val _ = Assert.assert ("x86MLton.prim: binal, src1size/src2size", @@ -302,7 +301,7 @@ struct {oper = oper, dst = tmp, src = src2, - size = tmpsize}, + size = src1size}, Assembly.instruction_setcc {condition = condition, dst = dst, @@ -375,8 +374,7 @@ struct val ((src1,src1size), _, (src3,src3size), _) = getSrc4 () val (dst,dstsize) = getDst1 () - val (tmp,tmpsize) = (overflowCheckTempContentsOperand src1size, - src1size) + val tmp = overflowCheckTempContentsOperand src1size val _ = Assert.assert ("x86MLton.prim: binal64cc, src1size/src3size", @@ -389,12 +387,12 @@ struct = [Assembly.instruction_mov {dst = tmp, src = src1, - size = tmpsize}, + size = src1size}, Assembly.instruction_binal {oper = oper, dst = tmp, src = src3, - size = tmpsize}, + size = src1size}, Assembly.instruction_setcc {condition = condition, dst = dst, @@ -452,8 +450,7 @@ struct val ((src1,src1size), (src2,src2size)) = getSrc2 () val (dst,dstsize) = getDst1 () - val (tmp,tmpsize) = (overflowCheckTempContentsOperand src1size, - src1size) + val tmp= overflowCheckTempContentsOperand src1size val _ = Assert.assert ("x86MLton.prim: pmdcc, src1size/src2size", @@ -483,12 +480,12 @@ struct = [Assembly.instruction_mov {dst = tmp, src = src1, - size = tmpsize}, + size = src1size}, Assembly.instruction_pmd {oper = oper, dst = tmp, src = src2, - size = tmpsize}, + size = src1size}, Assembly.instruction_setcc {condition = condition, dst = dst, @@ -541,8 +538,7 @@ struct val ((src1,src1size), (src2,src2size)) = getSrc2 () val (dst,dstsize) = getDst1 () - val (tmp,tmpsize) = (overflowCheckTempContentsOperand src1size, - src1size) + val tmp= overflowCheckTempContentsOperand src1size val _ = Assert.assert ("x86MLton.prim: imul2, src1size/src2size", @@ -568,11 +564,11 @@ struct = [Assembly.instruction_mov {dst = tmp, src = src1, - size = tmpsize}, + size = src1size}, Assembly.instruction_imul2 {dst = tmp, src = src2, - size = tmpsize}, + size = src1size}, Assembly.instruction_setcc {condition = condition, dst = dst, @@ -584,8 +580,7 @@ struct = let val (src,srcsize) = getSrc1 () val (dst,dstsize) = getDst1 () - val (tmp,tmpsize) = (overflowCheckTempContentsOperand srcsize, - srcsize) + val tmp = overflowCheckTempContentsOperand srcsize in AppendList.fromList [Block.mkBlock' @@ -594,7 +589,7 @@ struct = [Assembly.instruction_mov {dst = tmp, src = Operand.immediate_zero, - size = tmpsize}, + size = srcsize}, Assembly.instruction_binal {oper = Instruction.SUB, dst = tmp, @@ -612,8 +607,6 @@ struct val ((src1,src1size), (src2,src2size)) = getSrc2 () val (dst,dstsize) = getDst1 () - val (tmp,tmpsize) = (overflowCheckTempContentsOperand src1size, - src1size) val _ = Assert.assert ("x86MLton.prim: negal64cc, src1size/src2size", @@ -674,32 +667,6 @@ struct transfer = NONE}] end - fun unalcc (oper, condition) - = let - val (src,srcsize) = getSrc1 () - val (dst,dstsize) = getDst1 () - val (tmp,tmpsize) = (overflowCheckTempContentsOperand srcsize, - srcsize) - in - AppendList.fromList - [Block.mkBlock' - {entry = NONE, - statements - = [Assembly.instruction_mov - {dst = tmp, - src = src, - size = tmpsize}, - Assembly.instruction_unal - {oper = oper, - dst = tmp, - size = tmpsize}, - Assembly.instruction_setcc - {condition = condition, - dst = dst, - size = dstsize}], - transfer = NONE}] - end - fun unal64 (oper, mk) = let val ((src1,src1size),(src2,src2size)) = getSrc2 () @@ -744,33 +711,6 @@ struct transfer = NONE}] end - fun unal64cc (oper, condition) - = let - val ((src1,src1size),_) = getSrc2 () - val (dst,dstsize) = getDst1 () - val (tmp,tmpsize) = (overflowCheckTempContentsOperand src1size, - src1size) - in - AppendList.fromList - [Block.mkBlock' - {entry = NONE, - statements - = [Assembly.instruction_mov - {dst = tmp, - src = src1, - size = src1size}, - Assembly.instruction_unal - {oper = oper, - dst = tmp, - size = tmpsize}, - Assembly.instruction_setcc - {condition = condition, - dst = dst, - size = dstsize}], - transfer = NONE}] - end - - fun sral oper = let val (dst,dstsize) = getDst1 () From 3dffc90847db52ca06b8cd781168e0aa5b204beb Mon Sep 17 00:00:00 2001 From: Daman Morris Date: Thu, 12 Jul 2018 10:27:22 -0400 Subject: [PATCH 21/57] Correct implementation of `mulCheckP` The native codegens (amd64, x86) previously used the pmd and imul2 instructions incorrectly to check for overflow (based erroneously on the pattern of the corresponding arithmetic operations). This fix changes the implementation to use `pmdcc` for all unsigned operations. --- mlton/codegen/amd64-codegen/amd64-mlton.fun | 23 +++++++++----------- mlton/codegen/x86-codegen/x86-mlton.fun | 24 +++++++++++---------- 2 files changed, 23 insertions(+), 24 deletions(-) diff --git a/mlton/codegen/amd64-codegen/amd64-mlton.fun b/mlton/codegen/amd64-codegen/amd64-mlton.fun index 1046b71cf1..f2aa9fe538 100644 --- a/mlton/codegen/amd64-codegen/amd64-mlton.fun +++ b/mlton/codegen/amd64-codegen/amd64-mlton.fun @@ -827,7 +827,7 @@ struct else (AppendList.empty,AppendList.empty) fun flag {signed} = - if signed then Instruction.O else Instruction.C + if signed then amd64.Instruction.O else amd64.Instruction.C in AppendList.appends [comment_begin, @@ -1224,18 +1224,15 @@ struct | W16 => imul2 () | W32 => imul2 () | W64 => imul2 ()) - | Word_mulCheckP (s, sg) => - let - val {signed} = sg - in - case WordSize.prim s of - W8 => pmdcc (if signed then Instruction.IMUL - else Instruction.MUL, - flag sg) - | W16 => imul2cc (flag sg) - | W32 => imul2cc (flag sg) - | W64 => imul2cc (flag sg) - end + | Word_mulCheckP (s, {signed}) => + if signed then + (case WordSize.prim s of + W8 => pmdcc (Instruction.IMUL, amd64.Instruction.O) + | W16 => imul2cc amd64.Instruction.O + | W32 => imul2cc amd64.Instruction.O + | W64 => imul2cc amd64.Instruction.O) + else + pmdcc (Instruction.MUL, amd64.Instruction.C) | Word_neg _ => unal Instruction.NEG | Word_negCheckP _ => negalcc () | Word_notb _ => unal Instruction.NOT diff --git a/mlton/codegen/x86-codegen/x86-mlton.fun b/mlton/codegen/x86-codegen/x86-mlton.fun index 0ea34a553e..af12786809 100644 --- a/mlton/codegen/x86-codegen/x86-mlton.fun +++ b/mlton/codegen/x86-codegen/x86-mlton.fun @@ -1617,17 +1617,19 @@ struct | W32 => imul2 () | W64 => Error.bug "x86MLton.prim: Word_mul, W64") | Word_mulCheckP (s, {signed}) => - let - val cond = flag {signed = signed} - in - case WordSize.prim s of - W8 => pmdcc (if signed - then Instruction.IMUL - else Instruction.MUL, cond) - | W16 => imul2cc cond - | W32 => imul2cc cond - | W64 => Error.bug "x86MLton.prim: Word_mulCheckP, W64" - end + if signed + then + (case WordSize.prim s of + W8 => pmdcc (x86.Instruction.IMUL, x86.Instruction.O) + | W16 => imul2cc x86.Instruction.O + | W32 => imul2cc x86.Instruction.O + | W64 => Error.bug "x86MLton.arith: Word_mulCheckP, W64") + else + (case WordSize.prim s of + W8 => pmdcc (x86.Instruction.MUL, x86.Instruction.C) + | W16 => pmdcc (x86.Instruction.MUL, x86.Instruction.C) + | W32 => pmdcc (x86.Instruction.MUL, x86.Instruction.C) + | W64 => Error.bug "x86MLton.arith: Word_mulCheckP, W64") | Word_neg s => (case WordSize.prim s of W8 => unal Instruction.NEG From 844d11fbff78f3b66c772914b424de9b74a289e7 Mon Sep 17 00:00:00 2001 From: Daman Morris Date: Thu, 12 Jul 2018 11:49:12 -0400 Subject: [PATCH 22/57] Rename `negal(64)cc` to `neg(64)cc` --- mlton/codegen/amd64-codegen/amd64-mlton.fun | 4 ++-- mlton/codegen/x86-codegen/x86-mlton.fun | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/mlton/codegen/amd64-codegen/amd64-mlton.fun b/mlton/codegen/amd64-codegen/amd64-mlton.fun index f2aa9fe538..d22e80854b 100644 --- a/mlton/codegen/amd64-codegen/amd64-mlton.fun +++ b/mlton/codegen/amd64-codegen/amd64-mlton.fun @@ -501,7 +501,7 @@ struct transfer = NONE}] end - fun negalcc () + fun negcc () = let val (src,srcsize) = getSrc1 () val (dst,dstsize) = getDst1 () @@ -1234,7 +1234,7 @@ struct else pmdcc (Instruction.MUL, amd64.Instruction.C) | Word_neg _ => unal Instruction.NEG - | Word_negCheckP _ => negalcc () + | Word_negCheckP _ => negcc () | Word_notb _ => unal Instruction.NOT | Word_orb _ => binal Instruction.OR | Word_quot (_, {signed}) => diff --git a/mlton/codegen/x86-codegen/x86-mlton.fun b/mlton/codegen/x86-codegen/x86-mlton.fun index af12786809..2829770e3e 100644 --- a/mlton/codegen/x86-codegen/x86-mlton.fun +++ b/mlton/codegen/x86-codegen/x86-mlton.fun @@ -576,7 +576,7 @@ struct transfer = NONE}] end - fun negalcc () + fun negcc () = let val (src,srcsize) = getSrc1 () val (dst,dstsize) = getDst1 () @@ -602,14 +602,14 @@ struct transfer = NONE}] end - fun negal64cc () + fun neg64cc () = let val ((src1,src1size), (src2,src2size)) = getSrc2 () val (dst,dstsize) = getDst1 () val _ = Assert.assert - ("x86MLton.prim: negal64cc, src1size/src2size", + ("x86MLton.prim: neg64cc, src1size/src2size", fn () => src1size = src2size) val tdst1 = wordTemp1ContentsOperand src1size val tdst2 = wordTemp1ContentsOperand src2size @@ -1643,10 +1643,10 @@ struct size = dstsize}])) | Word_negCheckP s => (case WordSize.prim s of - W8 => negalcc () - | W16 => negalcc () - | W32 => negalcc () - | W64 => negal64cc ()) + W8 => negcc () + | W16 => negcc () + | W32 => negcc () + | W64 => neg64cc ()) | Word_notb s => (case WordSize.prim s of W8 => unal Instruction.NOT From 8f2dfab6c1d344fc2d824b0b6fd5844f9df99959 Mon Sep 17 00:00:00 2001 From: Daman Morris Date: Thu, 12 Jul 2018 11:49:37 -0400 Subject: [PATCH 23/57] Use a single statement map in redundantTests The existing redundantTests code consisted of a map over statements and a separate check for the presence of an arith transfer for the old overflow-checking primitives. Initially an additional map over statements was added to deal with the new overflow-checking primitives; this change merges the two maps into one. --- mlton/ssa/redundant-tests.fun | 98 +++++++++++++++-------------------- 1 file changed, 42 insertions(+), 56 deletions(-) diff --git a/mlton/ssa/redundant-tests.fun b/mlton/ssa/redundant-tests.fun index 93ea0785c3..b310e0fd3e 100644 --- a/mlton/ssa/redundant-tests.fun +++ b/mlton/ssa/redundant-tests.fun @@ -325,45 +325,6 @@ fun transform (Program.T {globals, datatypes, functions, main}) = Vector.map (blocks, fn Block.T {label, args, statements, transfer} => let - val statements = - Vector.map - (statements, fn statement as Statement.T {ty, var, ...} => - let - fun doit x = - (Int.inc numSimplified - ; Control.diagnostic - (fn () => - let open Layout - in seq [Option.layout Var.layout var, - str " -> ", - Var.layout x] - end) - ; Statement.T {var = var, - ty = ty, - exp = Var x}) - fun falsee () = doit falseVar - fun truee () = doit trueVar - in - case var of - NONE => statement - | SOME var => - (case varInfo var of - Or (f, f') => - (case determine (label, f) of - False => - (case determine (label, f') of - False => falsee () - | True => truee () - | Unknown => statement) - | True => truee () - | Unknown => statement) - | Fact f => - (case determine (label, f) of - False => falsee () - | True => truee () - | Unknown => statement) - | _ => statement) - end) fun add1Eligible (x: Var.t, s: WordSize.t, sg) = isFact (label, fn Fact.T {lhs, rel, rhs} => case (lhs, rel, rhs) of @@ -400,24 +361,26 @@ fun transform (Program.T {globals, datatypes, functions, main}) = | _ => false) val statements = Vector.map - (statements, - fn statement as Statement.T {exp, var, ...} => - case exp of - Exp.PrimApp {args, prim, ...} => + (statements, fn statement as Statement.T {ty, var, exp, ...} => + let + fun doit x = + (Int.inc numSimplified + ; Control.diagnostic + (fn () => + let open Layout + in seq [Option.layout Var.layout var, + str " -> ", + Var.layout x] + end) + ; Statement.T {var = var, + ty = ty, + exp = Var x}) + fun falsee () = doit falseVar + fun truee () = doit trueVar + + fun checkPrimApp (args, prim) = let open Prim.Name - fun doit x = - (Int.inc numSimplified - ; Control.diagnostic - (fn () => - let open Layout - in seq [Option.layout Var.layout var, - str " ~> ", - Var.layout x] - end) - ; Statement.T {var = var, ty = Type.bool, - exp = Var x}) - fun falsee () = doit falseVar fun add1 (x: Var.t, s: WordSize.t, sg) = if add1Eligible (x, s, sg) then falsee () @@ -470,7 +433,30 @@ fun transform (Program.T {globals, datatypes, functions, main}) = end | _ => statement end - | _ => statement) + in + case var of + NONE => statement + | SOME var => + (case varInfo var of + Or (f, f') => + (case determine (label, f) of + False => + (case determine (label, f') of + False => falsee () + | True => truee () + | Unknown => statement) + | True => truee () + | Unknown => statement) + | Fact f => + (case determine (label, f) of + False => falsee () + | True => truee () + | Unknown => statement) + | _ => (case exp of + Exp.PrimApp {args, prim, ...} => + checkPrimApp (args, prim) + | _ => statement)) + end) val noChange = (statements, transfer) fun arith (args: Var.t vector, prim: Type.t Prim.t, From afd428d180324642bd8903882705de182f8d0992 Mon Sep 17 00:00:00 2001 From: Daman Morris Date: Mon, 16 Jul 2018 11:24:07 -0400 Subject: [PATCH 24/57] Add peephole optimization for new primitives Adds a new peephole optimization pass for the native codegens to eliminate redundant AL instructions. In general, whenever a checked word operation is generated, the `Word_*` and `Word_*CheckP` operations generate distinct assembly instructions. However, only one of these instructions is actually needed, since both perform the same operation and set the same overflow flag, so the generated assembly for a `Word_*CheckP` immediately following an identical `Word_*` operation can be safely removed. Currently, blocks where one `mov` instruction has been hoisted to the front of the block are also recognized. --- .../codegen/amd64-codegen/amd64-simplify.fun | 212 ++++++++++++++++++ mlton/control/control-flags.sig | 3 + mlton/control/control-flags.sml | 4 + mlton/main/main.fun | 3 + 4 files changed, 222 insertions(+) diff --git a/mlton/codegen/amd64-codegen/amd64-simplify.fun b/mlton/codegen/amd64-codegen/amd64-simplify.fun index a5ed7d265d..93aeeae894 100644 --- a/mlton/codegen/amd64-codegen/amd64-simplify.fun +++ b/mlton/codegen/amd64-codegen/amd64-simplify.fun @@ -3087,6 +3087,216 @@ struct val elimALCopy_msg = elimALCopy_msg end + (* TODO add new template/rewriter elimCheckP? based on elimALCopy or + * others + * Also: + * - Fix liveness information + * - Reassemble block w/o check oper + * - Add flag to `main`, `control-flags`, `native`*) + local + val isInstructionMOV_dstTemp : statement_type -> bool + = fn (Assembly.Instruction (Instruction.MOV + {dst = Operand.MemLoc memloc,...}), + _) + => amd64Liveness.track memloc + | _ => false + + fun isInstructionAL_aux (check) : statement_type -> bool + = fn (Assembly.Instruction (Instruction.BinAL + {dst = Operand.MemLoc memloc,...}), + _) + => check memloc + | (Assembly.Instruction (Instruction.pMD + {dst = Operand.MemLoc memloc,...}), + + _) + => check memloc + | (Assembly.Instruction (Instruction.IMUL2 + {dst = Operand.MemLoc memloc,...}), + + _) + => check memloc + | (Assembly.Instruction (Instruction.UnAL + {dst = Operand.MemLoc memloc,...}), + + _) + => check memloc + | (Assembly.Instruction (Instruction.SRAL + {dst = Operand.MemLoc memloc,...}), + + _) + => check memloc + | _ => false + val isInstructionAL_dstTemp : statement_type -> bool + = isInstructionAL_aux amd64Liveness.track + fun isDeadTemp dead memloc + = amd64Liveness.track memloc andalso LiveSet.contains (dead, memloc) + val isInstructionAL_dstDeadTemp : statement_type -> bool + = fn (instr, liveness as Liveness.T {dead, ...}) + => isInstructionAL_aux (isDeadTemp dead) (instr, liveness) + + val isInstructionALorMOV_dstTemp : statement_type -> bool + = fn stype => isInstructionAL_dstTemp stype orelse + isInstructionMOV_dstTemp stype + + val template : template + = {start = EmptyOrNonEmpty, + statements = [One isInstructionMOV_dstTemp, + All isComment, + One isInstructionALorMOV_dstTemp, + All isComment, + One isInstructionALorMOV_dstTemp, + All isComment, + One isInstructionAL_dstDeadTemp], + finish = EmptyOrNonEmpty, + transfer = fn _ => true} + + (* + * Pattern: + * + * mov $x, $z + * AL $y, $z + * mov $x, $t + * AL $y, $t + * setcc + * + * OR + * + * mov $x, $z + * mov $x, $t + * AL $y, $z + * AL $y, $t + * setcc + *) + + val rewriter : rewriter + = fn {entry, profileLabel, start, statements, finish, transfer} => + let + fun rewriter' (stmtMov, src1x, dst1z, + comments1, + stmtAL, instrAL1, + comments2, + src2x, dst2z, + comments3, + instrAL2, liveOut2) + = if !Control.Native.elimALRedundant andalso + Operand.eq (src1x, src2x) andalso + (let + fun checkUn (oper1, dst1, oper2, dst2) + = oper1 = oper2 andalso + Operand.eq(dst1z, dst1) andalso + Operand.eq(dst2z, dst2) + + fun checkBin (oper1, src1, dst1, oper2, src2, dst2) + = oper1 = oper2 andalso + Operand.eq(src1, src2) andalso + Operand.eq(dst1z, dst1) andalso + Operand.eq(dst2z, dst2) + in + case (instrAL1, instrAL2) of + (Instruction.BinAL + {oper = oper1, src = src1, dst = dst1, ...}, + Instruction.BinAL + {oper = oper2, src = src2, dst = dst2, ...}) + => checkBin (oper1, src1, dst1, oper2, src2, dst2) + | (Instruction.pMD + {oper = oper1, src = src1, dst = dst1, ...}, + Instruction.pMD + {oper = oper2, src = src2, dst = dst2, ...}) + => checkBin (oper1, src1, dst1, oper2, src2, dst2) + | (Instruction.UnAL + {oper = oper1, dst = dst1, ...}, + Instruction.UnAL + {oper = oper2, dst = dst2, ...}) + => checkUn (oper1, dst1, oper2, dst2) + | (Instruction.SRAL + {oper = oper1, count = src1, dst = dst1, ...}, + Instruction.SRAL + {oper = oper2, count = src2, dst = dst2, ...}) + => checkBin (oper1, src1, dst1, oper2, src2, dst2) + | _ => false + end) + then + let + val excomm = fn comm => List.map (comm, fn (c, _) => c) + val comments1 = excomm comments1 + val comments2 = excomm comments2 + val comments3 = excomm comments3 + + val statements = + stmtMov::(comments1 @ (stmtAL::(comments2 @ comments3))) + val {statements, ...} + = LivenessBlock.toLivenessStatements + {statements = statements, live = liveOut2} + val statements + = List.fold (start, + List.concat [statements, finish], + op ::) + in + SOME (LivenessBlock.T + {entry = entry, + profileLabel = profileLabel, + statements = statements, + transfer = transfer}) + end + else NONE + in + case statements of + [[(stmtMov as Assembly.Instruction (Instruction.MOV + {src = src1x, + dst = dst1z, ...}), + _)], + comments1, + [(stmtAL as Assembly.Instruction instrAL1, _)], + comments2, + [(Assembly.Instruction (Instruction.MOV + {src = src2x, + dst = dst2z, ...}), + _)], + comments3, + [(Assembly.Instruction instrAL2, + Liveness.T {liveOut = liveOut2, ...})]] + => rewriter' (stmtMov, src1x, dst1z, + comments1, + stmtAL, instrAL1, + comments2, + src2x, dst2z, + comments3, + instrAL2, liveOut2) + | [[(stmtMov as Assembly.Instruction (Instruction.MOV + {src = src1x, + dst = dst1z, ...}), + _)], + comments1, + [(Assembly.Instruction (Instruction.MOV + {src = src2x, + dst = dst2z, ...}), + _)], + comments2, + [(stmtAL as Assembly.Instruction instrAL1, _)], + comments3, + [(Assembly.Instruction instrAL2, + Liveness.T {liveOut = liveOut2, ...})]] + => rewriter' (stmtMov, src1x, dst1z, + comments1, + stmtAL, instrAL1, + comments2, + src2x, dst2z, + comments3, + instrAL2, liveOut2) + | _ => NONE + end + + val (callback,elimALRedundant_msg) + = make_callback_msg "elimALRedundant" + in + val elimALRedundant : optimization + = {template = template, + rewriter = rewriter, + callback = callback} + val elimALRedundant_msg = elimALRedundant_msg + end + local val isInstructionSSEMOVS_dstTemp : statement_type -> bool = fn (Assembly.Instruction (Instruction.SSE_MOVS @@ -3938,6 +4148,7 @@ struct local val optimizations = elimALCopy:: + elimALRedundant:: elimSSEASCopy:: elimDeadDsts:: elimSelfMove:: @@ -3948,6 +4159,7 @@ struct nil val optimizations_msg = elimALCopy_msg:: + elimALRedundant_msg:: elimSSEASCopy_msg:: elimDeadDsts_msg:: elimSelfMove_msg:: diff --git a/mlton/control/control-flags.sig b/mlton/control/control-flags.sig index 51612c9db0..e12d0e5c75 100644 --- a/mlton/control/control-flags.sig +++ b/mlton/control/control-flags.sig @@ -270,6 +270,9 @@ signature CONTROL_FLAGS = (* whether or not to use comments in native codegen *) val commented: int ref + (* whether to eliminate redundant AL ops in native codegen *) + val elimALRedundant: bool ref + (* whether or not to track liveness of stack slots *) val liveStack: bool ref diff --git a/mlton/control/control-flags.sml b/mlton/control/control-flags.sml index 8edb49fcc4..0361b099bb 100644 --- a/mlton/control/control-flags.sml +++ b/mlton/control/control-flags.sml @@ -946,6 +946,10 @@ structure Native = default = 0, toString = Int.toString} + val elimALRedundant = control {name = "elim AL redundant", + default = true, + toString = Bool.toString} + val liveStack = control {name = "native live stack", default = false, toString = Bool.toString} diff --git a/mlton/main/main.fun b/mlton/main/main.fun index d321eb383a..52893bd053 100644 --- a/mlton/main/main.fun +++ b/mlton/main/main.fun @@ -600,6 +600,9 @@ fun makeOptions {usage} = | SOME v => v])), (Expert, "native-commented", " ", "level of comments (0)", intRef Native.commented), + (Expert, "native-al-redundant", "{true|false}", + "eliminate redundant AL ops", + boolRef Native.elimALRedundant), (Expert, "native-copy-prop", " {true|false}", "use copy propagation", boolRef Native.copyProp), From 01c9f125fda01c46588b9b72ddbab776d6a39321 Mon Sep 17 00:00:00 2001 From: Daman Morris Date: Fri, 27 Jul 2018 12:45:31 -0400 Subject: [PATCH 25/57] Add layout for amd64 chunks/blocks --- mlton/codegen/amd64-codegen/amd64.fun | 27 +++++++++++++++++++++++++++ mlton/codegen/amd64-codegen/amd64.sig | 4 ++++ 2 files changed, 31 insertions(+) diff --git a/mlton/codegen/amd64-codegen/amd64.fun b/mlton/codegen/amd64-codegen/amd64.fun index e9422ff989..9dfe657ac0 100644 --- a/mlton/codegen/amd64-codegen/amd64.fun +++ b/mlton/codegen/amd64-codegen/amd64.fun @@ -3448,6 +3448,8 @@ struct NONE => "" | SOME f => FrameInfo.toString f] + val layout = Layout.str o toString + val uses_defs_kills = fn CReturn {dsts, func, ...} => let @@ -3673,6 +3675,8 @@ struct Option.toString Label.toString return, ">"] + val layout = Layout.str o toString + val uses_defs_kills = fn Switch {test, ...} => {uses = [test], defs = [], kills = []} @@ -3808,6 +3812,26 @@ struct else "NONE"); print "\n") + fun layout (T {entry, profileLabel, statements, transfer, ...}) + = let + open Layout + in + align [seq [Entry.layout entry, + str ": ", + record [("profileLabel", + Option.layout ProfileLabel.layout + profileLabel)], + str "\n"], + indent (align + [align (List.map (statements, + fn s => seq [Assembly.layout s, + str "\n"])), + Transfer.layout transfer], + 4)] + end + + fun layouts (block, output' : Layout.t -> unit) = output' (layout block) + val compress': t' list -> t' list = fn l => List.fold @@ -3865,5 +3889,8 @@ struct struct datatype t = T of {data: Assembly.t list, blocks: Block.t list} + + fun layouts (T {blocks, ...}, output: Layout.t -> unit) + = List.foreach (blocks, fn block => Block.layouts (block, output)) end end diff --git a/mlton/codegen/amd64-codegen/amd64.sig b/mlton/codegen/amd64-codegen/amd64.sig index 1f543c47a8..02b2620be1 100644 --- a/mlton/codegen/amd64-codegen/amd64.sig +++ b/mlton/codegen/amd64-codegen/amd64.sig @@ -1128,6 +1128,8 @@ signature AMD64 = transfer: Transfer.t} val printBlock : t -> unit + val layouts: t * (Layout.t -> unit) -> unit + val compress : t' list -> t list end @@ -1135,5 +1137,7 @@ signature AMD64 = sig datatype t = T of {data: Assembly.t list, blocks: Block.t list} + + val layouts: t * (Layout.t -> unit) -> unit end end From a5d8e795ef89a880106cd5a1766346f16ffb7fa1 Mon Sep 17 00:00:00 2001 From: Daman Morris Date: Fri, 27 Jul 2018 12:45:58 -0400 Subject: [PATCH 26/57] Perform `elimALRedundant` before `moveHoist` Previously the `elimALRedundant` optimization was missing several cases because it occurred after the `moveHoist` optimization. Originally, an additional case was added to the `elimALRedundant` optimization to handle cases where one move had been hoisted immediately before the corresponding arithmetic operations, but this did not account for cases where one or both moves were hoisted elsewhere in the block. This change introduces a new group of optimizations in the `PeepholeLivenessBlock` section which execute before `moveHoist`. In the future additional optimizations may be added, but at present only the `elimALRedundant` optimization occurs in this group. In addition, the `elimALRedundant` was missing a branch to check for imul2 operations, which has now been added. --- .../codegen/amd64-codegen/amd64-simplify.fun | 200 +++++++++--------- 1 file changed, 98 insertions(+), 102 deletions(-) diff --git a/mlton/codegen/amd64-codegen/amd64-simplify.fun b/mlton/codegen/amd64-codegen/amd64-simplify.fun index 93aeeae894..5d83be79a6 100644 --- a/mlton/codegen/amd64-codegen/amd64-simplify.fun +++ b/mlton/codegen/amd64-codegen/amd64-simplify.fun @@ -3087,12 +3087,6 @@ struct val elimALCopy_msg = elimALCopy_msg end - (* TODO add new template/rewriter elimCheckP? based on elimALCopy or - * others - * Also: - * - Fix liveness information - * - Reassemble block w/o check oper - * - Add flag to `main`, `control-flags`, `native`*) local val isInstructionMOV_dstTemp : statement_type -> bool = fn (Assembly.Instruction (Instruction.MOV @@ -3103,28 +3097,19 @@ struct fun isInstructionAL_aux (check) : statement_type -> bool = fn (Assembly.Instruction (Instruction.BinAL - {dst = Operand.MemLoc memloc,...}), - _) + {dst = Operand.MemLoc memloc,...}), _) => check memloc | (Assembly.Instruction (Instruction.pMD - {dst = Operand.MemLoc memloc,...}), - - _) + {dst = Operand.MemLoc memloc,...}), _) => check memloc | (Assembly.Instruction (Instruction.IMUL2 - {dst = Operand.MemLoc memloc,...}), - - _) + {dst = Operand.MemLoc memloc,...}), _) => check memloc | (Assembly.Instruction (Instruction.UnAL - {dst = Operand.MemLoc memloc,...}), - - _) + {dst = Operand.MemLoc memloc,...}), _) => check memloc | (Assembly.Instruction (Instruction.SRAL - {dst = Operand.MemLoc memloc,...}), - - _) + {dst = Operand.MemLoc memloc,...}), _) => check memloc | _ => false val isInstructionAL_dstTemp : statement_type -> bool @@ -3135,51 +3120,40 @@ struct = fn (instr, liveness as Liveness.T {dead, ...}) => isInstructionAL_aux (isDeadTemp dead) (instr, liveness) - val isInstructionALorMOV_dstTemp : statement_type -> bool - = fn stype => isInstructionAL_dstTemp stype orelse - isInstructionMOV_dstTemp stype - val template : template = {start = EmptyOrNonEmpty, statements = [One isInstructionMOV_dstTemp, All isComment, - One isInstructionALorMOV_dstTemp, + One isInstructionAL_dstTemp, All isComment, - One isInstructionALorMOV_dstTemp, + One isInstructionMOV_dstTemp, All isComment, One isInstructionAL_dstDeadTemp], finish = EmptyOrNonEmpty, transfer = fn _ => true} - (* - * Pattern: - * - * mov $x, $z - * AL $y, $z - * mov $x, $t - * AL $y, $t - * setcc - * - * OR - * - * mov $x, $z - * mov $x, $t - * AL $y, $z - * AL $y, $t - * setcc - *) - val rewriter : rewriter - = fn {entry, profileLabel, start, statements, finish, transfer} => - let - fun rewriter' (stmtMov, src1x, dst1z, - comments1, - stmtAL, instrAL1, - comments2, - src2x, dst2z, - comments3, - instrAL2, liveOut2) - = if !Control.Native.elimALRedundant andalso + = fn {entry, + profileLabel, + start, + statements = + [[(stmtMov as Assembly.Instruction (Instruction.MOV + {src = src1x, + dst = dst1z, ...}), + _)], + comments1, + [(stmtAL as Assembly.Instruction instrAL1, _)], + comments2, + [(Assembly.Instruction (Instruction.MOV + {src = src2x, + dst = dst2z, ...}), + _)], + comments3, + [(Assembly.Instruction instrAL2, + Liveness.T {liveOut = liveOut2, ...})]], + finish, + transfer} + => if !Control.Native.elimALRedundant andalso Operand.eq (src1x, src2x) andalso (let fun checkUn (oper1, dst1, oper2, dst2) @@ -3192,6 +3166,7 @@ struct Operand.eq(src1, src2) andalso Operand.eq(dst1z, dst1) andalso Operand.eq(dst2z, dst2) + in case (instrAL1, instrAL2) of (Instruction.BinAL @@ -3204,6 +3179,12 @@ struct Instruction.pMD {oper = oper2, src = src2, dst = dst2, ...}) => checkBin (oper1, src1, dst1, oper2, src2, dst2) + | (Instruction.IMUL2 + {src = src1, dst = dst1, ...}, + Instruction.IMUL2 + {src = src2, dst = dst2, ...}) + => checkBin (Instruction.IMUL, src1, dst1, + Instruction.IMUL, src2, dst2) | (Instruction.UnAL {oper = oper1, dst = dst1, ...}, Instruction.UnAL @@ -3240,52 +3221,7 @@ struct transfer = transfer}) end else NONE - in - case statements of - [[(stmtMov as Assembly.Instruction (Instruction.MOV - {src = src1x, - dst = dst1z, ...}), - _)], - comments1, - [(stmtAL as Assembly.Instruction instrAL1, _)], - comments2, - [(Assembly.Instruction (Instruction.MOV - {src = src2x, - dst = dst2z, ...}), - _)], - comments3, - [(Assembly.Instruction instrAL2, - Liveness.T {liveOut = liveOut2, ...})]] - => rewriter' (stmtMov, src1x, dst1z, - comments1, - stmtAL, instrAL1, - comments2, - src2x, dst2z, - comments3, - instrAL2, liveOut2) - | [[(stmtMov as Assembly.Instruction (Instruction.MOV - {src = src1x, - dst = dst1z, ...}), - _)], - comments1, - [(Assembly.Instruction (Instruction.MOV - {src = src2x, - dst = dst2z, ...}), - _)], - comments2, - [(stmtAL as Assembly.Instruction instrAL1, _)], - comments3, - [(Assembly.Instruction instrAL2, - Liveness.T {liveOut = liveOut2, ...})]] - => rewriter' (stmtMov, src1x, dst1z, - comments1, - stmtAL, instrAL1, - comments2, - src2x, dst2z, - comments3, - instrAL2, liveOut2) - | _ => NONE - end + | _ => Error.bug "amd64Simplify.PeepholeBlock: elimALRedundant" val (callback,elimALRedundant_msg) = make_callback_msg "elimALRedundant" @@ -4146,9 +4082,15 @@ struct end local + val optimizations_pre + = elimALRedundant:: + nil + val optimizations_pre_msg + = elimALRedundant_msg:: + nil + val optimizations = elimALCopy:: - elimALRedundant:: elimSSEASCopy:: elimDeadDsts:: elimSelfMove:: @@ -4159,7 +4101,6 @@ struct nil val optimizations_msg = elimALCopy_msg:: - elimALRedundant_msg:: elimSSEASCopy_msg:: elimDeadDsts_msg:: elimSelfMove_msg:: @@ -4180,6 +4121,21 @@ struct elimSSESSelfMove_minor_msg:: nil in + val peepholeLivenessBlock_pre + = fn block => (peepholeBlock {optimizations = optimizations_pre, + block = block}) + + val (peepholeLivenessBlock_pre, peepholeLivenessBlock_pre_msg) + = tracer + "peepholeLivenessBlock_pre" + peepholeLivenessBlock_pre + + val peepholeLivenessBlock_pre_msg + = fn () => (peepholeLivenessBlock_pre_msg (); + Control.indent (); + List.foreach(optimizations_pre_msg, fn msg => msg ()); + Control.unindent ()) + val peepholeLivenessBlock = fn block => (peepholeBlock {optimizations = optimizations, block = block}) @@ -4403,6 +4359,7 @@ struct {block = block, changed = false, msg = "peepholeBlock/moveHoist/peepholeLivenessBlock/copyPropagate"} + (***************************************************) (* peepholeBlock_pre *) (***************************************************) @@ -4431,9 +4388,47 @@ struct changed = false, msg = "amd64Liveness.LivenessBlock.toLivenessBlock"} + + val _ = if !Control.debug then + (print "\n***** BEGIN PRE-PEEPHOLE *****\n" + ; Block.layouts (amd64Liveness.LivenessBlock.toBlock + {block = block}, + print o Layout.toString) + ; print "\n***** END PRE-PEEPHOLE *****\n") + else () + + (***************************************************) + (* peepholeLivenessBlock_pre *) + (***************************************************) + val {block = block', + changed = changed'} + = PeepholeLivenessBlock.peepholeLivenessBlock_pre + block + + val _ = checkLivenessBlock + {block = block, + block' = block', + msg = "PeepholeLivenessBlock.peepholeLivenessBlock_pre"} + + val _ = changedLivenessBlock_msg + {block = block', + changed = changed', + msg = "PeepholeLivenessBlock.peepholeLivenessBlock_pre"} + val block = block' + val changed = changed orelse changed' + + val _ = if !Control.debug then + (print "\n***** BEGIN POST-PEEPHOLE *****\n" + ; Block.layouts (amd64Liveness.LivenessBlock.toBlock + {block = block}, + print o Layout.toString) + ; print "\n***** END POST-PEEPHOLE *****\n") + else () + (***************************************************) (* moveHoist *) (***************************************************) + val {block = block', changed = changed'} = if !Control.Native.moveHoist @@ -4624,6 +4619,7 @@ struct amd64EntryTransfer.verifyEntryTransfer_msg (); PeepholeBlock.peepholeBlock_pre_msg (); amd64Liveness.LivenessBlock.toLivenessBlock_msg (); + PeepholeLivenessBlock.peepholeLivenessBlock_pre_msg (); MoveHoistLivenessBlock.moveHoist_msg (); PeepholeLivenessBlock.peepholeLivenessBlock_msg (); CopyPropagateLivenessBlock.copyPropagate_msg (); From 81f2c6eb6b958ddced7b5046df8d310122e4b3a5 Mon Sep 17 00:00:00 2001 From: Daman Morris Date: Mon, 30 Jul 2018 10:46:34 -0400 Subject: [PATCH 27/57] Add `elimALRedundant` pass to x86 codegen --- mlton/codegen/x86-codegen/x86-simplify.fun | 189 +++++++++++++++++++++ 1 file changed, 189 insertions(+) diff --git a/mlton/codegen/x86-codegen/x86-simplify.fun b/mlton/codegen/x86-codegen/x86-simplify.fun index acb6662ab3..5cecf6a50a 100644 --- a/mlton/codegen/x86-codegen/x86-simplify.fun +++ b/mlton/codegen/x86-codegen/x86-simplify.fun @@ -3181,6 +3181,152 @@ struct val elimALCopy_msg = elimALCopy_msg end + local + val isInstructionMOV_dstTemp : statement_type -> bool + = fn (Assembly.Instruction (Instruction.MOV + {dst = Operand.MemLoc memloc,...}), + _) + => x86Liveness.track memloc + | _ => false + + fun isInstructionAL_aux (check) : statement_type -> bool + = fn (Assembly.Instruction (Instruction.BinAL + {dst = Operand.MemLoc memloc,...}), _) + => check memloc + | (Assembly.Instruction (Instruction.pMD + {dst = Operand.MemLoc memloc,...}), _) + => check memloc + | (Assembly.Instruction (Instruction.IMUL2 + {dst = Operand.MemLoc memloc,...}), _) + => check memloc + | (Assembly.Instruction (Instruction.UnAL + {dst = Operand.MemLoc memloc,...}), _) + => check memloc + | (Assembly.Instruction (Instruction.SRAL + {dst = Operand.MemLoc memloc,...}), _) + => check memloc + | _ => false + val isInstructionAL_dstTemp : statement_type -> bool + = isInstructionAL_aux x86Liveness.track + fun isDeadTemp dead memloc + = x86Liveness.track memloc andalso LiveSet.contains (dead, memloc) + val isInstructionAL_dstDeadTemp : statement_type -> bool + = fn (instr, liveness as Liveness.T {dead, ...}) + => isInstructionAL_aux (isDeadTemp dead) (instr, liveness) + + val template : template + = {start = EmptyOrNonEmpty, + statements = [One isInstructionMOV_dstTemp, + All isComment, + One isInstructionAL_dstTemp, + All isComment, + One isInstructionMOV_dstTemp, + All isComment, + One isInstructionAL_dstDeadTemp], + finish = EmptyOrNonEmpty, + transfer = fn _ => true} + + val rewriter : rewriter + = fn {entry, + profileLabel, + start, + statements = + [[(stmtMov as Assembly.Instruction (Instruction.MOV + {src = src1x, + dst = dst1z, ...}), + _)], + comments1, + [(stmtAL as Assembly.Instruction instrAL1, _)], + comments2, + [(Assembly.Instruction (Instruction.MOV + {src = src2x, + dst = dst2z, ...}), + _)], + comments3, + [(Assembly.Instruction instrAL2, + Liveness.T {liveOut = liveOut2, ...})]], + finish, + transfer} + => if !Control.Native.elimALRedundant andalso + Operand.eq (src1x, src2x) andalso + (let + fun checkUn (oper1, dst1, oper2, dst2) + = oper1 = oper2 andalso + Operand.eq(dst1z, dst1) andalso + Operand.eq(dst2z, dst2) + + fun checkBin (oper1, src1, dst1, oper2, src2, dst2) + = oper1 = oper2 andalso + Operand.eq(src1, src2) andalso + Operand.eq(dst1z, dst1) andalso + Operand.eq(dst2z, dst2) + + in + case (instrAL1, instrAL2) of + (Instruction.BinAL + {oper = oper1, src = src1, dst = dst1, ...}, + Instruction.BinAL + {oper = oper2, src = src2, dst = dst2, ...}) + => checkBin (oper1, src1, dst1, oper2, src2, dst2) + | (Instruction.pMD + {oper = oper1, src = src1, dst = dst1, ...}, + Instruction.pMD + {oper = oper2, src = src2, dst = dst2, ...}) + => checkBin (oper1, src1, dst1, oper2, src2, dst2) + | (Instruction.IMUL2 + {src = src1, dst = dst1, ...}, + Instruction.IMUL2 + {src = src2, dst = dst2, ...}) + => checkBin (Instruction.IMUL, src1, dst1, + Instruction.IMUL, src2, dst2) + | (Instruction.UnAL + {oper = oper1, dst = dst1, ...}, + Instruction.UnAL + {oper = oper2, dst = dst2, ...}) + => checkUn (oper1, dst1, oper2, dst2) + | (Instruction.SRAL + {oper = oper1, count = src1, dst = dst1, ...}, + Instruction.SRAL + {oper = oper2, count = src2, dst = dst2, ...}) + => checkBin (oper1, src1, dst1, oper2, src2, dst2) + | _ => false + end) + then + let + val excomm = fn comm => List.map (comm, fn (c, _) => c) + val comments1 = excomm comments1 + val comments2 = excomm comments2 + val comments3 = excomm comments3 + + val statements = + stmtMov::(comments1 @ (stmtAL::(comments2 @ comments3))) + val {statements, ...} + = LivenessBlock.toLivenessStatements + {statements = statements, live = liveOut2} + val statements + = List.fold (start, + List.concat [statements, finish], + op ::) + in + SOME (LivenessBlock.T + {entry = entry, + profileLabel = profileLabel, + statements = statements, + transfer = transfer}) + end + else NONE + | _ => Error.bug "x86Simplify.PeepholeBlock: elimALRedundant" + + val (callback,elimALRedundant_msg) + = make_callback_msg "elimALRedundant" + in + val elimALRedundant : optimization + = {template = template, + rewriter = rewriter, + callback = callback} + val elimALRedundant_msg = elimALRedundant_msg + end + local val isInstructionMOV_eqSrcDst : statement_type -> bool = fn (Assembly.Instruction (Instruction.MOV @@ -4065,6 +4211,13 @@ struct end local + val optimizations_pre + = elimALRedundant:: + nil + val optimizations_pre_msg + = elimALRedundant_msg:: + nil + val optimizations = elimALCopy:: elimFltACopy:: @@ -4097,6 +4250,21 @@ struct elimFltSelfMove_minor_msg:: nil in + val peepholeLivenessBlock_pre + = fn block => (peepholeBlock {optimizations = optimizations_pre, + block = block}) + + val (peepholeLivenessBlock_pre, peepholeLivenessBlock_pre_msg) + = tracer + "peepholeLivenessBlock_pre" + peepholeLivenessBlock_pre + + val peepholeLivenessBlock_pre_msg + = fn () => (peepholeLivenessBlock_pre_msg (); + Control.indent (); + List.foreach(optimizations_pre_msg, fn msg => msg ()); + Control.unindent ()) + val peepholeLivenessBlock = fn block => (peepholeBlock {optimizations = optimizations, block = block}) @@ -4348,6 +4516,26 @@ struct changed = false, msg = "x86Liveness.LivenessBlock.toLivenessBlock"} + (***************************************************) + (* peepholeLivenessBlock_pre *) + (***************************************************) + val {block = block', + changed = changed'} + = PeepholeLivenessBlock.peepholeLivenessBlock_pre + block + + val _ = checkLivenessBlock + {block = block, + block' = block', + msg = "PeepholeLivenessBlock.peepholeLivenessBlock_pre"} + + val _ = changedLivenessBlock_msg + {block = block', + changed = changed', + msg = "PeepholeLivenessBlock.peepholeLivenessBlock_pre"} + val block = block' + val changed = changed orelse changed' + (***************************************************) (* moveHoist *) (***************************************************) @@ -4541,6 +4729,7 @@ struct x86EntryTransfer.verifyEntryTransfer_msg (); PeepholeBlock.peepholeBlock_pre_msg (); x86Liveness.LivenessBlock.toLivenessBlock_msg (); + PeepholeLivenessBlock.peepholeLivenessBlock_pre_msg (); MoveHoistLivenessBlock.moveHoist_msg (); PeepholeLivenessBlock.peepholeLivenessBlock_msg (); CopyPropagateLivenessBlock.copyPropagate_msg (); From ff6b544bdccebed69e2ce0579cd5a7c853f5d2e2 Mon Sep 17 00:00:00 2001 From: Daman Morris Date: Tue, 31 Jul 2018 12:51:44 -0400 Subject: [PATCH 28/57] Add more peephole optimization coverage Previously, some redundant `mulCheckP` operations were missed in the main peephole optimization pass due to a previous multiplication of a variable by 2 being replaced by an addition of that variable to itself. This change adds a new peephole optimization to catch such operations. --- .../codegen/amd64-codegen/amd64-simplify.fun | 106 +++++++++++++++++- mlton/codegen/x86-codegen/x86-simplify.fun | 103 +++++++++++++++++ 2 files changed, 208 insertions(+), 1 deletion(-) diff --git a/mlton/codegen/amd64-codegen/amd64-simplify.fun b/mlton/codegen/amd64-codegen/amd64-simplify.fun index 5d83be79a6..0fd818d862 100644 --- a/mlton/codegen/amd64-codegen/amd64-simplify.fun +++ b/mlton/codegen/amd64-codegen/amd64-simplify.fun @@ -3087,6 +3087,107 @@ struct val elimALCopy_msg = elimALCopy_msg end + local + fun isInstructionMOV_aux (check) : statement_type -> bool + = fn (Assembly.Instruction (Instruction.MOV + {dst = Operand.MemLoc memloc, ...}), + _) + => check memloc + | _ => false + + fun isInstructionBinAL_aux (check) : statement_type -> bool + = fn (Assembly.Instruction (Instruction.BinAL + {dst = Operand.MemLoc memloc, ...}), + _) + => check memloc + | _ => false + + fun isDeadTemp dead memloc + = amd64Liveness.track memloc andalso LiveSet.contains (dead, memloc) + val isInstructionBinAL_dstDeadTemp : statement_type -> bool + = fn (instr, liveness as Liveness.T {dead, ...}) + => isInstructionBinAL_aux (isDeadTemp dead) (instr, liveness) + + val template : template + = {start = EmptyOrNonEmpty, + statements = [One (isInstructionMOV_aux (fn _ => true)), + All isComment, + One (isInstructionBinAL_aux (fn _ => true)), + All isComment, + One (isInstructionMOV_aux amd64Liveness.track), + All isComment, + One isInstructionBinAL_dstDeadTemp], + finish = EmptyOrNonEmpty, + transfer = fn _ => true} + + val rewriter : rewriter + = fn {entry, + profileLabel, + start, + statements = + [[(stmtMov as Assembly.Instruction (Instruction.MOV + {src = src1x, + dst = dst1z, ...}), + _)], + comments1, + [(stmtAL as Assembly.Instruction (Instruction.BinAL + {src = src1, + dst = dst1, ...}), + _)], + comments2, + [(Assembly.Instruction (Instruction.MOV + {src = src2x, + dst = dst2z, ...}), + _)], + comments3, + [(Assembly.Instruction (Instruction.BinAL + {src = src2, + dst = dst2, ...}), + Liveness.T {liveOut = liveOut2, ...})]], + finish, + transfer} + => if !Control.Native.elimALRedundant andalso + Operand.eq (src1x, src2x) andalso + Operand.eq (src1, dst1) andalso + Operand.eq (src2, dst2) andalso + Operand.eq (dst1z, src1) andalso + Operand.eq (dst2z, src2) + then + let + val excomm = fn comm => List.map (comm, fn (c, _) => c) + val comments1 = excomm comments1 + val comments2 = excomm comments2 + val comments3 = excomm comments3 + + val statements = + stmtMov::(comments1 @ (stmtAL::(comments2 @ comments3))) + val {statements, ...} + = LivenessBlock.toLivenessStatements + {statements = statements, live = liveOut2} + val statements + = List.fold (start, + List.concat [statements, finish], + op ::) + in + SOME (LivenessBlock.T + {entry = entry, + profileLabel = profileLabel, + statements = statements, + transfer = transfer}) + end + else NONE + | _ => Error.bug "amd64Simplify.PeepholeBlock: elimALRedundant_pseudo" + + val (callback, elimALRedundant_pseudo_msg) + = make_callback_msg "elimALRedundant_pseudo" + in + val elimALRedundant_pseudo : optimization + = {template = template, + rewriter = rewriter, + callback = callback} + val elimALRedundant_pseudo_msg = elimALRedundant_pseudo_msg + end + local val isInstructionMOV_dstTemp : statement_type -> bool = fn (Assembly.Instruction (Instruction.MOV @@ -3166,7 +3267,6 @@ struct Operand.eq(src1, src2) andalso Operand.eq(dst1z, dst1) andalso Operand.eq(dst2z, dst2) - in case (instrAL1, instrAL2) of (Instruction.BinAL @@ -3174,6 +3274,8 @@ struct Instruction.BinAL {oper = oper2, src = src2, dst = dst2, ...}) => checkBin (oper1, src1, dst1, oper2, src2, dst2) + orelse + checkBin' (oper1, src2, dst1, oper2, src2, dst2) | (Instruction.pMD {oper = oper1, src = src1, dst = dst1, ...}, Instruction.pMD @@ -4084,9 +4186,11 @@ struct local val optimizations_pre = elimALRedundant:: + elimALRedundant_pseudo:: nil val optimizations_pre_msg = elimALRedundant_msg:: + elimALRedundant_pseudo_msg:: nil val optimizations diff --git a/mlton/codegen/x86-codegen/x86-simplify.fun b/mlton/codegen/x86-codegen/x86-simplify.fun index 5cecf6a50a..5d0d699ca8 100644 --- a/mlton/codegen/x86-codegen/x86-simplify.fun +++ b/mlton/codegen/x86-codegen/x86-simplify.fun @@ -3181,6 +3181,107 @@ struct val elimALCopy_msg = elimALCopy_msg end + local + fun isInstructionMOV_aux (check) : statement_type -> bool + = fn (Assembly.Instruction (Instruction.MOV + {dst = Operand.MemLoc memloc, ...}), + _) + => check memloc + | _ => false + + fun isInstructionBinAL_aux (check) : statement_type -> bool + = fn (Assembly.Instruction (Instruction.BinAL + {dst = Operand.MemLoc memloc, ...}), + _) + => check memloc + | _ => false + + fun isDeadTemp dead memloc + = x86Liveness.track memloc andalso LiveSet.contains (dead, memloc) + val isInstructionBinAL_dstDeadTemp : statement_type -> bool + = fn (instr, liveness as Liveness.T {dead, ...}) + => isInstructionBinAL_aux (isDeadTemp dead) (instr, liveness) + + val template : template + = {start = EmptyOrNonEmpty, + statements = [One (isInstructionMOV_aux (fn _ => true)), + All isComment, + One (isInstructionBinAL_aux (fn _ => true)), + All isComment, + One (isInstructionMOV_aux x86Liveness.track), + All isComment, + One isInstructionBinAL_dstDeadTemp], + finish = EmptyOrNonEmpty, + transfer = fn _ => true} + + val rewriter : rewriter + = fn {entry, + profileLabel, + start, + statements = + [[(stmtMov as Assembly.Instruction (Instruction.MOV + {src = src1x, + dst = dst1z, ...}), + _)], + comments1, + [(stmtAL as Assembly.Instruction (Instruction.BinAL + {src = src1, + dst = dst1, ...}), + _)], + comments2, + [(Assembly.Instruction (Instruction.MOV + {src = src2x, + dst = dst2z, ...}), + _)], + comments3, + [(Assembly.Instruction (Instruction.BinAL + {src = src2, + dst = dst2, ...}), + Liveness.T {liveOut = liveOut2, ...})]], + finish, + transfer} + => if !Control.Native.elimALRedundant andalso + Operand.eq (src1x, src2x) andalso + Operand.eq (src1, dst1) andalso + Operand.eq (src2, dst2) andalso + Operand.eq (dst1z, src1) andalso + Operand.eq (dst2z, src2) + then + let + val excomm = fn comm => List.map (comm, fn (c, _) => c) + val comments1 = excomm comments1 + val comments2 = excomm comments2 + val comments3 = excomm comments3 + + val statements = + stmtMov::(comments1 @ (stmtAL::(comments2 @ comments3))) + val {statements, ...} + = LivenessBlock.toLivenessStatements + {statements = statements, live = liveOut2} + val statements + = List.fold (start, + List.concat [statements, finish], + op ::) + in + SOME (LivenessBlock.T + {entry = entry, + profileLabel = profileLabel, + statements = statements, + transfer = transfer}) + end + else NONE + | _ => Error.bug "x86Simplify.PeepholeBlock: elimALRedundant_pseudo" + + val (callback, elimALRedundant_pseudo_msg) + = make_callback_msg "elimALRedundant_pseudo" + in + val elimALRedundant_pseudo : optimization + = {template = template, + rewriter = rewriter, + callback = callback} + val elimALRedundant_pseudo_msg = elimALRedundant_pseudo_msg + end + local val isInstructionMOV_dstTemp : statement_type -> bool = fn (Assembly.Instruction (Instruction.MOV @@ -4213,9 +4314,11 @@ struct local val optimizations_pre = elimALRedundant:: + elimALRedundant_pseudo:: nil val optimizations_pre_msg = elimALRedundant_msg:: + elimALRedundant_pseudo_msg:: nil val optimizations From 5de7724f8aa661eed17a5e19d0e478f03c38a199 Mon Sep 17 00:00:00 2001 From: Daman Morris Date: Wed, 1 Aug 2018 15:38:45 -0400 Subject: [PATCH 29/57] Fix undefined reference in amd64-simplify.fun --- mlton/codegen/amd64-codegen/amd64-simplify.fun | 2 -- 1 file changed, 2 deletions(-) diff --git a/mlton/codegen/amd64-codegen/amd64-simplify.fun b/mlton/codegen/amd64-codegen/amd64-simplify.fun index 0fd818d862..5bd912f3dd 100644 --- a/mlton/codegen/amd64-codegen/amd64-simplify.fun +++ b/mlton/codegen/amd64-codegen/amd64-simplify.fun @@ -3274,8 +3274,6 @@ struct Instruction.BinAL {oper = oper2, src = src2, dst = dst2, ...}) => checkBin (oper1, src1, dst1, oper2, src2, dst2) - orelse - checkBin' (oper1, src2, dst1, oper2, src2, dst2) | (Instruction.pMD {oper = oper1, src = src1, dst = dst1, ...}, Instruction.pMD From 47465f0c60f7daf0585ed4fe60d689075eac25db Mon Sep 17 00:00:00 2001 From: Daman Morris Date: Fri, 3 Aug 2018 13:03:12 -0400 Subject: [PATCH 30/57] Replace `0-x` in negCheckP with a NEG instruction --- mlton/codegen/amd64-codegen/amd64-mlton.fun | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/mlton/codegen/amd64-codegen/amd64-mlton.fun b/mlton/codegen/amd64-codegen/amd64-mlton.fun index d22e80854b..34760e1862 100644 --- a/mlton/codegen/amd64-codegen/amd64-mlton.fun +++ b/mlton/codegen/amd64-codegen/amd64-mlton.fun @@ -501,7 +501,7 @@ struct transfer = NONE}] end - fun negcc () + fun unalcc (oper, condition) = let val (src,srcsize) = getSrc1 () val (dst,dstsize) = getDst1 () @@ -513,15 +513,14 @@ struct statements = [Assembly.instruction_mov {dst = tmp, - src = Operand.immediate_zero, + src = src, size = srcsize}, - Assembly.instruction_binal - {oper = Instruction.SUB, + Assembly.instruction_unal + {oper = oper, dst = tmp, - src = src, size = srcsize}, Assembly.instruction_setcc - {condition = Instruction.O, + {condition = condition, dst = dst, size = dstsize}], transfer = NONE}] @@ -1234,7 +1233,7 @@ struct else pmdcc (Instruction.MUL, amd64.Instruction.C) | Word_neg _ => unal Instruction.NEG - | Word_negCheckP _ => negcc () + | Word_negCheckP _ => unalcc (Instruction.NEG, Instruction.O) | Word_notb _ => unal Instruction.NOT | Word_orb _ => binal Instruction.OR | Word_quot (_, {signed}) => From da8f4ee9ecf450e9ddace777072a262f6e848715 Mon Sep 17 00:00:00 2001 From: Daman Morris Date: Mon, 6 Aug 2018 14:11:23 -0400 Subject: [PATCH 31/57] Modify peephole template for native codegens --- .../codegen/amd64-codegen/amd64-simplify.fun | 33 ++++++++++++++----- mlton/codegen/x86-codegen/x86-simplify.fun | 25 +++++++++----- 2 files changed, 40 insertions(+), 18 deletions(-) diff --git a/mlton/codegen/amd64-codegen/amd64-simplify.fun b/mlton/codegen/amd64-codegen/amd64-simplify.fun index 5bd912f3dd..4a10eb5592 100644 --- a/mlton/codegen/amd64-codegen/amd64-simplify.fun +++ b/mlton/codegen/amd64-codegen/amd64-simplify.fun @@ -3095,6 +3095,11 @@ struct => check memloc | _ => false + val isInstructionMOV : statement_type -> bool + = isInstructionMOV_aux (fn _ => true) + val isInstructionMOV_dstTemp : statement_type -> bool + = isInstructionMOV_aux amd64Liveness.track + fun isInstructionBinAL_aux (check) : statement_type -> bool = fn (Assembly.Instruction (Instruction.BinAL {dst = Operand.MemLoc memloc, ...}), @@ -3102,6 +3107,9 @@ struct => check memloc | _ => false + val isInstructionBinAL : statement_type -> bool + = isInstructionBinAL_aux (fn _ => true) + fun isDeadTemp dead memloc = amd64Liveness.track memloc andalso LiveSet.contains (dead, memloc) val isInstructionBinAL_dstDeadTemp : statement_type -> bool @@ -3110,11 +3118,11 @@ struct val template : template = {start = EmptyOrNonEmpty, - statements = [One (isInstructionMOV_aux (fn _ => true)), + statements = [One isInstructionMOV, All isComment, - One (isInstructionBinAL_aux (fn _ => true)), + One isInstructionBinAL, All isComment, - One (isInstructionMOV_aux amd64Liveness.track), + One isInstructionMOV_dstTemp, All isComment, One isInstructionBinAL_dstDeadTemp], finish = EmptyOrNonEmpty, @@ -3189,13 +3197,18 @@ struct end local - val isInstructionMOV_dstTemp : statement_type -> bool + fun isInstructionMOV_aux (check) : statement_type -> bool = fn (Assembly.Instruction (Instruction.MOV {dst = Operand.MemLoc memloc,...}), _) - => amd64Liveness.track memloc + => check memloc | _ => false + val isInstructionMOV : statement_type -> bool + = isInstructionMOV_aux (fn _ => true) + val isInstructionMOV_dstTemp : statement_type -> bool + = isInstructionMOV_aux amd64Liveness.track + fun isInstructionAL_aux (check) : statement_type -> bool = fn (Assembly.Instruction (Instruction.BinAL {dst = Operand.MemLoc memloc,...}), _) @@ -3213,8 +3226,10 @@ struct {dst = Operand.MemLoc memloc,...}), _) => check memloc | _ => false - val isInstructionAL_dstTemp : statement_type -> bool - = isInstructionAL_aux amd64Liveness.track + + val isInstructionAL : statement_type -> bool + = isInstructionAL_aux (fn _ => true) + fun isDeadTemp dead memloc = amd64Liveness.track memloc andalso LiveSet.contains (dead, memloc) val isInstructionAL_dstDeadTemp : statement_type -> bool @@ -3223,9 +3238,9 @@ struct val template : template = {start = EmptyOrNonEmpty, - statements = [One isInstructionMOV_dstTemp, + statements = [One isInstructionMOV, All isComment, - One isInstructionAL_dstTemp, + One isInstructionAL, All isComment, One isInstructionMOV_dstTemp, All isComment, diff --git a/mlton/codegen/x86-codegen/x86-simplify.fun b/mlton/codegen/x86-codegen/x86-simplify.fun index 5d0d699ca8..e3b3f18c61 100644 --- a/mlton/codegen/x86-codegen/x86-simplify.fun +++ b/mlton/codegen/x86-codegen/x86-simplify.fun @@ -3189,6 +3189,9 @@ struct => check memloc | _ => false + val isInstructionMOV = isInstructionMOV_aux (fn _ => true) + val isInstructionMOV_dstTemp = isInstructionMOV_aux x86Liveness.track + fun isInstructionBinAL_aux (check) : statement_type -> bool = fn (Assembly.Instruction (Instruction.BinAL {dst = Operand.MemLoc memloc, ...}), @@ -3196,6 +3199,8 @@ struct => check memloc | _ => false + val isInstructionBinAL = isInstructionBinAL_aux (fn _ => true) + fun isDeadTemp dead memloc = x86Liveness.track memloc andalso LiveSet.contains (dead, memloc) val isInstructionBinAL_dstDeadTemp : statement_type -> bool @@ -3204,11 +3209,11 @@ struct val template : template = {start = EmptyOrNonEmpty, - statements = [One (isInstructionMOV_aux (fn _ => true)), + statements = [One isInstructionMOV, All isComment, - One (isInstructionBinAL_aux (fn _ => true)), + One isInstructionBinAL, All isComment, - One (isInstructionMOV_aux x86Liveness.track), + One isInstructionMOV_dstTemp, All isComment, One isInstructionBinAL_dstDeadTemp], finish = EmptyOrNonEmpty, @@ -3283,13 +3288,16 @@ struct end local - val isInstructionMOV_dstTemp : statement_type -> bool + fun isInstructionMOV_aux (check) : statement_type -> bool = fn (Assembly.Instruction (Instruction.MOV {dst = Operand.MemLoc memloc,...}), _) - => x86Liveness.track memloc + => check memloc | _ => false + val isInstructionMOV = isInstructionMOV_aux (fn _ => true) + val isInstructionMOV_dstTemp = isInstructionMOV_aux x86Liveness.track + fun isInstructionAL_aux (check) : statement_type -> bool = fn (Assembly.Instruction (Instruction.BinAL {dst = Operand.MemLoc memloc,...}), _) @@ -3307,8 +3315,7 @@ struct {dst = Operand.MemLoc memloc,...}), _) => check memloc | _ => false - val isInstructionAL_dstTemp : statement_type -> bool - = isInstructionAL_aux x86Liveness.track + val isInstructionAL = isInstructionAL_aux (fn _ => true) fun isDeadTemp dead memloc = x86Liveness.track memloc andalso LiveSet.contains (dead, memloc) val isInstructionAL_dstDeadTemp : statement_type -> bool @@ -3317,9 +3324,9 @@ struct val template : template = {start = EmptyOrNonEmpty, - statements = [One isInstructionMOV_dstTemp, + statements = [One isInstructionMOV, All isComment, - One isInstructionAL_dstTemp, + One isInstructionAL, All isComment, One isInstructionMOV_dstTemp, All isComment, From 7f8f493a3b45af4b03f47c5537d3ca0af6b9f96e Mon Sep 17 00:00:00 2001 From: Daman Morris Date: Mon, 13 Aug 2018 09:22:04 -0400 Subject: [PATCH 32/57] Use only `_overflow` builtins for the C codegen Previously the implementations of the relevant primitives in `Word-check.h` used either `_overflow` or `_overflow_p` builtins, depending on the GCC version, but since clang only has the `_overflow` variety, for simplicity's sake this removes the predicate variants. --- runtime/basis/Word/Word-check.h | 24 +++--------------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/runtime/basis/Word/Word-check.h b/runtime/basis/Word/Word-check.h index 62d0eecd6d..2368219037 100644 --- a/runtime/basis/Word/Word-check.h +++ b/runtime/basis/Word/Word-check.h @@ -1,4 +1,3 @@ -#if __GNUC__ < 7 #define add_overflow_b(x, y, size, onOverflow, onSuccess) \ do { \ WordS##size res; \ @@ -23,31 +22,14 @@ } \ onSuccess; \ } while (0) -#else -#define add_overflow_b(x, y, size, onOverflow, onSuccess) \ - do { \ - if (__builtin_add_overflow_p(x, y, (WordS##size) 0)) { \ - onOverflow; \ - } \ - onSuccess; \ - } while (0) -#define sub_overflow_b(x, y, size, onOverflow, onSuccess) \ - do { \ - if (__builtin_sub_overflow_p(x, y, (WordS##size) 0)) { \ - onOverflow; \ - } \ - onSuccess; \ - } while (0) -#define mul_overflow_b(x, y, size, onOverflow, onSuccess) \ +#define neg_overflow_b(x, size, onOverflow, onSuccess) \ do { \ - if (__builtin_mul_overflow_p(x, y, (WordS##size) 0)) { \ + Word##size res; \ + if (__builtin_sub_overflow(0, x, &res)) { \ onOverflow; \ } \ onSuccess; \ } while (0) -#endif -#define neg_overflow_b(x, size, onOverflow, onSuccess) \ - sub_overflow_b(0, x, size, onOverflow, onSuccess) /** * Old-style overflow operators From 7cd21e989ffd567ca4f8d906f7d5fcbdb5813f26 Mon Sep 17 00:00:00 2001 From: Daman Morris Date: Mon, 13 Aug 2018 14:32:21 -0400 Subject: [PATCH 33/57] Refactor C overflow primitives and FFI definitions --- basis-library/primitive/basis-ffi.sml | 8 +++--- runtime/basis-ffi.h | 8 +++--- runtime/basis/Word/Word-check.h | 40 +++++++++++++-------------- runtime/gen/basis-ffi.def | 8 +++--- runtime/gen/basis-ffi.h | 8 +++--- runtime/gen/basis-ffi.sml | 8 +++--- 6 files changed, 40 insertions(+), 40 deletions(-) diff --git a/basis-library/primitive/basis-ffi.sml b/basis-library/primitive/basis-ffi.sml index cd74bcd57e..47e017bfe0 100644 --- a/basis-library/primitive/basis-ffi.sml +++ b/basis-library/primitive/basis-ffi.sml @@ -1148,6 +1148,7 @@ val andb = _import "Word16_andb" private : Word16.t * Word16.t -> Word16.t; val equal = _import "Word16_equal" private : Word16.t * Word16.t -> Bool.t; val lshift = _import "Word16_lshift" private : Word16.t * Word32.t -> Word16.t; val neg = _import "Word16_neg" private : Word16.t -> Word16.t; +val negCheckP = _import "Word16_negCheckP" private : Int16.t -> Bool.t; val notb = _import "Word16_notb" private : Word16.t -> Word16.t; val orb = _import "Word16_orb" private : Word16.t * Word16.t -> Word16.t; val rol = _import "Word16_rol" private : Word16.t * Word32.t -> Word16.t; @@ -1164,6 +1165,7 @@ val castToReal32 = _import "Word32_castToReal32" private : Word32.t -> Real32.t; val equal = _import "Word32_equal" private : Word32.t * Word32.t -> Bool.t; val lshift = _import "Word32_lshift" private : Word32.t * Word32.t -> Word32.t; val neg = _import "Word32_neg" private : Word32.t -> Word32.t; +val negCheckP = _import "Word32_negCheckP" private : Int32.t -> Bool.t; val notb = _import "Word32_notb" private : Word32.t -> Word32.t; val orb = _import "Word32_orb" private : Word32.t * Word32.t -> Word32.t; val rol = _import "Word32_rol" private : Word32.t * Word32.t -> Word32.t; @@ -1182,6 +1184,7 @@ val fetch = _import "Word64_fetch" private : (Word64.t) ref -> Word64.t; val lshift = _import "Word64_lshift" private : Word64.t * Word32.t -> Word64.t; val move = _import "Word64_move" private : (Word64.t) ref * (Word64.t) ref -> unit; val neg = _import "Word64_neg" private : Word64.t -> Word64.t; +val negCheckP = _import "Word64_negCheckP" private : Int64.t -> Bool.t; val notb = _import "Word64_notb" private : Word64.t -> Word64.t; val orb = _import "Word64_orb" private : Word64.t * Word64.t -> Word64.t; val rol = _import "Word64_rol" private : Word64.t * Word32.t -> Word64.t; @@ -1198,6 +1201,7 @@ val andb = _import "Word8_andb" private : Word8.t * Word8.t -> Word8.t; val equal = _import "Word8_equal" private : Word8.t * Word8.t -> Bool.t; val lshift = _import "Word8_lshift" private : Word8.t * Word32.t -> Word8.t; val neg = _import "Word8_neg" private : Word8.t -> Word8.t; +val negCheckP = _import "Word8_negCheckP" private : Int8.t -> Bool.t; val notb = _import "Word8_notb" private : Word8.t -> Word8.t; val orb = _import "Word8_orb" private : Word8.t * Word8.t -> Word8.t; val rol = _import "Word8_rol" private : Word8.t * Word32.t -> Word8.t; @@ -1218,7 +1222,6 @@ val le = _import "WordS16_le" private : Int16.t * Int16.t -> Bool.t; val lt = _import "WordS16_lt" private : Int16.t * Int16.t -> Bool.t; val mul = _import "WordS16_mul" private : Int16.t * Int16.t -> Int16.t; val mulCheckP = _import "WordS16_mulCheckP" private : Int16.t * Int16.t -> Bool.t; -val negCheckP = _import "WordS16_negCheckP" private : Int16.t -> Bool.t; val quot = _import "WordS16_quot" private : Int16.t * Int16.t -> Int16.t; val rem = _import "WordS16_rem" private : Int16.t * Int16.t -> Int16.t; val rndToReal32 = _import "WordS16_rndToReal32" private : Int16.t -> Real32.t; @@ -1239,7 +1242,6 @@ val le = _import "WordS32_le" private : Int32.t * Int32.t -> Bool.t; val lt = _import "WordS32_lt" private : Int32.t * Int32.t -> Bool.t; val mul = _import "WordS32_mul" private : Int32.t * Int32.t -> Int32.t; val mulCheckP = _import "WordS32_mulCheckP" private : Int32.t * Int32.t -> Bool.t; -val negCheckP = _import "WordS32_negCheckP" private : Int32.t -> Bool.t; val quot = _import "WordS32_quot" private : Int32.t * Int32.t -> Int32.t; val rem = _import "WordS32_rem" private : Int32.t * Int32.t -> Int32.t; val rndToReal32 = _import "WordS32_rndToReal32" private : Int32.t -> Real32.t; @@ -1260,7 +1262,6 @@ val le = _import "WordS64_le" private : Int64.t * Int64.t -> Bool.t; val lt = _import "WordS64_lt" private : Int64.t * Int64.t -> Bool.t; val mul = _import "WordS64_mul" private : Int64.t * Int64.t -> Int64.t; val mulCheckP = _import "WordS64_mulCheckP" private : Int64.t * Int64.t -> Bool.t; -val negCheckP = _import "WordS64_negCheckP" private : Int64.t -> Bool.t; val quot = _import "WordS64_quot" private : Int64.t * Int64.t -> Int64.t; val rem = _import "WordS64_rem" private : Int64.t * Int64.t -> Int64.t; val rndToReal32 = _import "WordS64_rndToReal32" private : Int64.t -> Real32.t; @@ -1281,7 +1282,6 @@ val le = _import "WordS8_le" private : Int8.t * Int8.t -> Bool.t; val lt = _import "WordS8_lt" private : Int8.t * Int8.t -> Bool.t; val mul = _import "WordS8_mul" private : Int8.t * Int8.t -> Int8.t; val mulCheckP = _import "WordS8_mulCheckP" private : Int8.t * Int8.t -> Bool.t; -val negCheckP = _import "WordS8_negCheckP" private : Int8.t -> Bool.t; val quot = _import "WordS8_quot" private : Int8.t * Int8.t -> Int8.t; val rem = _import "WordS8_rem" private : Int8.t * Int8.t -> Int8.t; val rndToReal32 = _import "WordS8_rndToReal32" private : Int8.t -> Real32.t; diff --git a/runtime/basis-ffi.h b/runtime/basis-ffi.h index 0772b62891..4c7e5af415 100644 --- a/runtime/basis-ffi.h +++ b/runtime/basis-ffi.h @@ -938,6 +938,7 @@ MLTON_CODEGEN_STATIC_INLINE Word16_t Word16_andb(Word16_t,Word16_t); MLTON_CODEGEN_STATIC_INLINE Bool_t Word16_equal(Word16_t,Word16_t); MLTON_CODEGEN_STATIC_INLINE Word16_t Word16_lshift(Word16_t,Word32_t); MLTON_CODEGEN_STATIC_INLINE Word16_t Word16_neg(Word16_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t Word16_negCheckP(Int16_t); MLTON_CODEGEN_STATIC_INLINE Word16_t Word16_notb(Word16_t); MLTON_CODEGEN_STATIC_INLINE Word16_t Word16_orb(Word16_t,Word16_t); MLTON_CODEGEN_STATIC_INLINE Word16_t Word16_rol(Word16_t,Word32_t); @@ -950,6 +951,7 @@ MLTON_CODEGEN_STATIC_INLINE Real32_t Word32_castToReal32(Word32_t); MLTON_CODEGEN_STATIC_INLINE Bool_t Word32_equal(Word32_t,Word32_t); MLTON_CODEGEN_STATIC_INLINE Word32_t Word32_lshift(Word32_t,Word32_t); MLTON_CODEGEN_STATIC_INLINE Word32_t Word32_neg(Word32_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t Word32_negCheckP(Int32_t); MLTON_CODEGEN_STATIC_INLINE Word32_t Word32_notb(Word32_t); MLTON_CODEGEN_STATIC_INLINE Word32_t Word32_orb(Word32_t,Word32_t); MLTON_CODEGEN_STATIC_INLINE Word32_t Word32_rol(Word32_t,Word32_t); @@ -964,6 +966,7 @@ MLTON_CODEGEN_STATIC_INLINE Word64_t Word64_fetch(Ref(Word64_t)); MLTON_CODEGEN_STATIC_INLINE Word64_t Word64_lshift(Word64_t,Word32_t); MLTON_CODEGEN_STATIC_INLINE void Word64_move(Ref(Word64_t),Ref(Word64_t)); MLTON_CODEGEN_STATIC_INLINE Word64_t Word64_neg(Word64_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t Word64_negCheckP(Int64_t); MLTON_CODEGEN_STATIC_INLINE Word64_t Word64_notb(Word64_t); MLTON_CODEGEN_STATIC_INLINE Word64_t Word64_orb(Word64_t,Word64_t); MLTON_CODEGEN_STATIC_INLINE Word64_t Word64_rol(Word64_t,Word32_t); @@ -976,6 +979,7 @@ MLTON_CODEGEN_STATIC_INLINE Word8_t Word8_andb(Word8_t,Word8_t); MLTON_CODEGEN_STATIC_INLINE Bool_t Word8_equal(Word8_t,Word8_t); MLTON_CODEGEN_STATIC_INLINE Word8_t Word8_lshift(Word8_t,Word32_t); MLTON_CODEGEN_STATIC_INLINE Word8_t Word8_neg(Word8_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t Word8_negCheckP(Int8_t); MLTON_CODEGEN_STATIC_INLINE Word8_t Word8_notb(Word8_t); MLTON_CODEGEN_STATIC_INLINE Word8_t Word8_orb(Word8_t,Word8_t); MLTON_CODEGEN_STATIC_INLINE Word8_t Word8_rol(Word8_t,Word32_t); @@ -993,7 +997,6 @@ MLTON_CODEGEN_STATIC_INLINE Bool_t WordS16_le(Int16_t,Int16_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordS16_lt(Int16_t,Int16_t); MLTON_CODEGEN_STATIC_INLINE Int16_t WordS16_mul(Int16_t,Int16_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordS16_mulCheckP(Int16_t,Int16_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordS16_negCheckP(Int16_t); MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) Int16_t WordS16_quot(Int16_t,Int16_t); MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) Int16_t WordS16_rem(Int16_t,Int16_t); PRIVATE Real32_t WordS16_rndToReal32(Int16_t); @@ -1011,7 +1014,6 @@ MLTON_CODEGEN_STATIC_INLINE Bool_t WordS32_le(Int32_t,Int32_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordS32_lt(Int32_t,Int32_t); MLTON_CODEGEN_STATIC_INLINE Int32_t WordS32_mul(Int32_t,Int32_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordS32_mulCheckP(Int32_t,Int32_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordS32_negCheckP(Int32_t); MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) Int32_t WordS32_quot(Int32_t,Int32_t); MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) Int32_t WordS32_rem(Int32_t,Int32_t); PRIVATE Real32_t WordS32_rndToReal32(Int32_t); @@ -1029,7 +1031,6 @@ MLTON_CODEGEN_STATIC_INLINE Bool_t WordS64_le(Int64_t,Int64_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordS64_lt(Int64_t,Int64_t); MLTON_CODEGEN_STATIC_INLINE Int64_t WordS64_mul(Int64_t,Int64_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordS64_mulCheckP(Int64_t,Int64_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordS64_negCheckP(Int64_t); MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) Int64_t WordS64_quot(Int64_t,Int64_t); MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) Int64_t WordS64_rem(Int64_t,Int64_t); PRIVATE Real32_t WordS64_rndToReal32(Int64_t); @@ -1047,7 +1048,6 @@ MLTON_CODEGEN_STATIC_INLINE Bool_t WordS8_le(Int8_t,Int8_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordS8_lt(Int8_t,Int8_t); MLTON_CODEGEN_STATIC_INLINE Int8_t WordS8_mul(Int8_t,Int8_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordS8_mulCheckP(Int8_t,Int8_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordS8_negCheckP(Int8_t); MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) Int8_t WordS8_quot(Int8_t,Int8_t); MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) Int8_t WordS8_rem(Int8_t,Int8_t); PRIVATE Real32_t WordS8_rndToReal32(Int8_t); diff --git a/runtime/basis/Word/Word-check.h b/runtime/basis/Word/Word-check.h index 2368219037..581f63a994 100644 --- a/runtime/basis/Word/Word-check.h +++ b/runtime/basis/Word/Word-check.h @@ -1,30 +1,30 @@ -#define add_overflow_b(x, y, size, onOverflow, onSuccess) \ +#define add_overflow_b(x, y, kind, onOverflow, onSuccess) \ do { \ - WordS##size res; \ + Word##kind res; \ if (__builtin_add_overflow(x, y, &res)) { \ onOverflow; \ } \ onSuccess; \ } while (0) -#define sub_overflow_b(x, y, size, onOverflow, onSuccess) \ +#define sub_overflow_b(x, y, kind, onOverflow, onSuccess) \ do { \ - WordS##size res; \ + Word##kind res; \ if (__builtin_sub_overflow(x, y, &res)) { \ onOverflow; \ } \ onSuccess; \ } while (0) -#define mul_overflow_b(x, y, size, onOverflow, onSuccess) \ +#define mul_overflow_b(x, y, kind, onOverflow, onSuccess) \ do { \ - WordS##size res; \ + Word##kind res; \ if (__builtin_mul_overflow(x, y, &res)) { \ onOverflow; \ } \ onSuccess; \ } while (0) -#define neg_overflow_b(x, size, onOverflow, onSuccess) \ +#define neg_overflow_b(x, kind, onOverflow, onSuccess) \ do { \ - Word##size res; \ + Word##kind res; \ if (__builtin_sub_overflow(0, x, &res)) { \ onOverflow; \ } \ @@ -36,26 +36,26 @@ */ #define WordS_addCheckBody(size, x, y, doOverflow, doSuccess) \ - add_overflow_b(x, y, size, doOverflow, doSuccess) + add_overflow_b(x, y, S##size, doOverflow, doSuccess) #define WordS_addCheckBodyCX(size, c, x, doOverflow, doSuccess) \ WordS_addCheckBody(size, c, x, doOverflow, doSuccess) #define WordU_addCheckBody(size, x, y, doOverflow, doSuccess) \ - add_overflow_b(x, y, size, doOverflow, doSuccess) + add_overflow_b(x, y, U##size, doOverflow, doSuccess) #define WordU_addCheckBodyCX(size, c, x, doOverflow, doSuccess) \ WordU_addCheckBody(size, c, x, doOverflow, doSuccess) #define WordS_mulCheckBody(size, x, y, doOverflow, doSuccess) \ - mul_overflow_b(x, y, size, doOverflow, doSuccess) + mul_overflow_b(x, y, S##size, doOverflow, doSuccess) #define WordU_mulCheckBody(size, x, y, doOverflow, doSuccess) \ - mul_overflow_b(x, y, size, doOverflow, doSuccess) + mul_overflow_b(x, y, U##size, doOverflow, doSuccess) #define WordS_negCheckBody(size, x, doOverflow, doSuccess) \ - neg_overflow_b(x, size, doOverflow, doSuccess) + neg_overflow_b(x, S##size, doOverflow, doSuccess) #define WordS_subCheckBody(size, x, y, doOverflow, doSuccess) \ - sub_overflow_b(x, y, size, doOverflow, doSuccess) + sub_overflow_b(x, y, S##size, doOverflow, doSuccess) #define WordS_subCheckBodyCX(size, c, x, doOverflow, doSuccess) \ WordS_subCheckBody(size, c, x, doOverflow, doSuccess) @@ -84,36 +84,36 @@ #define WordS_addCheckP(size) \ MLTON_CODEGEN_STATIC_INLINE \ Bool WordS##size##_addCheckP (WordS##size x, WordS##size y) { \ - add_overflow_b(x, y, size, return TRUE, return FALSE); \ + add_overflow_b(x, y, S##size, return TRUE, return FALSE); \ } #define WordU_addCheckP(size) \ MLTON_CODEGEN_STATIC_INLINE \ Bool WordU##size##_addCheckP (WordU##size x, WordU##size y) { \ - add_overflow_b(x, y, size, return TRUE, return FALSE); \ + add_overflow_b(x, y, U##size, return TRUE, return FALSE); \ } #define WordS_mulCheckP(size) \ MLTON_CODEGEN_STATIC_INLINE \ Bool WordS##size##_mulCheckP (WordS##size x, WordS##size y) { \ - mul_overflow_b(x, y, size, return TRUE, return FALSE); \ + mul_overflow_b(x, y, S##size, return TRUE, return FALSE); \ } #define WordU_mulCheckP(size) \ MLTON_CODEGEN_STATIC_INLINE \ Bool WordU##size##_mulCheckP (WordU##size x, WordU##size y) { \ - mul_overflow_b(x, y, size, return TRUE, return FALSE); \ + mul_overflow_b(x, y, U##size, return TRUE, return FALSE); \ } #define Word_negCheckP(size) \ MLTON_CODEGEN_STATIC_INLINE \ Bool Word##size##_negCheckP (WordS##size x) { \ - neg_overflow_b(x, size, return TRUE, return FALSE); \ + neg_overflow_b(x, S##size, return TRUE, return FALSE); \ } #define WordS_subCheckP(size) \ MLTON_CODEGEN_STATIC_INLINE \ Bool WordS##size##_subCheckP (WordS##size x, WordS##size y) { \ - sub_overflow_b(x, y, size, return TRUE, return FALSE); \ + sub_overflow_b(x, y, S##size, return TRUE, return FALSE); \ } #define all(size) \ diff --git a/runtime/gen/basis-ffi.def b/runtime/gen/basis-ffi.def index 7cb0d47bd1..db591459f5 100644 --- a/runtime/gen/basis-ffi.def +++ b/runtime/gen/basis-ffi.def @@ -990,7 +990,7 @@ WordS16.le = _import MLTON_CODEGEN_STATIC_INLINE : Int16.t * Int16.t -> Bool.t WordS16.lt = _import MLTON_CODEGEN_STATIC_INLINE : Int16.t * Int16.t -> Bool.t WordS16.mul = _import MLTON_CODEGEN_STATIC_INLINE : Int16.t * Int16.t -> Int16.t WordS16.mulCheckP = _import MLTON_CODEGEN_STATIC_INLINE : Int16.t * Int16.t -> Bool.t -WordS16.negCheckP = _import MLTON_CODEGEN_STATIC_INLINE : Int16.t -> Bool.t +Word16.negCheckP = _import MLTON_CODEGEN_STATIC_INLINE : Int16.t -> Bool.t WordS16.quot = _import MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) : Int16.t * Int16.t -> Int16.t WordS16.rem = _import MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) : Int16.t * Int16.t -> Int16.t WordS16.rndToReal32 = _import PRIVATE : Int16.t -> Real32.t @@ -1008,7 +1008,7 @@ WordS32.le = _import MLTON_CODEGEN_STATIC_INLINE : Int32.t * Int32.t -> Bool.t WordS32.lt = _import MLTON_CODEGEN_STATIC_INLINE : Int32.t * Int32.t -> Bool.t WordS32.mul = _import MLTON_CODEGEN_STATIC_INLINE : Int32.t * Int32.t -> Int32.t WordS32.mulCheckP = _import MLTON_CODEGEN_STATIC_INLINE : Int32.t * Int32.t -> Bool.t -WordS32.negCheckP = _import MLTON_CODEGEN_STATIC_INLINE : Int32.t -> Bool.t +Word32.negCheckP = _import MLTON_CODEGEN_STATIC_INLINE : Int32.t -> Bool.t WordS32.quot = _import MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) : Int32.t * Int32.t -> Int32.t WordS32.rem = _import MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) : Int32.t * Int32.t -> Int32.t WordS32.rndToReal32 = _import PRIVATE : Int32.t -> Real32.t @@ -1026,7 +1026,7 @@ WordS64.le = _import MLTON_CODEGEN_STATIC_INLINE : Int64.t * Int64.t -> Bool.t WordS64.lt = _import MLTON_CODEGEN_STATIC_INLINE : Int64.t * Int64.t -> Bool.t WordS64.mul = _import MLTON_CODEGEN_STATIC_INLINE : Int64.t * Int64.t -> Int64.t WordS64.mulCheckP = _import MLTON_CODEGEN_STATIC_INLINE : Int64.t * Int64.t -> Bool.t -WordS64.negCheckP = _import MLTON_CODEGEN_STATIC_INLINE : Int64.t -> Bool.t +Word64.negCheckP = _import MLTON_CODEGEN_STATIC_INLINE : Int64.t -> Bool.t WordS64.quot = _import MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) : Int64.t * Int64.t -> Int64.t WordS64.rem = _import MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) : Int64.t * Int64.t -> Int64.t WordS64.rndToReal32 = _import PRIVATE : Int64.t -> Real32.t @@ -1044,7 +1044,7 @@ WordS8.le = _import MLTON_CODEGEN_STATIC_INLINE : Int8.t * Int8.t -> Bool.t WordS8.lt = _import MLTON_CODEGEN_STATIC_INLINE : Int8.t * Int8.t -> Bool.t WordS8.mul = _import MLTON_CODEGEN_STATIC_INLINE : Int8.t * Int8.t -> Int8.t WordS8.mulCheckP = _import MLTON_CODEGEN_STATIC_INLINE : Int8.t * Int8.t -> Bool.t -WordS8.negCheckP = _import MLTON_CODEGEN_STATIC_INLINE : Int8.t -> Bool.t +Word8.negCheckP = _import MLTON_CODEGEN_STATIC_INLINE : Int8.t -> Bool.t WordS8.quot = _import MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) : Int8.t * Int8.t -> Int8.t WordS8.rem = _import MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) : Int8.t * Int8.t -> Int8.t WordS8.rndToReal32 = _import PRIVATE : Int8.t -> Real32.t diff --git a/runtime/gen/basis-ffi.h b/runtime/gen/basis-ffi.h index 0772b62891..4c7e5af415 100644 --- a/runtime/gen/basis-ffi.h +++ b/runtime/gen/basis-ffi.h @@ -938,6 +938,7 @@ MLTON_CODEGEN_STATIC_INLINE Word16_t Word16_andb(Word16_t,Word16_t); MLTON_CODEGEN_STATIC_INLINE Bool_t Word16_equal(Word16_t,Word16_t); MLTON_CODEGEN_STATIC_INLINE Word16_t Word16_lshift(Word16_t,Word32_t); MLTON_CODEGEN_STATIC_INLINE Word16_t Word16_neg(Word16_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t Word16_negCheckP(Int16_t); MLTON_CODEGEN_STATIC_INLINE Word16_t Word16_notb(Word16_t); MLTON_CODEGEN_STATIC_INLINE Word16_t Word16_orb(Word16_t,Word16_t); MLTON_CODEGEN_STATIC_INLINE Word16_t Word16_rol(Word16_t,Word32_t); @@ -950,6 +951,7 @@ MLTON_CODEGEN_STATIC_INLINE Real32_t Word32_castToReal32(Word32_t); MLTON_CODEGEN_STATIC_INLINE Bool_t Word32_equal(Word32_t,Word32_t); MLTON_CODEGEN_STATIC_INLINE Word32_t Word32_lshift(Word32_t,Word32_t); MLTON_CODEGEN_STATIC_INLINE Word32_t Word32_neg(Word32_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t Word32_negCheckP(Int32_t); MLTON_CODEGEN_STATIC_INLINE Word32_t Word32_notb(Word32_t); MLTON_CODEGEN_STATIC_INLINE Word32_t Word32_orb(Word32_t,Word32_t); MLTON_CODEGEN_STATIC_INLINE Word32_t Word32_rol(Word32_t,Word32_t); @@ -964,6 +966,7 @@ MLTON_CODEGEN_STATIC_INLINE Word64_t Word64_fetch(Ref(Word64_t)); MLTON_CODEGEN_STATIC_INLINE Word64_t Word64_lshift(Word64_t,Word32_t); MLTON_CODEGEN_STATIC_INLINE void Word64_move(Ref(Word64_t),Ref(Word64_t)); MLTON_CODEGEN_STATIC_INLINE Word64_t Word64_neg(Word64_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t Word64_negCheckP(Int64_t); MLTON_CODEGEN_STATIC_INLINE Word64_t Word64_notb(Word64_t); MLTON_CODEGEN_STATIC_INLINE Word64_t Word64_orb(Word64_t,Word64_t); MLTON_CODEGEN_STATIC_INLINE Word64_t Word64_rol(Word64_t,Word32_t); @@ -976,6 +979,7 @@ MLTON_CODEGEN_STATIC_INLINE Word8_t Word8_andb(Word8_t,Word8_t); MLTON_CODEGEN_STATIC_INLINE Bool_t Word8_equal(Word8_t,Word8_t); MLTON_CODEGEN_STATIC_INLINE Word8_t Word8_lshift(Word8_t,Word32_t); MLTON_CODEGEN_STATIC_INLINE Word8_t Word8_neg(Word8_t); +MLTON_CODEGEN_STATIC_INLINE Bool_t Word8_negCheckP(Int8_t); MLTON_CODEGEN_STATIC_INLINE Word8_t Word8_notb(Word8_t); MLTON_CODEGEN_STATIC_INLINE Word8_t Word8_orb(Word8_t,Word8_t); MLTON_CODEGEN_STATIC_INLINE Word8_t Word8_rol(Word8_t,Word32_t); @@ -993,7 +997,6 @@ MLTON_CODEGEN_STATIC_INLINE Bool_t WordS16_le(Int16_t,Int16_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordS16_lt(Int16_t,Int16_t); MLTON_CODEGEN_STATIC_INLINE Int16_t WordS16_mul(Int16_t,Int16_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordS16_mulCheckP(Int16_t,Int16_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordS16_negCheckP(Int16_t); MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) Int16_t WordS16_quot(Int16_t,Int16_t); MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) Int16_t WordS16_rem(Int16_t,Int16_t); PRIVATE Real32_t WordS16_rndToReal32(Int16_t); @@ -1011,7 +1014,6 @@ MLTON_CODEGEN_STATIC_INLINE Bool_t WordS32_le(Int32_t,Int32_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordS32_lt(Int32_t,Int32_t); MLTON_CODEGEN_STATIC_INLINE Int32_t WordS32_mul(Int32_t,Int32_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordS32_mulCheckP(Int32_t,Int32_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordS32_negCheckP(Int32_t); MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) Int32_t WordS32_quot(Int32_t,Int32_t); MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) Int32_t WordS32_rem(Int32_t,Int32_t); PRIVATE Real32_t WordS32_rndToReal32(Int32_t); @@ -1029,7 +1031,6 @@ MLTON_CODEGEN_STATIC_INLINE Bool_t WordS64_le(Int64_t,Int64_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordS64_lt(Int64_t,Int64_t); MLTON_CODEGEN_STATIC_INLINE Int64_t WordS64_mul(Int64_t,Int64_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordS64_mulCheckP(Int64_t,Int64_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordS64_negCheckP(Int64_t); MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) Int64_t WordS64_quot(Int64_t,Int64_t); MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) Int64_t WordS64_rem(Int64_t,Int64_t); PRIVATE Real32_t WordS64_rndToReal32(Int64_t); @@ -1047,7 +1048,6 @@ MLTON_CODEGEN_STATIC_INLINE Bool_t WordS8_le(Int8_t,Int8_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordS8_lt(Int8_t,Int8_t); MLTON_CODEGEN_STATIC_INLINE Int8_t WordS8_mul(Int8_t,Int8_t); MLTON_CODEGEN_STATIC_INLINE Bool_t WordS8_mulCheckP(Int8_t,Int8_t); -MLTON_CODEGEN_STATIC_INLINE Bool_t WordS8_negCheckP(Int8_t); MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) Int8_t WordS8_quot(Int8_t,Int8_t); MLTON_CODEGEN_WORDSQUOTREM(MLTON_CODEGEN_STATIC_INLINE) Int8_t WordS8_rem(Int8_t,Int8_t); PRIVATE Real32_t WordS8_rndToReal32(Int8_t); diff --git a/runtime/gen/basis-ffi.sml b/runtime/gen/basis-ffi.sml index cd74bcd57e..47e017bfe0 100644 --- a/runtime/gen/basis-ffi.sml +++ b/runtime/gen/basis-ffi.sml @@ -1148,6 +1148,7 @@ val andb = _import "Word16_andb" private : Word16.t * Word16.t -> Word16.t; val equal = _import "Word16_equal" private : Word16.t * Word16.t -> Bool.t; val lshift = _import "Word16_lshift" private : Word16.t * Word32.t -> Word16.t; val neg = _import "Word16_neg" private : Word16.t -> Word16.t; +val negCheckP = _import "Word16_negCheckP" private : Int16.t -> Bool.t; val notb = _import "Word16_notb" private : Word16.t -> Word16.t; val orb = _import "Word16_orb" private : Word16.t * Word16.t -> Word16.t; val rol = _import "Word16_rol" private : Word16.t * Word32.t -> Word16.t; @@ -1164,6 +1165,7 @@ val castToReal32 = _import "Word32_castToReal32" private : Word32.t -> Real32.t; val equal = _import "Word32_equal" private : Word32.t * Word32.t -> Bool.t; val lshift = _import "Word32_lshift" private : Word32.t * Word32.t -> Word32.t; val neg = _import "Word32_neg" private : Word32.t -> Word32.t; +val negCheckP = _import "Word32_negCheckP" private : Int32.t -> Bool.t; val notb = _import "Word32_notb" private : Word32.t -> Word32.t; val orb = _import "Word32_orb" private : Word32.t * Word32.t -> Word32.t; val rol = _import "Word32_rol" private : Word32.t * Word32.t -> Word32.t; @@ -1182,6 +1184,7 @@ val fetch = _import "Word64_fetch" private : (Word64.t) ref -> Word64.t; val lshift = _import "Word64_lshift" private : Word64.t * Word32.t -> Word64.t; val move = _import "Word64_move" private : (Word64.t) ref * (Word64.t) ref -> unit; val neg = _import "Word64_neg" private : Word64.t -> Word64.t; +val negCheckP = _import "Word64_negCheckP" private : Int64.t -> Bool.t; val notb = _import "Word64_notb" private : Word64.t -> Word64.t; val orb = _import "Word64_orb" private : Word64.t * Word64.t -> Word64.t; val rol = _import "Word64_rol" private : Word64.t * Word32.t -> Word64.t; @@ -1198,6 +1201,7 @@ val andb = _import "Word8_andb" private : Word8.t * Word8.t -> Word8.t; val equal = _import "Word8_equal" private : Word8.t * Word8.t -> Bool.t; val lshift = _import "Word8_lshift" private : Word8.t * Word32.t -> Word8.t; val neg = _import "Word8_neg" private : Word8.t -> Word8.t; +val negCheckP = _import "Word8_negCheckP" private : Int8.t -> Bool.t; val notb = _import "Word8_notb" private : Word8.t -> Word8.t; val orb = _import "Word8_orb" private : Word8.t * Word8.t -> Word8.t; val rol = _import "Word8_rol" private : Word8.t * Word32.t -> Word8.t; @@ -1218,7 +1222,6 @@ val le = _import "WordS16_le" private : Int16.t * Int16.t -> Bool.t; val lt = _import "WordS16_lt" private : Int16.t * Int16.t -> Bool.t; val mul = _import "WordS16_mul" private : Int16.t * Int16.t -> Int16.t; val mulCheckP = _import "WordS16_mulCheckP" private : Int16.t * Int16.t -> Bool.t; -val negCheckP = _import "WordS16_negCheckP" private : Int16.t -> Bool.t; val quot = _import "WordS16_quot" private : Int16.t * Int16.t -> Int16.t; val rem = _import "WordS16_rem" private : Int16.t * Int16.t -> Int16.t; val rndToReal32 = _import "WordS16_rndToReal32" private : Int16.t -> Real32.t; @@ -1239,7 +1242,6 @@ val le = _import "WordS32_le" private : Int32.t * Int32.t -> Bool.t; val lt = _import "WordS32_lt" private : Int32.t * Int32.t -> Bool.t; val mul = _import "WordS32_mul" private : Int32.t * Int32.t -> Int32.t; val mulCheckP = _import "WordS32_mulCheckP" private : Int32.t * Int32.t -> Bool.t; -val negCheckP = _import "WordS32_negCheckP" private : Int32.t -> Bool.t; val quot = _import "WordS32_quot" private : Int32.t * Int32.t -> Int32.t; val rem = _import "WordS32_rem" private : Int32.t * Int32.t -> Int32.t; val rndToReal32 = _import "WordS32_rndToReal32" private : Int32.t -> Real32.t; @@ -1260,7 +1262,6 @@ val le = _import "WordS64_le" private : Int64.t * Int64.t -> Bool.t; val lt = _import "WordS64_lt" private : Int64.t * Int64.t -> Bool.t; val mul = _import "WordS64_mul" private : Int64.t * Int64.t -> Int64.t; val mulCheckP = _import "WordS64_mulCheckP" private : Int64.t * Int64.t -> Bool.t; -val negCheckP = _import "WordS64_negCheckP" private : Int64.t -> Bool.t; val quot = _import "WordS64_quot" private : Int64.t * Int64.t -> Int64.t; val rem = _import "WordS64_rem" private : Int64.t * Int64.t -> Int64.t; val rndToReal32 = _import "WordS64_rndToReal32" private : Int64.t -> Real32.t; @@ -1281,7 +1282,6 @@ val le = _import "WordS8_le" private : Int8.t * Int8.t -> Bool.t; val lt = _import "WordS8_lt" private : Int8.t * Int8.t -> Bool.t; val mul = _import "WordS8_mul" private : Int8.t * Int8.t -> Int8.t; val mulCheckP = _import "WordS8_mulCheckP" private : Int8.t * Int8.t -> Bool.t; -val negCheckP = _import "WordS8_negCheckP" private : Int8.t -> Bool.t; val quot = _import "WordS8_quot" private : Int8.t * Int8.t -> Int8.t; val rem = _import "WordS8_rem" private : Int8.t * Int8.t -> Int8.t; val rndToReal32 = _import "WordS8_rndToReal32" private : Int8.t -> Real32.t; From bdb93353c376493107a4e98dfb50f5a193899813 Mon Sep 17 00:00:00 2001 From: Daman Morris Date: Mon, 13 Aug 2018 14:54:04 -0400 Subject: [PATCH 34/57] Use GCC5 for Travis CI --- .travis.yml | 44 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index fe1494196f..15b6d97b30 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,21 +5,49 @@ sudo: required matrix: include: - os: linux - env: CC=gcc MLTON_COMPILE_ARGS="-codegen amd64" REGRESSION=true + dist: trusty + addons: + apt: + update: true + sources: + - ubuntu-toolchain-r-test + packages: + - gcc-5 + - mlton + env: CC=gcc-5 MLTON_COMPILE_ARGS="-codegen amd64" REGRESSION=true - os: linux - env: CC=gcc MLTON_COMPILE_ARGS="-codegen c" REGRESSION=false + dist: trusty + addons: + apt: + update: true + sources: + - ubuntu-toolchain-r-test + packages: + - gcc-5 + - mlton + env: CC=gcc-5 MLTON_COMPILE_ARGS="-codegen c" REGRESSION=false - os: linux - env: CC=clang MLTON_COMPILE_ARGS="-codegen c" REGRESSION=false + dist: trusty + addons: + apt: + update: true + packages: + - mlton + env: CC=clang MLTON_COMPILE_ARGS="-codegen c" REGRESSION=false - os: linux - env: CC=clang MLTON_COMPILE_ARGS="-codegen llvm" REGRESSION=false + dist: trusty + addons: + apt: + update: true + packages: + - mlton + env: CC=clang MLTON_COMPILE_ARGS="-codegen llvm" REGRESSION=false - os: osx - env: CC=clang MLTON_COMPILE_ARGS="-codegen amd64" REGRESSION=false + env: CC=clang MLTON_COMPILE_ARGS="-codegen amd64" REGRESSION=false - os: osx - env: CC=clang MLTON_COMPILE_ARGS="-codegen c" REGRESSION=false + env: CC=clang MLTON_COMPILE_ARGS="-codegen c" REGRESSION=false install: - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get -qq update; fi - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install -qq mlton; fi - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update; fi - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install mlton; fi From 45461741312445e04e9eecc0d79b1f6467c176de Mon Sep 17 00:00:00 2001 From: Daman Morris Date: Tue, 14 Aug 2018 08:59:03 -0400 Subject: [PATCH 35/57] Un-ignore vim configuration files --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 34f9885d88..0ba45dd349 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ /build/ /install/ -.nvimrc From a410df47cd0aee09ba5261878616e52ea874b343 Mon Sep 17 00:00:00 2001 From: Matthew Fluet Date: Wed, 15 Aug 2018 11:11:33 -0400 Subject: [PATCH 36/57] Add `int-mul-pow2` regression test demonstrating bug This new regression test demonstrates a bug with the native codegens and `MLton.newOverflow true`. Essentially, multiplications by a constant (positive or negative) power of 2 can either erroneously `raise Overflow` or fail to `raise Overflow`. The issue is that the `elimMDPow2` peephole optimization tries to replace multiplications and divisions by powers of 2 by appropriate shifts, adds, and negations. Unfortunately, the conditions for application of the peephole optimization are insufficient for `MLton.newOverflow true`. The implicit assumption in the `elimMDPow2` rewriter is that only signed multiplication may check for overflow and that if a signed multiplication is checked for overflow, then it does so by an immediately following iff-O transfer. Under these assumptions, there are special cases for multiplication by 1, -1, 2, and -2: imul 1, dst => jmp L_nooverflow jo L_overflow jmp L_nooverflow imul -1, dst => neg dst jo L_overflow jo L_overflow jmp L_nooverflow jmp L_nooverflow imul 2, dst => add dst, dst jo L_overflow jo L_overflow jmp L_nooverflow jmp L_nooverflow imul -2, dst => add dst, dst jo L_overflow neg dst jmp L_nooverflow jo L_overflow jmp L_nooverflow Note that multiplication by larger powers of 2 are not rewritten, as the resulting shift and negation will not set the overflow flag in an equivalent manner. If a signed multiplication is not immediately followed by an iff-condition transfer, then multiplication by 1, -1, 2, -2, 2^i (i > 1), and -2^i (i > 1) are rewritten: imul 1, dst => nop imul -1, dst => neg dst1 imul 2, dst => add dst, dst imul -2, dst => add dst, dst neg dst imul 2^i, dst => shl i, dst imul -2^i, dst => shl i, dst neg dst However, with `MLton.newOverflow true`, then a signed multiplication may be followed by a `seto fdst` instruction (followed by a `test fdst, fdst`, followed by a iff-NZ transfer --- this sequence will subsequently be optimized to an iff-O transfer by the `conditionalJump` peephole optimization, but the `conditionalJump` peephole optimization runs later, as part of `peepholeLivenessBlock`). When `imul 1, dst`, `imul 2^i, dst` (i > 1), and `imul -2^i, dst` (i > 1) are rewritten as above, then the subsequent `seto fdst` instruction will not be equivalent. The appropriate fix is unclear. One option is to strengthen the checks in the `elimMDPow2` peephole optimization to disable the rewrite if a subsequent `setcc` instruction would observe the flags. Another option is to delay the `elimMDPow2` peephole optimization until after the `elimALRedundant` peephole optimization has executed. As an aside, note that neither the C codegen nor the LLVM codegen have a similar bug, although their optimizers almost certainly optimize multiplications by powers of 2. This simply adds to the argument that the native codegens should be retired; resources may be better spent improving the C and LLVM codegens than maintaining the native codegens. --- regression/int-mul-pow2.ok | 3440 +++++++++++++++++++++++++++++++++++ regression/int-mul-pow2.sml | 187 ++ 2 files changed, 3627 insertions(+) create mode 100644 regression/int-mul-pow2.ok create mode 100644 regression/int-mul-pow2.sml diff --git a/regression/int-mul-pow2.ok b/regression/int-mul-pow2.ok new file mode 100644 index 0000000000..31e4890b66 --- /dev/null +++ b/regression/int-mul-pow2.ok @@ -0,0 +1,3440 @@ +~32 * 64 = Overflow +~32 * 32 = Overflow +~32 * 16 = Overflow +~32 * 8 = Overflow +~32 * 4 = ~128 +~31 * 64 = Overflow +~31 * 32 = Overflow +~31 * 16 = Overflow +~31 * 8 = Overflow +~31 * 4 = ~124 +~30 * 64 = Overflow +~30 * 32 = Overflow +~30 * 16 = Overflow +~30 * 8 = Overflow +~30 * 4 = ~120 +~29 * 64 = Overflow +~29 * 32 = Overflow +~29 * 16 = Overflow +~29 * 8 = Overflow +~29 * 4 = ~116 +~28 * 64 = Overflow +~28 * 32 = Overflow +~28 * 16 = Overflow +~28 * 8 = Overflow +~28 * 4 = ~112 +~27 * 64 = Overflow +~27 * 32 = Overflow +~27 * 16 = Overflow +~27 * 8 = Overflow +~27 * 4 = ~108 +~26 * 64 = Overflow +~26 * 32 = Overflow +~26 * 16 = Overflow +~26 * 8 = Overflow +~26 * 4 = ~104 +~25 * 64 = Overflow +~25 * 32 = Overflow +~25 * 16 = Overflow +~25 * 8 = Overflow +~25 * 4 = ~100 +~24 * 64 = Overflow +~24 * 32 = Overflow +~24 * 16 = Overflow +~24 * 8 = Overflow +~24 * 4 = ~96 +~23 * 64 = Overflow +~23 * 32 = Overflow +~23 * 16 = Overflow +~23 * 8 = Overflow +~23 * 4 = ~92 +~22 * 64 = Overflow +~22 * 32 = Overflow +~22 * 16 = Overflow +~22 * 8 = Overflow +~22 * 4 = ~88 +~21 * 64 = Overflow +~21 * 32 = Overflow +~21 * 16 = Overflow +~21 * 8 = Overflow +~21 * 4 = ~84 +~20 * 64 = Overflow +~20 * 32 = Overflow +~20 * 16 = Overflow +~20 * 8 = Overflow +~20 * 4 = ~80 +~19 * 64 = Overflow +~19 * 32 = Overflow +~19 * 16 = Overflow +~19 * 8 = Overflow +~19 * 4 = ~76 +~18 * 64 = Overflow +~18 * 32 = Overflow +~18 * 16 = Overflow +~18 * 8 = Overflow +~18 * 4 = ~72 +~17 * 64 = Overflow +~17 * 32 = Overflow +~17 * 16 = Overflow +~17 * 8 = Overflow +~17 * 4 = ~68 +~16 * 64 = Overflow +~16 * 32 = Overflow +~16 * 16 = Overflow +~16 * 8 = ~128 +~16 * 4 = ~64 +~15 * 64 = Overflow +~15 * 32 = Overflow +~15 * 16 = Overflow +~15 * 8 = ~120 +~15 * 4 = ~60 +~14 * 64 = Overflow +~14 * 32 = Overflow +~14 * 16 = Overflow +~14 * 8 = ~112 +~14 * 4 = ~56 +~13 * 64 = Overflow +~13 * 32 = Overflow +~13 * 16 = Overflow +~13 * 8 = ~104 +~13 * 4 = ~52 +~12 * 64 = Overflow +~12 * 32 = Overflow +~12 * 16 = Overflow +~12 * 8 = ~96 +~12 * 4 = ~48 +~11 * 64 = Overflow +~11 * 32 = Overflow +~11 * 16 = Overflow +~11 * 8 = ~88 +~11 * 4 = ~44 +~10 * 64 = Overflow +~10 * 32 = Overflow +~10 * 16 = Overflow +~10 * 8 = ~80 +~10 * 4 = ~40 +~9 * 64 = Overflow +~9 * 32 = Overflow +~9 * 16 = Overflow +~9 * 8 = ~72 +~9 * 4 = ~36 +~8 * 64 = Overflow +~8 * 32 = Overflow +~8 * 16 = ~128 +~8 * 8 = ~64 +~8 * 4 = ~32 +~7 * 64 = Overflow +~7 * 32 = Overflow +~7 * 16 = ~112 +~7 * 8 = ~56 +~7 * 4 = ~28 +~6 * 64 = Overflow +~6 * 32 = Overflow +~6 * 16 = ~96 +~6 * 8 = ~48 +~6 * 4 = ~24 +~5 * 64 = Overflow +~5 * 32 = Overflow +~5 * 16 = ~80 +~5 * 8 = ~40 +~5 * 4 = ~20 +~4 * 64 = Overflow +~4 * 32 = ~128 +~4 * 16 = ~64 +~4 * 8 = ~32 +~4 * 4 = ~16 +~3 * 64 = Overflow +~3 * 32 = ~96 +~3 * 16 = ~48 +~3 * 8 = ~24 +~3 * 4 = ~12 +~2 * 64 = ~128 +~2 * 32 = ~64 +~2 * 16 = ~32 +~2 * 8 = ~16 +~2 * 4 = ~8 +~1 * 64 = ~64 +~1 * 32 = ~32 +~1 * 16 = ~16 +~1 * 8 = ~8 +~1 * 4 = ~4 +0 * 64 = 0 +0 * 32 = 0 +0 * 16 = 0 +0 * 8 = 0 +0 * 4 = 0 +1 * 64 = 64 +1 * 32 = 32 +1 * 16 = 16 +1 * 8 = 8 +1 * 4 = 4 +2 * 64 = Overflow +2 * 32 = 64 +2 * 16 = 32 +2 * 8 = 16 +2 * 4 = 8 +3 * 64 = Overflow +3 * 32 = 96 +3 * 16 = 48 +3 * 8 = 24 +3 * 4 = 12 +4 * 64 = Overflow +4 * 32 = Overflow +4 * 16 = 64 +4 * 8 = 32 +4 * 4 = 16 +5 * 64 = Overflow +5 * 32 = Overflow +5 * 16 = 80 +5 * 8 = 40 +5 * 4 = 20 +6 * 64 = Overflow +6 * 32 = Overflow +6 * 16 = 96 +6 * 8 = 48 +6 * 4 = 24 +7 * 64 = Overflow +7 * 32 = Overflow +7 * 16 = 112 +7 * 8 = 56 +7 * 4 = 28 +8 * 64 = Overflow +8 * 32 = Overflow +8 * 16 = Overflow +8 * 8 = 64 +8 * 4 = 32 +9 * 64 = Overflow +9 * 32 = Overflow +9 * 16 = Overflow +9 * 8 = 72 +9 * 4 = 36 +10 * 64 = Overflow +10 * 32 = Overflow +10 * 16 = Overflow +10 * 8 = 80 +10 * 4 = 40 +11 * 64 = Overflow +11 * 32 = Overflow +11 * 16 = Overflow +11 * 8 = 88 +11 * 4 = 44 +12 * 64 = Overflow +12 * 32 = Overflow +12 * 16 = Overflow +12 * 8 = 96 +12 * 4 = 48 +13 * 64 = Overflow +13 * 32 = Overflow +13 * 16 = Overflow +13 * 8 = 104 +13 * 4 = 52 +14 * 64 = Overflow +14 * 32 = Overflow +14 * 16 = Overflow +14 * 8 = 112 +14 * 4 = 56 +15 * 64 = Overflow +15 * 32 = Overflow +15 * 16 = Overflow +15 * 8 = 120 +15 * 4 = 60 +16 * 64 = Overflow +16 * 32 = Overflow +16 * 16 = Overflow +16 * 8 = Overflow +16 * 4 = 64 +17 * 64 = Overflow +17 * 32 = Overflow +17 * 16 = Overflow +17 * 8 = Overflow +17 * 4 = 68 +18 * 64 = Overflow +18 * 32 = Overflow +18 * 16 = Overflow +18 * 8 = Overflow +18 * 4 = 72 +19 * 64 = Overflow +19 * 32 = Overflow +19 * 16 = Overflow +19 * 8 = Overflow +19 * 4 = 76 +20 * 64 = Overflow +20 * 32 = Overflow +20 * 16 = Overflow +20 * 8 = Overflow +20 * 4 = 80 +21 * 64 = Overflow +21 * 32 = Overflow +21 * 16 = Overflow +21 * 8 = Overflow +21 * 4 = 84 +22 * 64 = Overflow +22 * 32 = Overflow +22 * 16 = Overflow +22 * 8 = Overflow +22 * 4 = 88 +23 * 64 = Overflow +23 * 32 = Overflow +23 * 16 = Overflow +23 * 8 = Overflow +23 * 4 = 92 +24 * 64 = Overflow +24 * 32 = Overflow +24 * 16 = Overflow +24 * 8 = Overflow +24 * 4 = 96 +25 * 64 = Overflow +25 * 32 = Overflow +25 * 16 = Overflow +25 * 8 = Overflow +25 * 4 = 100 +26 * 64 = Overflow +26 * 32 = Overflow +26 * 16 = Overflow +26 * 8 = Overflow +26 * 4 = 104 +27 * 64 = Overflow +27 * 32 = Overflow +27 * 16 = Overflow +27 * 8 = Overflow +27 * 4 = 108 +28 * 64 = Overflow +28 * 32 = Overflow +28 * 16 = Overflow +28 * 8 = Overflow +28 * 4 = 112 +29 * 64 = Overflow +29 * 32 = Overflow +29 * 16 = Overflow +29 * 8 = Overflow +29 * 4 = 116 +30 * 64 = Overflow +30 * 32 = Overflow +30 * 16 = Overflow +30 * 8 = Overflow +30 * 4 = 120 +31 * 64 = Overflow +31 * 32 = Overflow +31 * 16 = Overflow +31 * 8 = Overflow +31 * 4 = 124 +32 * 64 = Overflow +32 * 32 = Overflow +32 * 16 = Overflow +32 * 8 = Overflow +32 * 4 = Overflow +~32 * ~128 = Overflow +~32 * ~64 = Overflow +~32 * ~32 = Overflow +~32 * ~16 = Overflow +~32 * ~8 = Overflow +~31 * ~128 = Overflow +~31 * ~64 = Overflow +~31 * ~32 = Overflow +~31 * ~16 = Overflow +~31 * ~8 = Overflow +~30 * ~128 = Overflow +~30 * ~64 = Overflow +~30 * ~32 = Overflow +~30 * ~16 = Overflow +~30 * ~8 = Overflow +~29 * ~128 = Overflow +~29 * ~64 = Overflow +~29 * ~32 = Overflow +~29 * ~16 = Overflow +~29 * ~8 = Overflow +~28 * ~128 = Overflow +~28 * ~64 = Overflow +~28 * ~32 = Overflow +~28 * ~16 = Overflow +~28 * ~8 = Overflow +~27 * ~128 = Overflow +~27 * ~64 = Overflow +~27 * ~32 = Overflow +~27 * ~16 = Overflow +~27 * ~8 = Overflow +~26 * ~128 = Overflow +~26 * ~64 = Overflow +~26 * ~32 = Overflow +~26 * ~16 = Overflow +~26 * ~8 = Overflow +~25 * ~128 = Overflow +~25 * ~64 = Overflow +~25 * ~32 = Overflow +~25 * ~16 = Overflow +~25 * ~8 = Overflow +~24 * ~128 = Overflow +~24 * ~64 = Overflow +~24 * ~32 = Overflow +~24 * ~16 = Overflow +~24 * ~8 = Overflow +~23 * ~128 = Overflow +~23 * ~64 = Overflow +~23 * ~32 = Overflow +~23 * ~16 = Overflow +~23 * ~8 = Overflow +~22 * ~128 = Overflow +~22 * ~64 = Overflow +~22 * ~32 = Overflow +~22 * ~16 = Overflow +~22 * ~8 = Overflow +~21 * ~128 = Overflow +~21 * ~64 = Overflow +~21 * ~32 = Overflow +~21 * ~16 = Overflow +~21 * ~8 = Overflow +~20 * ~128 = Overflow +~20 * ~64 = Overflow +~20 * ~32 = Overflow +~20 * ~16 = Overflow +~20 * ~8 = Overflow +~19 * ~128 = Overflow +~19 * ~64 = Overflow +~19 * ~32 = Overflow +~19 * ~16 = Overflow +~19 * ~8 = Overflow +~18 * ~128 = Overflow +~18 * ~64 = Overflow +~18 * ~32 = Overflow +~18 * ~16 = Overflow +~18 * ~8 = Overflow +~17 * ~128 = Overflow +~17 * ~64 = Overflow +~17 * ~32 = Overflow +~17 * ~16 = Overflow +~17 * ~8 = Overflow +~16 * ~128 = Overflow +~16 * ~64 = Overflow +~16 * ~32 = Overflow +~16 * ~16 = Overflow +~16 * ~8 = Overflow +~15 * ~128 = Overflow +~15 * ~64 = Overflow +~15 * ~32 = Overflow +~15 * ~16 = Overflow +~15 * ~8 = 120 +~14 * ~128 = Overflow +~14 * ~64 = Overflow +~14 * ~32 = Overflow +~14 * ~16 = Overflow +~14 * ~8 = 112 +~13 * ~128 = Overflow +~13 * ~64 = Overflow +~13 * ~32 = Overflow +~13 * ~16 = Overflow +~13 * ~8 = 104 +~12 * ~128 = Overflow +~12 * ~64 = Overflow +~12 * ~32 = Overflow +~12 * ~16 = Overflow +~12 * ~8 = 96 +~11 * ~128 = Overflow +~11 * ~64 = Overflow +~11 * ~32 = Overflow +~11 * ~16 = Overflow +~11 * ~8 = 88 +~10 * ~128 = Overflow +~10 * ~64 = Overflow +~10 * ~32 = Overflow +~10 * ~16 = Overflow +~10 * ~8 = 80 +~9 * ~128 = Overflow +~9 * ~64 = Overflow +~9 * ~32 = Overflow +~9 * ~16 = Overflow +~9 * ~8 = 72 +~8 * ~128 = Overflow +~8 * ~64 = Overflow +~8 * ~32 = Overflow +~8 * ~16 = Overflow +~8 * ~8 = 64 +~7 * ~128 = Overflow +~7 * ~64 = Overflow +~7 * ~32 = Overflow +~7 * ~16 = 112 +~7 * ~8 = 56 +~6 * ~128 = Overflow +~6 * ~64 = Overflow +~6 * ~32 = Overflow +~6 * ~16 = 96 +~6 * ~8 = 48 +~5 * ~128 = Overflow +~5 * ~64 = Overflow +~5 * ~32 = Overflow +~5 * ~16 = 80 +~5 * ~8 = 40 +~4 * ~128 = Overflow +~4 * ~64 = Overflow +~4 * ~32 = Overflow +~4 * ~16 = 64 +~4 * ~8 = 32 +~3 * ~128 = Overflow +~3 * ~64 = Overflow +~3 * ~32 = 96 +~3 * ~16 = 48 +~3 * ~8 = 24 +~2 * ~128 = Overflow +~2 * ~64 = Overflow +~2 * ~32 = 64 +~2 * ~16 = 32 +~2 * ~8 = 16 +~1 * ~128 = Overflow +~1 * ~64 = 64 +~1 * ~32 = 32 +~1 * ~16 = 16 +~1 * ~8 = 8 +0 * ~128 = 0 +0 * ~64 = 0 +0 * ~32 = 0 +0 * ~16 = 0 +0 * ~8 = 0 +1 * ~128 = ~128 +1 * ~64 = ~64 +1 * ~32 = ~32 +1 * ~16 = ~16 +1 * ~8 = ~8 +2 * ~128 = Overflow +2 * ~64 = ~128 +2 * ~32 = ~64 +2 * ~16 = ~32 +2 * ~8 = ~16 +3 * ~128 = Overflow +3 * ~64 = Overflow +3 * ~32 = ~96 +3 * ~16 = ~48 +3 * ~8 = ~24 +4 * ~128 = Overflow +4 * ~64 = Overflow +4 * ~32 = ~128 +4 * ~16 = ~64 +4 * ~8 = ~32 +5 * ~128 = Overflow +5 * ~64 = Overflow +5 * ~32 = Overflow +5 * ~16 = ~80 +5 * ~8 = ~40 +6 * ~128 = Overflow +6 * ~64 = Overflow +6 * ~32 = Overflow +6 * ~16 = ~96 +6 * ~8 = ~48 +7 * ~128 = Overflow +7 * ~64 = Overflow +7 * ~32 = Overflow +7 * ~16 = ~112 +7 * ~8 = ~56 +8 * ~128 = Overflow +8 * ~64 = Overflow +8 * ~32 = Overflow +8 * ~16 = ~128 +8 * ~8 = ~64 +9 * ~128 = Overflow +9 * ~64 = Overflow +9 * ~32 = Overflow +9 * ~16 = Overflow +9 * ~8 = ~72 +10 * ~128 = Overflow +10 * ~64 = Overflow +10 * ~32 = Overflow +10 * ~16 = Overflow +10 * ~8 = ~80 +11 * ~128 = Overflow +11 * ~64 = Overflow +11 * ~32 = Overflow +11 * ~16 = Overflow +11 * ~8 = ~88 +12 * ~128 = Overflow +12 * ~64 = Overflow +12 * ~32 = Overflow +12 * ~16 = Overflow +12 * ~8 = ~96 +13 * ~128 = Overflow +13 * ~64 = Overflow +13 * ~32 = Overflow +13 * ~16 = Overflow +13 * ~8 = ~104 +14 * ~128 = Overflow +14 * ~64 = Overflow +14 * ~32 = Overflow +14 * ~16 = Overflow +14 * ~8 = ~112 +15 * ~128 = Overflow +15 * ~64 = Overflow +15 * ~32 = Overflow +15 * ~16 = Overflow +15 * ~8 = ~120 +16 * ~128 = Overflow +16 * ~64 = Overflow +16 * ~32 = Overflow +16 * ~16 = Overflow +16 * ~8 = ~128 +17 * ~128 = Overflow +17 * ~64 = Overflow +17 * ~32 = Overflow +17 * ~16 = Overflow +17 * ~8 = Overflow +18 * ~128 = Overflow +18 * ~64 = Overflow +18 * ~32 = Overflow +18 * ~16 = Overflow +18 * ~8 = Overflow +19 * ~128 = Overflow +19 * ~64 = Overflow +19 * ~32 = Overflow +19 * ~16 = Overflow +19 * ~8 = Overflow +20 * ~128 = Overflow +20 * ~64 = Overflow +20 * ~32 = Overflow +20 * ~16 = Overflow +20 * ~8 = Overflow +21 * ~128 = Overflow +21 * ~64 = Overflow +21 * ~32 = Overflow +21 * ~16 = Overflow +21 * ~8 = Overflow +22 * ~128 = Overflow +22 * ~64 = Overflow +22 * ~32 = Overflow +22 * ~16 = Overflow +22 * ~8 = Overflow +23 * ~128 = Overflow +23 * ~64 = Overflow +23 * ~32 = Overflow +23 * ~16 = Overflow +23 * ~8 = Overflow +24 * ~128 = Overflow +24 * ~64 = Overflow +24 * ~32 = Overflow +24 * ~16 = Overflow +24 * ~8 = Overflow +25 * ~128 = Overflow +25 * ~64 = Overflow +25 * ~32 = Overflow +25 * ~16 = Overflow +25 * ~8 = Overflow +26 * ~128 = Overflow +26 * ~64 = Overflow +26 * ~32 = Overflow +26 * ~16 = Overflow +26 * ~8 = Overflow +27 * ~128 = Overflow +27 * ~64 = Overflow +27 * ~32 = Overflow +27 * ~16 = Overflow +27 * ~8 = Overflow +28 * ~128 = Overflow +28 * ~64 = Overflow +28 * ~32 = Overflow +28 * ~16 = Overflow +28 * ~8 = Overflow +29 * ~128 = Overflow +29 * ~64 = Overflow +29 * ~32 = Overflow +29 * ~16 = Overflow +29 * ~8 = Overflow +30 * ~128 = Overflow +30 * ~64 = Overflow +30 * ~32 = Overflow +30 * ~16 = Overflow +30 * ~8 = Overflow +31 * ~128 = Overflow +31 * ~64 = Overflow +31 * ~32 = Overflow +31 * ~16 = Overflow +31 * ~8 = Overflow +32 * ~128 = Overflow +32 * ~64 = Overflow +32 * ~32 = Overflow +32 * ~16 = Overflow +32 * ~8 = Overflow +~128 * 1 = ~128 +~128 * 2 = Overflow +~128 * 4 = Overflow +~128 * 8 = Overflow +~128 * 16 = Overflow +~64 * 1 = ~64 +~64 * 2 = ~128 +~64 * 4 = Overflow +~64 * 8 = Overflow +~64 * 16 = Overflow +~32 * 1 = ~32 +~32 * 2 = ~64 +~32 * 4 = ~128 +~32 * 8 = Overflow +~32 * 16 = Overflow +~16 * 1 = ~16 +~16 * 2 = ~32 +~16 * 4 = ~64 +~16 * 8 = ~128 +~16 * 16 = Overflow +~8 * 1 = ~8 +~8 * 2 = ~16 +~8 * 4 = ~32 +~8 * 8 = ~64 +~8 * 16 = ~128 +~4 * 1 = ~4 +~4 * 2 = ~8 +~4 * 4 = ~16 +~4 * 8 = ~32 +~4 * 16 = ~64 +~4 * 1 = ~4 +~4 * 2 = ~8 +~4 * 4 = ~16 +~4 * 8 = ~32 +~4 * 16 = ~64 +~3 * 1 = ~3 +~3 * 2 = ~6 +~3 * 4 = ~12 +~3 * 8 = ~24 +~3 * 16 = ~48 +~2 * 1 = ~2 +~2 * 2 = ~4 +~2 * 4 = ~8 +~2 * 8 = ~16 +~2 * 16 = ~32 +~1 * 1 = ~1 +~1 * 2 = ~2 +~1 * 4 = ~4 +~1 * 8 = ~8 +~1 * 16 = ~16 +0 * 1 = 0 +0 * 2 = 0 +0 * 4 = 0 +0 * 8 = 0 +0 * 16 = 0 +1 * 1 = 1 +1 * 2 = 2 +1 * 4 = 4 +1 * 8 = 8 +1 * 16 = 16 +2 * 1 = 2 +2 * 2 = 4 +2 * 4 = 8 +2 * 8 = 16 +2 * 16 = 32 +3 * 1 = 3 +3 * 2 = 6 +3 * 4 = 12 +3 * 8 = 24 +3 * 16 = 48 +4 * 1 = 4 +4 * 2 = 8 +4 * 4 = 16 +4 * 8 = 32 +4 * 16 = 64 +2 * 1 = 2 +2 * 2 = 4 +2 * 4 = 8 +2 * 8 = 16 +2 * 16 = 32 +4 * 1 = 4 +4 * 2 = 8 +4 * 4 = 16 +4 * 8 = 32 +4 * 16 = 64 +8 * 1 = 8 +8 * 2 = 16 +8 * 4 = 32 +8 * 8 = 64 +8 * 16 = Overflow +16 * 1 = 16 +16 * 2 = 32 +16 * 4 = 64 +16 * 8 = Overflow +16 * 16 = Overflow +32 * 1 = 32 +32 * 2 = 64 +32 * 4 = Overflow +32 * 8 = Overflow +32 * 16 = Overflow +64 * 1 = 64 +64 * 2 = Overflow +64 * 4 = Overflow +64 * 8 = Overflow +64 * 16 = Overflow +~128 * ~1 = Overflow +~128 * ~2 = Overflow +~128 * ~4 = Overflow +~128 * ~8 = Overflow +~128 * ~16 = Overflow +~64 * ~1 = 64 +~64 * ~2 = Overflow +~64 * ~4 = Overflow +~64 * ~8 = Overflow +~64 * ~16 = Overflow +~32 * ~1 = 32 +~32 * ~2 = 64 +~32 * ~4 = Overflow +~32 * ~8 = Overflow +~32 * ~16 = Overflow +~16 * ~1 = 16 +~16 * ~2 = 32 +~16 * ~4 = 64 +~16 * ~8 = Overflow +~16 * ~16 = Overflow +~8 * ~1 = 8 +~8 * ~2 = 16 +~8 * ~4 = 32 +~8 * ~8 = 64 +~8 * ~16 = Overflow +~4 * ~1 = 4 +~4 * ~2 = 8 +~4 * ~4 = 16 +~4 * ~8 = 32 +~4 * ~16 = 64 +~4 * ~1 = 4 +~4 * ~2 = 8 +~4 * ~4 = 16 +~4 * ~8 = 32 +~4 * ~16 = 64 +~3 * ~1 = 3 +~3 * ~2 = 6 +~3 * ~4 = 12 +~3 * ~8 = 24 +~3 * ~16 = 48 +~2 * ~1 = 2 +~2 * ~2 = 4 +~2 * ~4 = 8 +~2 * ~8 = 16 +~2 * ~16 = 32 +~1 * ~1 = 1 +~1 * ~2 = 2 +~1 * ~4 = 4 +~1 * ~8 = 8 +~1 * ~16 = 16 +0 * ~1 = 0 +0 * ~2 = 0 +0 * ~4 = 0 +0 * ~8 = 0 +0 * ~16 = 0 +1 * ~1 = ~1 +1 * ~2 = ~2 +1 * ~4 = ~4 +1 * ~8 = ~8 +1 * ~16 = ~16 +2 * ~1 = ~2 +2 * ~2 = ~4 +2 * ~4 = ~8 +2 * ~8 = ~16 +2 * ~16 = ~32 +3 * ~1 = ~3 +3 * ~2 = ~6 +3 * ~4 = ~12 +3 * ~8 = ~24 +3 * ~16 = ~48 +4 * ~1 = ~4 +4 * ~2 = ~8 +4 * ~4 = ~16 +4 * ~8 = ~32 +4 * ~16 = ~64 +2 * ~1 = ~2 +2 * ~2 = ~4 +2 * ~4 = ~8 +2 * ~8 = ~16 +2 * ~16 = ~32 +4 * ~1 = ~4 +4 * ~2 = ~8 +4 * ~4 = ~16 +4 * ~8 = ~32 +4 * ~16 = ~64 +8 * ~1 = ~8 +8 * ~2 = ~16 +8 * ~4 = ~32 +8 * ~8 = ~64 +8 * ~16 = ~128 +16 * ~1 = ~16 +16 * ~2 = ~32 +16 * ~4 = ~64 +16 * ~8 = ~128 +16 * ~16 = Overflow +32 * ~1 = ~32 +32 * ~2 = ~64 +32 * ~4 = ~128 +32 * ~8 = Overflow +32 * ~16 = Overflow +64 * ~1 = ~64 +64 * ~2 = ~128 +64 * ~4 = Overflow +64 * ~8 = Overflow +64 * ~16 = Overflow +~32 * 16384 = Overflow +~32 * 8192 = Overflow +~32 * 4096 = Overflow +~32 * 2048 = Overflow +~32 * 1024 = ~32768 +~31 * 16384 = Overflow +~31 * 8192 = Overflow +~31 * 4096 = Overflow +~31 * 2048 = Overflow +~31 * 1024 = ~31744 +~30 * 16384 = Overflow +~30 * 8192 = Overflow +~30 * 4096 = Overflow +~30 * 2048 = Overflow +~30 * 1024 = ~30720 +~29 * 16384 = Overflow +~29 * 8192 = Overflow +~29 * 4096 = Overflow +~29 * 2048 = Overflow +~29 * 1024 = ~29696 +~28 * 16384 = Overflow +~28 * 8192 = Overflow +~28 * 4096 = Overflow +~28 * 2048 = Overflow +~28 * 1024 = ~28672 +~27 * 16384 = Overflow +~27 * 8192 = Overflow +~27 * 4096 = Overflow +~27 * 2048 = Overflow +~27 * 1024 = ~27648 +~26 * 16384 = Overflow +~26 * 8192 = Overflow +~26 * 4096 = Overflow +~26 * 2048 = Overflow +~26 * 1024 = ~26624 +~25 * 16384 = Overflow +~25 * 8192 = Overflow +~25 * 4096 = Overflow +~25 * 2048 = Overflow +~25 * 1024 = ~25600 +~24 * 16384 = Overflow +~24 * 8192 = Overflow +~24 * 4096 = Overflow +~24 * 2048 = Overflow +~24 * 1024 = ~24576 +~23 * 16384 = Overflow +~23 * 8192 = Overflow +~23 * 4096 = Overflow +~23 * 2048 = Overflow +~23 * 1024 = ~23552 +~22 * 16384 = Overflow +~22 * 8192 = Overflow +~22 * 4096 = Overflow +~22 * 2048 = Overflow +~22 * 1024 = ~22528 +~21 * 16384 = Overflow +~21 * 8192 = Overflow +~21 * 4096 = Overflow +~21 * 2048 = Overflow +~21 * 1024 = ~21504 +~20 * 16384 = Overflow +~20 * 8192 = Overflow +~20 * 4096 = Overflow +~20 * 2048 = Overflow +~20 * 1024 = ~20480 +~19 * 16384 = Overflow +~19 * 8192 = Overflow +~19 * 4096 = Overflow +~19 * 2048 = Overflow +~19 * 1024 = ~19456 +~18 * 16384 = Overflow +~18 * 8192 = Overflow +~18 * 4096 = Overflow +~18 * 2048 = Overflow +~18 * 1024 = ~18432 +~17 * 16384 = Overflow +~17 * 8192 = Overflow +~17 * 4096 = Overflow +~17 * 2048 = Overflow +~17 * 1024 = ~17408 +~16 * 16384 = Overflow +~16 * 8192 = Overflow +~16 * 4096 = Overflow +~16 * 2048 = ~32768 +~16 * 1024 = ~16384 +~15 * 16384 = Overflow +~15 * 8192 = Overflow +~15 * 4096 = Overflow +~15 * 2048 = ~30720 +~15 * 1024 = ~15360 +~14 * 16384 = Overflow +~14 * 8192 = Overflow +~14 * 4096 = Overflow +~14 * 2048 = ~28672 +~14 * 1024 = ~14336 +~13 * 16384 = Overflow +~13 * 8192 = Overflow +~13 * 4096 = Overflow +~13 * 2048 = ~26624 +~13 * 1024 = ~13312 +~12 * 16384 = Overflow +~12 * 8192 = Overflow +~12 * 4096 = Overflow +~12 * 2048 = ~24576 +~12 * 1024 = ~12288 +~11 * 16384 = Overflow +~11 * 8192 = Overflow +~11 * 4096 = Overflow +~11 * 2048 = ~22528 +~11 * 1024 = ~11264 +~10 * 16384 = Overflow +~10 * 8192 = Overflow +~10 * 4096 = Overflow +~10 * 2048 = ~20480 +~10 * 1024 = ~10240 +~9 * 16384 = Overflow +~9 * 8192 = Overflow +~9 * 4096 = Overflow +~9 * 2048 = ~18432 +~9 * 1024 = ~9216 +~8 * 16384 = Overflow +~8 * 8192 = Overflow +~8 * 4096 = ~32768 +~8 * 2048 = ~16384 +~8 * 1024 = ~8192 +~7 * 16384 = Overflow +~7 * 8192 = Overflow +~7 * 4096 = ~28672 +~7 * 2048 = ~14336 +~7 * 1024 = ~7168 +~6 * 16384 = Overflow +~6 * 8192 = Overflow +~6 * 4096 = ~24576 +~6 * 2048 = ~12288 +~6 * 1024 = ~6144 +~5 * 16384 = Overflow +~5 * 8192 = Overflow +~5 * 4096 = ~20480 +~5 * 2048 = ~10240 +~5 * 1024 = ~5120 +~4 * 16384 = Overflow +~4 * 8192 = ~32768 +~4 * 4096 = ~16384 +~4 * 2048 = ~8192 +~4 * 1024 = ~4096 +~3 * 16384 = Overflow +~3 * 8192 = ~24576 +~3 * 4096 = ~12288 +~3 * 2048 = ~6144 +~3 * 1024 = ~3072 +~2 * 16384 = ~32768 +~2 * 8192 = ~16384 +~2 * 4096 = ~8192 +~2 * 2048 = ~4096 +~2 * 1024 = ~2048 +~1 * 16384 = ~16384 +~1 * 8192 = ~8192 +~1 * 4096 = ~4096 +~1 * 2048 = ~2048 +~1 * 1024 = ~1024 +0 * 16384 = 0 +0 * 8192 = 0 +0 * 4096 = 0 +0 * 2048 = 0 +0 * 1024 = 0 +1 * 16384 = 16384 +1 * 8192 = 8192 +1 * 4096 = 4096 +1 * 2048 = 2048 +1 * 1024 = 1024 +2 * 16384 = Overflow +2 * 8192 = 16384 +2 * 4096 = 8192 +2 * 2048 = 4096 +2 * 1024 = 2048 +3 * 16384 = Overflow +3 * 8192 = 24576 +3 * 4096 = 12288 +3 * 2048 = 6144 +3 * 1024 = 3072 +4 * 16384 = Overflow +4 * 8192 = Overflow +4 * 4096 = 16384 +4 * 2048 = 8192 +4 * 1024 = 4096 +5 * 16384 = Overflow +5 * 8192 = Overflow +5 * 4096 = 20480 +5 * 2048 = 10240 +5 * 1024 = 5120 +6 * 16384 = Overflow +6 * 8192 = Overflow +6 * 4096 = 24576 +6 * 2048 = 12288 +6 * 1024 = 6144 +7 * 16384 = Overflow +7 * 8192 = Overflow +7 * 4096 = 28672 +7 * 2048 = 14336 +7 * 1024 = 7168 +8 * 16384 = Overflow +8 * 8192 = Overflow +8 * 4096 = Overflow +8 * 2048 = 16384 +8 * 1024 = 8192 +9 * 16384 = Overflow +9 * 8192 = Overflow +9 * 4096 = Overflow +9 * 2048 = 18432 +9 * 1024 = 9216 +10 * 16384 = Overflow +10 * 8192 = Overflow +10 * 4096 = Overflow +10 * 2048 = 20480 +10 * 1024 = 10240 +11 * 16384 = Overflow +11 * 8192 = Overflow +11 * 4096 = Overflow +11 * 2048 = 22528 +11 * 1024 = 11264 +12 * 16384 = Overflow +12 * 8192 = Overflow +12 * 4096 = Overflow +12 * 2048 = 24576 +12 * 1024 = 12288 +13 * 16384 = Overflow +13 * 8192 = Overflow +13 * 4096 = Overflow +13 * 2048 = 26624 +13 * 1024 = 13312 +14 * 16384 = Overflow +14 * 8192 = Overflow +14 * 4096 = Overflow +14 * 2048 = 28672 +14 * 1024 = 14336 +15 * 16384 = Overflow +15 * 8192 = Overflow +15 * 4096 = Overflow +15 * 2048 = 30720 +15 * 1024 = 15360 +16 * 16384 = Overflow +16 * 8192 = Overflow +16 * 4096 = Overflow +16 * 2048 = Overflow +16 * 1024 = 16384 +17 * 16384 = Overflow +17 * 8192 = Overflow +17 * 4096 = Overflow +17 * 2048 = Overflow +17 * 1024 = 17408 +18 * 16384 = Overflow +18 * 8192 = Overflow +18 * 4096 = Overflow +18 * 2048 = Overflow +18 * 1024 = 18432 +19 * 16384 = Overflow +19 * 8192 = Overflow +19 * 4096 = Overflow +19 * 2048 = Overflow +19 * 1024 = 19456 +20 * 16384 = Overflow +20 * 8192 = Overflow +20 * 4096 = Overflow +20 * 2048 = Overflow +20 * 1024 = 20480 +21 * 16384 = Overflow +21 * 8192 = Overflow +21 * 4096 = Overflow +21 * 2048 = Overflow +21 * 1024 = 21504 +22 * 16384 = Overflow +22 * 8192 = Overflow +22 * 4096 = Overflow +22 * 2048 = Overflow +22 * 1024 = 22528 +23 * 16384 = Overflow +23 * 8192 = Overflow +23 * 4096 = Overflow +23 * 2048 = Overflow +23 * 1024 = 23552 +24 * 16384 = Overflow +24 * 8192 = Overflow +24 * 4096 = Overflow +24 * 2048 = Overflow +24 * 1024 = 24576 +25 * 16384 = Overflow +25 * 8192 = Overflow +25 * 4096 = Overflow +25 * 2048 = Overflow +25 * 1024 = 25600 +26 * 16384 = Overflow +26 * 8192 = Overflow +26 * 4096 = Overflow +26 * 2048 = Overflow +26 * 1024 = 26624 +27 * 16384 = Overflow +27 * 8192 = Overflow +27 * 4096 = Overflow +27 * 2048 = Overflow +27 * 1024 = 27648 +28 * 16384 = Overflow +28 * 8192 = Overflow +28 * 4096 = Overflow +28 * 2048 = Overflow +28 * 1024 = 28672 +29 * 16384 = Overflow +29 * 8192 = Overflow +29 * 4096 = Overflow +29 * 2048 = Overflow +29 * 1024 = 29696 +30 * 16384 = Overflow +30 * 8192 = Overflow +30 * 4096 = Overflow +30 * 2048 = Overflow +30 * 1024 = 30720 +31 * 16384 = Overflow +31 * 8192 = Overflow +31 * 4096 = Overflow +31 * 2048 = Overflow +31 * 1024 = 31744 +32 * 16384 = Overflow +32 * 8192 = Overflow +32 * 4096 = Overflow +32 * 2048 = Overflow +32 * 1024 = Overflow +~32 * ~32768 = Overflow +~32 * ~16384 = Overflow +~32 * ~8192 = Overflow +~32 * ~4096 = Overflow +~32 * ~2048 = Overflow +~31 * ~32768 = Overflow +~31 * ~16384 = Overflow +~31 * ~8192 = Overflow +~31 * ~4096 = Overflow +~31 * ~2048 = Overflow +~30 * ~32768 = Overflow +~30 * ~16384 = Overflow +~30 * ~8192 = Overflow +~30 * ~4096 = Overflow +~30 * ~2048 = Overflow +~29 * ~32768 = Overflow +~29 * ~16384 = Overflow +~29 * ~8192 = Overflow +~29 * ~4096 = Overflow +~29 * ~2048 = Overflow +~28 * ~32768 = Overflow +~28 * ~16384 = Overflow +~28 * ~8192 = Overflow +~28 * ~4096 = Overflow +~28 * ~2048 = Overflow +~27 * ~32768 = Overflow +~27 * ~16384 = Overflow +~27 * ~8192 = Overflow +~27 * ~4096 = Overflow +~27 * ~2048 = Overflow +~26 * ~32768 = Overflow +~26 * ~16384 = Overflow +~26 * ~8192 = Overflow +~26 * ~4096 = Overflow +~26 * ~2048 = Overflow +~25 * ~32768 = Overflow +~25 * ~16384 = Overflow +~25 * ~8192 = Overflow +~25 * ~4096 = Overflow +~25 * ~2048 = Overflow +~24 * ~32768 = Overflow +~24 * ~16384 = Overflow +~24 * ~8192 = Overflow +~24 * ~4096 = Overflow +~24 * ~2048 = Overflow +~23 * ~32768 = Overflow +~23 * ~16384 = Overflow +~23 * ~8192 = Overflow +~23 * ~4096 = Overflow +~23 * ~2048 = Overflow +~22 * ~32768 = Overflow +~22 * ~16384 = Overflow +~22 * ~8192 = Overflow +~22 * ~4096 = Overflow +~22 * ~2048 = Overflow +~21 * ~32768 = Overflow +~21 * ~16384 = Overflow +~21 * ~8192 = Overflow +~21 * ~4096 = Overflow +~21 * ~2048 = Overflow +~20 * ~32768 = Overflow +~20 * ~16384 = Overflow +~20 * ~8192 = Overflow +~20 * ~4096 = Overflow +~20 * ~2048 = Overflow +~19 * ~32768 = Overflow +~19 * ~16384 = Overflow +~19 * ~8192 = Overflow +~19 * ~4096 = Overflow +~19 * ~2048 = Overflow +~18 * ~32768 = Overflow +~18 * ~16384 = Overflow +~18 * ~8192 = Overflow +~18 * ~4096 = Overflow +~18 * ~2048 = Overflow +~17 * ~32768 = Overflow +~17 * ~16384 = Overflow +~17 * ~8192 = Overflow +~17 * ~4096 = Overflow +~17 * ~2048 = Overflow +~16 * ~32768 = Overflow +~16 * ~16384 = Overflow +~16 * ~8192 = Overflow +~16 * ~4096 = Overflow +~16 * ~2048 = Overflow +~15 * ~32768 = Overflow +~15 * ~16384 = Overflow +~15 * ~8192 = Overflow +~15 * ~4096 = Overflow +~15 * ~2048 = 30720 +~14 * ~32768 = Overflow +~14 * ~16384 = Overflow +~14 * ~8192 = Overflow +~14 * ~4096 = Overflow +~14 * ~2048 = 28672 +~13 * ~32768 = Overflow +~13 * ~16384 = Overflow +~13 * ~8192 = Overflow +~13 * ~4096 = Overflow +~13 * ~2048 = 26624 +~12 * ~32768 = Overflow +~12 * ~16384 = Overflow +~12 * ~8192 = Overflow +~12 * ~4096 = Overflow +~12 * ~2048 = 24576 +~11 * ~32768 = Overflow +~11 * ~16384 = Overflow +~11 * ~8192 = Overflow +~11 * ~4096 = Overflow +~11 * ~2048 = 22528 +~10 * ~32768 = Overflow +~10 * ~16384 = Overflow +~10 * ~8192 = Overflow +~10 * ~4096 = Overflow +~10 * ~2048 = 20480 +~9 * ~32768 = Overflow +~9 * ~16384 = Overflow +~9 * ~8192 = Overflow +~9 * ~4096 = Overflow +~9 * ~2048 = 18432 +~8 * ~32768 = Overflow +~8 * ~16384 = Overflow +~8 * ~8192 = Overflow +~8 * ~4096 = Overflow +~8 * ~2048 = 16384 +~7 * ~32768 = Overflow +~7 * ~16384 = Overflow +~7 * ~8192 = Overflow +~7 * ~4096 = 28672 +~7 * ~2048 = 14336 +~6 * ~32768 = Overflow +~6 * ~16384 = Overflow +~6 * ~8192 = Overflow +~6 * ~4096 = 24576 +~6 * ~2048 = 12288 +~5 * ~32768 = Overflow +~5 * ~16384 = Overflow +~5 * ~8192 = Overflow +~5 * ~4096 = 20480 +~5 * ~2048 = 10240 +~4 * ~32768 = Overflow +~4 * ~16384 = Overflow +~4 * ~8192 = Overflow +~4 * ~4096 = 16384 +~4 * ~2048 = 8192 +~3 * ~32768 = Overflow +~3 * ~16384 = Overflow +~3 * ~8192 = 24576 +~3 * ~4096 = 12288 +~3 * ~2048 = 6144 +~2 * ~32768 = Overflow +~2 * ~16384 = Overflow +~2 * ~8192 = 16384 +~2 * ~4096 = 8192 +~2 * ~2048 = 4096 +~1 * ~32768 = Overflow +~1 * ~16384 = 16384 +~1 * ~8192 = 8192 +~1 * ~4096 = 4096 +~1 * ~2048 = 2048 +0 * ~32768 = 0 +0 * ~16384 = 0 +0 * ~8192 = 0 +0 * ~4096 = 0 +0 * ~2048 = 0 +1 * ~32768 = ~32768 +1 * ~16384 = ~16384 +1 * ~8192 = ~8192 +1 * ~4096 = ~4096 +1 * ~2048 = ~2048 +2 * ~32768 = Overflow +2 * ~16384 = ~32768 +2 * ~8192 = ~16384 +2 * ~4096 = ~8192 +2 * ~2048 = ~4096 +3 * ~32768 = Overflow +3 * ~16384 = Overflow +3 * ~8192 = ~24576 +3 * ~4096 = ~12288 +3 * ~2048 = ~6144 +4 * ~32768 = Overflow +4 * ~16384 = Overflow +4 * ~8192 = ~32768 +4 * ~4096 = ~16384 +4 * ~2048 = ~8192 +5 * ~32768 = Overflow +5 * ~16384 = Overflow +5 * ~8192 = Overflow +5 * ~4096 = ~20480 +5 * ~2048 = ~10240 +6 * ~32768 = Overflow +6 * ~16384 = Overflow +6 * ~8192 = Overflow +6 * ~4096 = ~24576 +6 * ~2048 = ~12288 +7 * ~32768 = Overflow +7 * ~16384 = Overflow +7 * ~8192 = Overflow +7 * ~4096 = ~28672 +7 * ~2048 = ~14336 +8 * ~32768 = Overflow +8 * ~16384 = Overflow +8 * ~8192 = Overflow +8 * ~4096 = ~32768 +8 * ~2048 = ~16384 +9 * ~32768 = Overflow +9 * ~16384 = Overflow +9 * ~8192 = Overflow +9 * ~4096 = Overflow +9 * ~2048 = ~18432 +10 * ~32768 = Overflow +10 * ~16384 = Overflow +10 * ~8192 = Overflow +10 * ~4096 = Overflow +10 * ~2048 = ~20480 +11 * ~32768 = Overflow +11 * ~16384 = Overflow +11 * ~8192 = Overflow +11 * ~4096 = Overflow +11 * ~2048 = ~22528 +12 * ~32768 = Overflow +12 * ~16384 = Overflow +12 * ~8192 = Overflow +12 * ~4096 = Overflow +12 * ~2048 = ~24576 +13 * ~32768 = Overflow +13 * ~16384 = Overflow +13 * ~8192 = Overflow +13 * ~4096 = Overflow +13 * ~2048 = ~26624 +14 * ~32768 = Overflow +14 * ~16384 = Overflow +14 * ~8192 = Overflow +14 * ~4096 = Overflow +14 * ~2048 = ~28672 +15 * ~32768 = Overflow +15 * ~16384 = Overflow +15 * ~8192 = Overflow +15 * ~4096 = Overflow +15 * ~2048 = ~30720 +16 * ~32768 = Overflow +16 * ~16384 = Overflow +16 * ~8192 = Overflow +16 * ~4096 = Overflow +16 * ~2048 = ~32768 +17 * ~32768 = Overflow +17 * ~16384 = Overflow +17 * ~8192 = Overflow +17 * ~4096 = Overflow +17 * ~2048 = Overflow +18 * ~32768 = Overflow +18 * ~16384 = Overflow +18 * ~8192 = Overflow +18 * ~4096 = Overflow +18 * ~2048 = Overflow +19 * ~32768 = Overflow +19 * ~16384 = Overflow +19 * ~8192 = Overflow +19 * ~4096 = Overflow +19 * ~2048 = Overflow +20 * ~32768 = Overflow +20 * ~16384 = Overflow +20 * ~8192 = Overflow +20 * ~4096 = Overflow +20 * ~2048 = Overflow +21 * ~32768 = Overflow +21 * ~16384 = Overflow +21 * ~8192 = Overflow +21 * ~4096 = Overflow +21 * ~2048 = Overflow +22 * ~32768 = Overflow +22 * ~16384 = Overflow +22 * ~8192 = Overflow +22 * ~4096 = Overflow +22 * ~2048 = Overflow +23 * ~32768 = Overflow +23 * ~16384 = Overflow +23 * ~8192 = Overflow +23 * ~4096 = Overflow +23 * ~2048 = Overflow +24 * ~32768 = Overflow +24 * ~16384 = Overflow +24 * ~8192 = Overflow +24 * ~4096 = Overflow +24 * ~2048 = Overflow +25 * ~32768 = Overflow +25 * ~16384 = Overflow +25 * ~8192 = Overflow +25 * ~4096 = Overflow +25 * ~2048 = Overflow +26 * ~32768 = Overflow +26 * ~16384 = Overflow +26 * ~8192 = Overflow +26 * ~4096 = Overflow +26 * ~2048 = Overflow +27 * ~32768 = Overflow +27 * ~16384 = Overflow +27 * ~8192 = Overflow +27 * ~4096 = Overflow +27 * ~2048 = Overflow +28 * ~32768 = Overflow +28 * ~16384 = Overflow +28 * ~8192 = Overflow +28 * ~4096 = Overflow +28 * ~2048 = Overflow +29 * ~32768 = Overflow +29 * ~16384 = Overflow +29 * ~8192 = Overflow +29 * ~4096 = Overflow +29 * ~2048 = Overflow +30 * ~32768 = Overflow +30 * ~16384 = Overflow +30 * ~8192 = Overflow +30 * ~4096 = Overflow +30 * ~2048 = Overflow +31 * ~32768 = Overflow +31 * ~16384 = Overflow +31 * ~8192 = Overflow +31 * ~4096 = Overflow +31 * ~2048 = Overflow +32 * ~32768 = Overflow +32 * ~16384 = Overflow +32 * ~8192 = Overflow +32 * ~4096 = Overflow +32 * ~2048 = Overflow +~32768 * 1 = ~32768 +~32768 * 2 = Overflow +~32768 * 4 = Overflow +~32768 * 8 = Overflow +~32768 * 16 = Overflow +~16384 * 1 = ~16384 +~16384 * 2 = ~32768 +~16384 * 4 = Overflow +~16384 * 8 = Overflow +~16384 * 16 = Overflow +~8192 * 1 = ~8192 +~8192 * 2 = ~16384 +~8192 * 4 = ~32768 +~8192 * 8 = Overflow +~8192 * 16 = Overflow +~4096 * 1 = ~4096 +~4096 * 2 = ~8192 +~4096 * 4 = ~16384 +~4096 * 8 = ~32768 +~4096 * 16 = Overflow +~2048 * 1 = ~2048 +~2048 * 2 = ~4096 +~2048 * 4 = ~8192 +~2048 * 8 = ~16384 +~2048 * 16 = ~32768 +~1024 * 1 = ~1024 +~1024 * 2 = ~2048 +~1024 * 4 = ~4096 +~1024 * 8 = ~8192 +~1024 * 16 = ~16384 +~4 * 1 = ~4 +~4 * 2 = ~8 +~4 * 4 = ~16 +~4 * 8 = ~32 +~4 * 16 = ~64 +~3 * 1 = ~3 +~3 * 2 = ~6 +~3 * 4 = ~12 +~3 * 8 = ~24 +~3 * 16 = ~48 +~2 * 1 = ~2 +~2 * 2 = ~4 +~2 * 4 = ~8 +~2 * 8 = ~16 +~2 * 16 = ~32 +~1 * 1 = ~1 +~1 * 2 = ~2 +~1 * 4 = ~4 +~1 * 8 = ~8 +~1 * 16 = ~16 +0 * 1 = 0 +0 * 2 = 0 +0 * 4 = 0 +0 * 8 = 0 +0 * 16 = 0 +1 * 1 = 1 +1 * 2 = 2 +1 * 4 = 4 +1 * 8 = 8 +1 * 16 = 16 +2 * 1 = 2 +2 * 2 = 4 +2 * 4 = 8 +2 * 8 = 16 +2 * 16 = 32 +3 * 1 = 3 +3 * 2 = 6 +3 * 4 = 12 +3 * 8 = 24 +3 * 16 = 48 +4 * 1 = 4 +4 * 2 = 8 +4 * 4 = 16 +4 * 8 = 32 +4 * 16 = 64 +512 * 1 = 512 +512 * 2 = 1024 +512 * 4 = 2048 +512 * 8 = 4096 +512 * 16 = 8192 +1024 * 1 = 1024 +1024 * 2 = 2048 +1024 * 4 = 4096 +1024 * 8 = 8192 +1024 * 16 = 16384 +2048 * 1 = 2048 +2048 * 2 = 4096 +2048 * 4 = 8192 +2048 * 8 = 16384 +2048 * 16 = Overflow +4096 * 1 = 4096 +4096 * 2 = 8192 +4096 * 4 = 16384 +4096 * 8 = Overflow +4096 * 16 = Overflow +8192 * 1 = 8192 +8192 * 2 = 16384 +8192 * 4 = Overflow +8192 * 8 = Overflow +8192 * 16 = Overflow +16384 * 1 = 16384 +16384 * 2 = Overflow +16384 * 4 = Overflow +16384 * 8 = Overflow +16384 * 16 = Overflow +~32768 * ~1 = Overflow +~32768 * ~2 = Overflow +~32768 * ~4 = Overflow +~32768 * ~8 = Overflow +~32768 * ~16 = Overflow +~16384 * ~1 = 16384 +~16384 * ~2 = Overflow +~16384 * ~4 = Overflow +~16384 * ~8 = Overflow +~16384 * ~16 = Overflow +~8192 * ~1 = 8192 +~8192 * ~2 = 16384 +~8192 * ~4 = Overflow +~8192 * ~8 = Overflow +~8192 * ~16 = Overflow +~4096 * ~1 = 4096 +~4096 * ~2 = 8192 +~4096 * ~4 = 16384 +~4096 * ~8 = Overflow +~4096 * ~16 = Overflow +~2048 * ~1 = 2048 +~2048 * ~2 = 4096 +~2048 * ~4 = 8192 +~2048 * ~8 = 16384 +~2048 * ~16 = Overflow +~1024 * ~1 = 1024 +~1024 * ~2 = 2048 +~1024 * ~4 = 4096 +~1024 * ~8 = 8192 +~1024 * ~16 = 16384 +~4 * ~1 = 4 +~4 * ~2 = 8 +~4 * ~4 = 16 +~4 * ~8 = 32 +~4 * ~16 = 64 +~3 * ~1 = 3 +~3 * ~2 = 6 +~3 * ~4 = 12 +~3 * ~8 = 24 +~3 * ~16 = 48 +~2 * ~1 = 2 +~2 * ~2 = 4 +~2 * ~4 = 8 +~2 * ~8 = 16 +~2 * ~16 = 32 +~1 * ~1 = 1 +~1 * ~2 = 2 +~1 * ~4 = 4 +~1 * ~8 = 8 +~1 * ~16 = 16 +0 * ~1 = 0 +0 * ~2 = 0 +0 * ~4 = 0 +0 * ~8 = 0 +0 * ~16 = 0 +1 * ~1 = ~1 +1 * ~2 = ~2 +1 * ~4 = ~4 +1 * ~8 = ~8 +1 * ~16 = ~16 +2 * ~1 = ~2 +2 * ~2 = ~4 +2 * ~4 = ~8 +2 * ~8 = ~16 +2 * ~16 = ~32 +3 * ~1 = ~3 +3 * ~2 = ~6 +3 * ~4 = ~12 +3 * ~8 = ~24 +3 * ~16 = ~48 +4 * ~1 = ~4 +4 * ~2 = ~8 +4 * ~4 = ~16 +4 * ~8 = ~32 +4 * ~16 = ~64 +512 * ~1 = ~512 +512 * ~2 = ~1024 +512 * ~4 = ~2048 +512 * ~8 = ~4096 +512 * ~16 = ~8192 +1024 * ~1 = ~1024 +1024 * ~2 = ~2048 +1024 * ~4 = ~4096 +1024 * ~8 = ~8192 +1024 * ~16 = ~16384 +2048 * ~1 = ~2048 +2048 * ~2 = ~4096 +2048 * ~4 = ~8192 +2048 * ~8 = ~16384 +2048 * ~16 = ~32768 +4096 * ~1 = ~4096 +4096 * ~2 = ~8192 +4096 * ~4 = ~16384 +4096 * ~8 = ~32768 +4096 * ~16 = Overflow +8192 * ~1 = ~8192 +8192 * ~2 = ~16384 +8192 * ~4 = ~32768 +8192 * ~8 = Overflow +8192 * ~16 = Overflow +16384 * ~1 = ~16384 +16384 * ~2 = ~32768 +16384 * ~4 = Overflow +16384 * ~8 = Overflow +16384 * ~16 = Overflow +~32 * 1073741824 = Overflow +~32 * 536870912 = Overflow +~32 * 268435456 = Overflow +~32 * 134217728 = Overflow +~32 * 67108864 = ~2147483648 +~31 * 1073741824 = Overflow +~31 * 536870912 = Overflow +~31 * 268435456 = Overflow +~31 * 134217728 = Overflow +~31 * 67108864 = ~2080374784 +~30 * 1073741824 = Overflow +~30 * 536870912 = Overflow +~30 * 268435456 = Overflow +~30 * 134217728 = Overflow +~30 * 67108864 = ~2013265920 +~29 * 1073741824 = Overflow +~29 * 536870912 = Overflow +~29 * 268435456 = Overflow +~29 * 134217728 = Overflow +~29 * 67108864 = ~1946157056 +~28 * 1073741824 = Overflow +~28 * 536870912 = Overflow +~28 * 268435456 = Overflow +~28 * 134217728 = Overflow +~28 * 67108864 = ~1879048192 +~27 * 1073741824 = Overflow +~27 * 536870912 = Overflow +~27 * 268435456 = Overflow +~27 * 134217728 = Overflow +~27 * 67108864 = ~1811939328 +~26 * 1073741824 = Overflow +~26 * 536870912 = Overflow +~26 * 268435456 = Overflow +~26 * 134217728 = Overflow +~26 * 67108864 = ~1744830464 +~25 * 1073741824 = Overflow +~25 * 536870912 = Overflow +~25 * 268435456 = Overflow +~25 * 134217728 = Overflow +~25 * 67108864 = ~1677721600 +~24 * 1073741824 = Overflow +~24 * 536870912 = Overflow +~24 * 268435456 = Overflow +~24 * 134217728 = Overflow +~24 * 67108864 = ~1610612736 +~23 * 1073741824 = Overflow +~23 * 536870912 = Overflow +~23 * 268435456 = Overflow +~23 * 134217728 = Overflow +~23 * 67108864 = ~1543503872 +~22 * 1073741824 = Overflow +~22 * 536870912 = Overflow +~22 * 268435456 = Overflow +~22 * 134217728 = Overflow +~22 * 67108864 = ~1476395008 +~21 * 1073741824 = Overflow +~21 * 536870912 = Overflow +~21 * 268435456 = Overflow +~21 * 134217728 = Overflow +~21 * 67108864 = ~1409286144 +~20 * 1073741824 = Overflow +~20 * 536870912 = Overflow +~20 * 268435456 = Overflow +~20 * 134217728 = Overflow +~20 * 67108864 = ~1342177280 +~19 * 1073741824 = Overflow +~19 * 536870912 = Overflow +~19 * 268435456 = Overflow +~19 * 134217728 = Overflow +~19 * 67108864 = ~1275068416 +~18 * 1073741824 = Overflow +~18 * 536870912 = Overflow +~18 * 268435456 = Overflow +~18 * 134217728 = Overflow +~18 * 67108864 = ~1207959552 +~17 * 1073741824 = Overflow +~17 * 536870912 = Overflow +~17 * 268435456 = Overflow +~17 * 134217728 = Overflow +~17 * 67108864 = ~1140850688 +~16 * 1073741824 = Overflow +~16 * 536870912 = Overflow +~16 * 268435456 = Overflow +~16 * 134217728 = ~2147483648 +~16 * 67108864 = ~1073741824 +~15 * 1073741824 = Overflow +~15 * 536870912 = Overflow +~15 * 268435456 = Overflow +~15 * 134217728 = ~2013265920 +~15 * 67108864 = ~1006632960 +~14 * 1073741824 = Overflow +~14 * 536870912 = Overflow +~14 * 268435456 = Overflow +~14 * 134217728 = ~1879048192 +~14 * 67108864 = ~939524096 +~13 * 1073741824 = Overflow +~13 * 536870912 = Overflow +~13 * 268435456 = Overflow +~13 * 134217728 = ~1744830464 +~13 * 67108864 = ~872415232 +~12 * 1073741824 = Overflow +~12 * 536870912 = Overflow +~12 * 268435456 = Overflow +~12 * 134217728 = ~1610612736 +~12 * 67108864 = ~805306368 +~11 * 1073741824 = Overflow +~11 * 536870912 = Overflow +~11 * 268435456 = Overflow +~11 * 134217728 = ~1476395008 +~11 * 67108864 = ~738197504 +~10 * 1073741824 = Overflow +~10 * 536870912 = Overflow +~10 * 268435456 = Overflow +~10 * 134217728 = ~1342177280 +~10 * 67108864 = ~671088640 +~9 * 1073741824 = Overflow +~9 * 536870912 = Overflow +~9 * 268435456 = Overflow +~9 * 134217728 = ~1207959552 +~9 * 67108864 = ~603979776 +~8 * 1073741824 = Overflow +~8 * 536870912 = Overflow +~8 * 268435456 = ~2147483648 +~8 * 134217728 = ~1073741824 +~8 * 67108864 = ~536870912 +~7 * 1073741824 = Overflow +~7 * 536870912 = Overflow +~7 * 268435456 = ~1879048192 +~7 * 134217728 = ~939524096 +~7 * 67108864 = ~469762048 +~6 * 1073741824 = Overflow +~6 * 536870912 = Overflow +~6 * 268435456 = ~1610612736 +~6 * 134217728 = ~805306368 +~6 * 67108864 = ~402653184 +~5 * 1073741824 = Overflow +~5 * 536870912 = Overflow +~5 * 268435456 = ~1342177280 +~5 * 134217728 = ~671088640 +~5 * 67108864 = ~335544320 +~4 * 1073741824 = Overflow +~4 * 536870912 = ~2147483648 +~4 * 268435456 = ~1073741824 +~4 * 134217728 = ~536870912 +~4 * 67108864 = ~268435456 +~3 * 1073741824 = Overflow +~3 * 536870912 = ~1610612736 +~3 * 268435456 = ~805306368 +~3 * 134217728 = ~402653184 +~3 * 67108864 = ~201326592 +~2 * 1073741824 = ~2147483648 +~2 * 536870912 = ~1073741824 +~2 * 268435456 = ~536870912 +~2 * 134217728 = ~268435456 +~2 * 67108864 = ~134217728 +~1 * 1073741824 = ~1073741824 +~1 * 536870912 = ~536870912 +~1 * 268435456 = ~268435456 +~1 * 134217728 = ~134217728 +~1 * 67108864 = ~67108864 +0 * 1073741824 = 0 +0 * 536870912 = 0 +0 * 268435456 = 0 +0 * 134217728 = 0 +0 * 67108864 = 0 +1 * 1073741824 = 1073741824 +1 * 536870912 = 536870912 +1 * 268435456 = 268435456 +1 * 134217728 = 134217728 +1 * 67108864 = 67108864 +2 * 1073741824 = Overflow +2 * 536870912 = 1073741824 +2 * 268435456 = 536870912 +2 * 134217728 = 268435456 +2 * 67108864 = 134217728 +3 * 1073741824 = Overflow +3 * 536870912 = 1610612736 +3 * 268435456 = 805306368 +3 * 134217728 = 402653184 +3 * 67108864 = 201326592 +4 * 1073741824 = Overflow +4 * 536870912 = Overflow +4 * 268435456 = 1073741824 +4 * 134217728 = 536870912 +4 * 67108864 = 268435456 +5 * 1073741824 = Overflow +5 * 536870912 = Overflow +5 * 268435456 = 1342177280 +5 * 134217728 = 671088640 +5 * 67108864 = 335544320 +6 * 1073741824 = Overflow +6 * 536870912 = Overflow +6 * 268435456 = 1610612736 +6 * 134217728 = 805306368 +6 * 67108864 = 402653184 +7 * 1073741824 = Overflow +7 * 536870912 = Overflow +7 * 268435456 = 1879048192 +7 * 134217728 = 939524096 +7 * 67108864 = 469762048 +8 * 1073741824 = Overflow +8 * 536870912 = Overflow +8 * 268435456 = Overflow +8 * 134217728 = 1073741824 +8 * 67108864 = 536870912 +9 * 1073741824 = Overflow +9 * 536870912 = Overflow +9 * 268435456 = Overflow +9 * 134217728 = 1207959552 +9 * 67108864 = 603979776 +10 * 1073741824 = Overflow +10 * 536870912 = Overflow +10 * 268435456 = Overflow +10 * 134217728 = 1342177280 +10 * 67108864 = 671088640 +11 * 1073741824 = Overflow +11 * 536870912 = Overflow +11 * 268435456 = Overflow +11 * 134217728 = 1476395008 +11 * 67108864 = 738197504 +12 * 1073741824 = Overflow +12 * 536870912 = Overflow +12 * 268435456 = Overflow +12 * 134217728 = 1610612736 +12 * 67108864 = 805306368 +13 * 1073741824 = Overflow +13 * 536870912 = Overflow +13 * 268435456 = Overflow +13 * 134217728 = 1744830464 +13 * 67108864 = 872415232 +14 * 1073741824 = Overflow +14 * 536870912 = Overflow +14 * 268435456 = Overflow +14 * 134217728 = 1879048192 +14 * 67108864 = 939524096 +15 * 1073741824 = Overflow +15 * 536870912 = Overflow +15 * 268435456 = Overflow +15 * 134217728 = 2013265920 +15 * 67108864 = 1006632960 +16 * 1073741824 = Overflow +16 * 536870912 = Overflow +16 * 268435456 = Overflow +16 * 134217728 = Overflow +16 * 67108864 = 1073741824 +17 * 1073741824 = Overflow +17 * 536870912 = Overflow +17 * 268435456 = Overflow +17 * 134217728 = Overflow +17 * 67108864 = 1140850688 +18 * 1073741824 = Overflow +18 * 536870912 = Overflow +18 * 268435456 = Overflow +18 * 134217728 = Overflow +18 * 67108864 = 1207959552 +19 * 1073741824 = Overflow +19 * 536870912 = Overflow +19 * 268435456 = Overflow +19 * 134217728 = Overflow +19 * 67108864 = 1275068416 +20 * 1073741824 = Overflow +20 * 536870912 = Overflow +20 * 268435456 = Overflow +20 * 134217728 = Overflow +20 * 67108864 = 1342177280 +21 * 1073741824 = Overflow +21 * 536870912 = Overflow +21 * 268435456 = Overflow +21 * 134217728 = Overflow +21 * 67108864 = 1409286144 +22 * 1073741824 = Overflow +22 * 536870912 = Overflow +22 * 268435456 = Overflow +22 * 134217728 = Overflow +22 * 67108864 = 1476395008 +23 * 1073741824 = Overflow +23 * 536870912 = Overflow +23 * 268435456 = Overflow +23 * 134217728 = Overflow +23 * 67108864 = 1543503872 +24 * 1073741824 = Overflow +24 * 536870912 = Overflow +24 * 268435456 = Overflow +24 * 134217728 = Overflow +24 * 67108864 = 1610612736 +25 * 1073741824 = Overflow +25 * 536870912 = Overflow +25 * 268435456 = Overflow +25 * 134217728 = Overflow +25 * 67108864 = 1677721600 +26 * 1073741824 = Overflow +26 * 536870912 = Overflow +26 * 268435456 = Overflow +26 * 134217728 = Overflow +26 * 67108864 = 1744830464 +27 * 1073741824 = Overflow +27 * 536870912 = Overflow +27 * 268435456 = Overflow +27 * 134217728 = Overflow +27 * 67108864 = 1811939328 +28 * 1073741824 = Overflow +28 * 536870912 = Overflow +28 * 268435456 = Overflow +28 * 134217728 = Overflow +28 * 67108864 = 1879048192 +29 * 1073741824 = Overflow +29 * 536870912 = Overflow +29 * 268435456 = Overflow +29 * 134217728 = Overflow +29 * 67108864 = 1946157056 +30 * 1073741824 = Overflow +30 * 536870912 = Overflow +30 * 268435456 = Overflow +30 * 134217728 = Overflow +30 * 67108864 = 2013265920 +31 * 1073741824 = Overflow +31 * 536870912 = Overflow +31 * 268435456 = Overflow +31 * 134217728 = Overflow +31 * 67108864 = 2080374784 +32 * 1073741824 = Overflow +32 * 536870912 = Overflow +32 * 268435456 = Overflow +32 * 134217728 = Overflow +32 * 67108864 = Overflow +~32 * ~2147483648 = Overflow +~32 * ~1073741824 = Overflow +~32 * ~536870912 = Overflow +~32 * ~268435456 = Overflow +~32 * ~134217728 = Overflow +~31 * ~2147483648 = Overflow +~31 * ~1073741824 = Overflow +~31 * ~536870912 = Overflow +~31 * ~268435456 = Overflow +~31 * ~134217728 = Overflow +~30 * ~2147483648 = Overflow +~30 * ~1073741824 = Overflow +~30 * ~536870912 = Overflow +~30 * ~268435456 = Overflow +~30 * ~134217728 = Overflow +~29 * ~2147483648 = Overflow +~29 * ~1073741824 = Overflow +~29 * ~536870912 = Overflow +~29 * ~268435456 = Overflow +~29 * ~134217728 = Overflow +~28 * ~2147483648 = Overflow +~28 * ~1073741824 = Overflow +~28 * ~536870912 = Overflow +~28 * ~268435456 = Overflow +~28 * ~134217728 = Overflow +~27 * ~2147483648 = Overflow +~27 * ~1073741824 = Overflow +~27 * ~536870912 = Overflow +~27 * ~268435456 = Overflow +~27 * ~134217728 = Overflow +~26 * ~2147483648 = Overflow +~26 * ~1073741824 = Overflow +~26 * ~536870912 = Overflow +~26 * ~268435456 = Overflow +~26 * ~134217728 = Overflow +~25 * ~2147483648 = Overflow +~25 * ~1073741824 = Overflow +~25 * ~536870912 = Overflow +~25 * ~268435456 = Overflow +~25 * ~134217728 = Overflow +~24 * ~2147483648 = Overflow +~24 * ~1073741824 = Overflow +~24 * ~536870912 = Overflow +~24 * ~268435456 = Overflow +~24 * ~134217728 = Overflow +~23 * ~2147483648 = Overflow +~23 * ~1073741824 = Overflow +~23 * ~536870912 = Overflow +~23 * ~268435456 = Overflow +~23 * ~134217728 = Overflow +~22 * ~2147483648 = Overflow +~22 * ~1073741824 = Overflow +~22 * ~536870912 = Overflow +~22 * ~268435456 = Overflow +~22 * ~134217728 = Overflow +~21 * ~2147483648 = Overflow +~21 * ~1073741824 = Overflow +~21 * ~536870912 = Overflow +~21 * ~268435456 = Overflow +~21 * ~134217728 = Overflow +~20 * ~2147483648 = Overflow +~20 * ~1073741824 = Overflow +~20 * ~536870912 = Overflow +~20 * ~268435456 = Overflow +~20 * ~134217728 = Overflow +~19 * ~2147483648 = Overflow +~19 * ~1073741824 = Overflow +~19 * ~536870912 = Overflow +~19 * ~268435456 = Overflow +~19 * ~134217728 = Overflow +~18 * ~2147483648 = Overflow +~18 * ~1073741824 = Overflow +~18 * ~536870912 = Overflow +~18 * ~268435456 = Overflow +~18 * ~134217728 = Overflow +~17 * ~2147483648 = Overflow +~17 * ~1073741824 = Overflow +~17 * ~536870912 = Overflow +~17 * ~268435456 = Overflow +~17 * ~134217728 = Overflow +~16 * ~2147483648 = Overflow +~16 * ~1073741824 = Overflow +~16 * ~536870912 = Overflow +~16 * ~268435456 = Overflow +~16 * ~134217728 = Overflow +~15 * ~2147483648 = Overflow +~15 * ~1073741824 = Overflow +~15 * ~536870912 = Overflow +~15 * ~268435456 = Overflow +~15 * ~134217728 = 2013265920 +~14 * ~2147483648 = Overflow +~14 * ~1073741824 = Overflow +~14 * ~536870912 = Overflow +~14 * ~268435456 = Overflow +~14 * ~134217728 = 1879048192 +~13 * ~2147483648 = Overflow +~13 * ~1073741824 = Overflow +~13 * ~536870912 = Overflow +~13 * ~268435456 = Overflow +~13 * ~134217728 = 1744830464 +~12 * ~2147483648 = Overflow +~12 * ~1073741824 = Overflow +~12 * ~536870912 = Overflow +~12 * ~268435456 = Overflow +~12 * ~134217728 = 1610612736 +~11 * ~2147483648 = Overflow +~11 * ~1073741824 = Overflow +~11 * ~536870912 = Overflow +~11 * ~268435456 = Overflow +~11 * ~134217728 = 1476395008 +~10 * ~2147483648 = Overflow +~10 * ~1073741824 = Overflow +~10 * ~536870912 = Overflow +~10 * ~268435456 = Overflow +~10 * ~134217728 = 1342177280 +~9 * ~2147483648 = Overflow +~9 * ~1073741824 = Overflow +~9 * ~536870912 = Overflow +~9 * ~268435456 = Overflow +~9 * ~134217728 = 1207959552 +~8 * ~2147483648 = Overflow +~8 * ~1073741824 = Overflow +~8 * ~536870912 = Overflow +~8 * ~268435456 = Overflow +~8 * ~134217728 = 1073741824 +~7 * ~2147483648 = Overflow +~7 * ~1073741824 = Overflow +~7 * ~536870912 = Overflow +~7 * ~268435456 = 1879048192 +~7 * ~134217728 = 939524096 +~6 * ~2147483648 = Overflow +~6 * ~1073741824 = Overflow +~6 * ~536870912 = Overflow +~6 * ~268435456 = 1610612736 +~6 * ~134217728 = 805306368 +~5 * ~2147483648 = Overflow +~5 * ~1073741824 = Overflow +~5 * ~536870912 = Overflow +~5 * ~268435456 = 1342177280 +~5 * ~134217728 = 671088640 +~4 * ~2147483648 = Overflow +~4 * ~1073741824 = Overflow +~4 * ~536870912 = Overflow +~4 * ~268435456 = 1073741824 +~4 * ~134217728 = 536870912 +~3 * ~2147483648 = Overflow +~3 * ~1073741824 = Overflow +~3 * ~536870912 = 1610612736 +~3 * ~268435456 = 805306368 +~3 * ~134217728 = 402653184 +~2 * ~2147483648 = Overflow +~2 * ~1073741824 = Overflow +~2 * ~536870912 = 1073741824 +~2 * ~268435456 = 536870912 +~2 * ~134217728 = 268435456 +~1 * ~2147483648 = Overflow +~1 * ~1073741824 = 1073741824 +~1 * ~536870912 = 536870912 +~1 * ~268435456 = 268435456 +~1 * ~134217728 = 134217728 +0 * ~2147483648 = 0 +0 * ~1073741824 = 0 +0 * ~536870912 = 0 +0 * ~268435456 = 0 +0 * ~134217728 = 0 +1 * ~2147483648 = ~2147483648 +1 * ~1073741824 = ~1073741824 +1 * ~536870912 = ~536870912 +1 * ~268435456 = ~268435456 +1 * ~134217728 = ~134217728 +2 * ~2147483648 = Overflow +2 * ~1073741824 = ~2147483648 +2 * ~536870912 = ~1073741824 +2 * ~268435456 = ~536870912 +2 * ~134217728 = ~268435456 +3 * ~2147483648 = Overflow +3 * ~1073741824 = Overflow +3 * ~536870912 = ~1610612736 +3 * ~268435456 = ~805306368 +3 * ~134217728 = ~402653184 +4 * ~2147483648 = Overflow +4 * ~1073741824 = Overflow +4 * ~536870912 = ~2147483648 +4 * ~268435456 = ~1073741824 +4 * ~134217728 = ~536870912 +5 * ~2147483648 = Overflow +5 * ~1073741824 = Overflow +5 * ~536870912 = Overflow +5 * ~268435456 = ~1342177280 +5 * ~134217728 = ~671088640 +6 * ~2147483648 = Overflow +6 * ~1073741824 = Overflow +6 * ~536870912 = Overflow +6 * ~268435456 = ~1610612736 +6 * ~134217728 = ~805306368 +7 * ~2147483648 = Overflow +7 * ~1073741824 = Overflow +7 * ~536870912 = Overflow +7 * ~268435456 = ~1879048192 +7 * ~134217728 = ~939524096 +8 * ~2147483648 = Overflow +8 * ~1073741824 = Overflow +8 * ~536870912 = Overflow +8 * ~268435456 = ~2147483648 +8 * ~134217728 = ~1073741824 +9 * ~2147483648 = Overflow +9 * ~1073741824 = Overflow +9 * ~536870912 = Overflow +9 * ~268435456 = Overflow +9 * ~134217728 = ~1207959552 +10 * ~2147483648 = Overflow +10 * ~1073741824 = Overflow +10 * ~536870912 = Overflow +10 * ~268435456 = Overflow +10 * ~134217728 = ~1342177280 +11 * ~2147483648 = Overflow +11 * ~1073741824 = Overflow +11 * ~536870912 = Overflow +11 * ~268435456 = Overflow +11 * ~134217728 = ~1476395008 +12 * ~2147483648 = Overflow +12 * ~1073741824 = Overflow +12 * ~536870912 = Overflow +12 * ~268435456 = Overflow +12 * ~134217728 = ~1610612736 +13 * ~2147483648 = Overflow +13 * ~1073741824 = Overflow +13 * ~536870912 = Overflow +13 * ~268435456 = Overflow +13 * ~134217728 = ~1744830464 +14 * ~2147483648 = Overflow +14 * ~1073741824 = Overflow +14 * ~536870912 = Overflow +14 * ~268435456 = Overflow +14 * ~134217728 = ~1879048192 +15 * ~2147483648 = Overflow +15 * ~1073741824 = Overflow +15 * ~536870912 = Overflow +15 * ~268435456 = Overflow +15 * ~134217728 = ~2013265920 +16 * ~2147483648 = Overflow +16 * ~1073741824 = Overflow +16 * ~536870912 = Overflow +16 * ~268435456 = Overflow +16 * ~134217728 = ~2147483648 +17 * ~2147483648 = Overflow +17 * ~1073741824 = Overflow +17 * ~536870912 = Overflow +17 * ~268435456 = Overflow +17 * ~134217728 = Overflow +18 * ~2147483648 = Overflow +18 * ~1073741824 = Overflow +18 * ~536870912 = Overflow +18 * ~268435456 = Overflow +18 * ~134217728 = Overflow +19 * ~2147483648 = Overflow +19 * ~1073741824 = Overflow +19 * ~536870912 = Overflow +19 * ~268435456 = Overflow +19 * ~134217728 = Overflow +20 * ~2147483648 = Overflow +20 * ~1073741824 = Overflow +20 * ~536870912 = Overflow +20 * ~268435456 = Overflow +20 * ~134217728 = Overflow +21 * ~2147483648 = Overflow +21 * ~1073741824 = Overflow +21 * ~536870912 = Overflow +21 * ~268435456 = Overflow +21 * ~134217728 = Overflow +22 * ~2147483648 = Overflow +22 * ~1073741824 = Overflow +22 * ~536870912 = Overflow +22 * ~268435456 = Overflow +22 * ~134217728 = Overflow +23 * ~2147483648 = Overflow +23 * ~1073741824 = Overflow +23 * ~536870912 = Overflow +23 * ~268435456 = Overflow +23 * ~134217728 = Overflow +24 * ~2147483648 = Overflow +24 * ~1073741824 = Overflow +24 * ~536870912 = Overflow +24 * ~268435456 = Overflow +24 * ~134217728 = Overflow +25 * ~2147483648 = Overflow +25 * ~1073741824 = Overflow +25 * ~536870912 = Overflow +25 * ~268435456 = Overflow +25 * ~134217728 = Overflow +26 * ~2147483648 = Overflow +26 * ~1073741824 = Overflow +26 * ~536870912 = Overflow +26 * ~268435456 = Overflow +26 * ~134217728 = Overflow +27 * ~2147483648 = Overflow +27 * ~1073741824 = Overflow +27 * ~536870912 = Overflow +27 * ~268435456 = Overflow +27 * ~134217728 = Overflow +28 * ~2147483648 = Overflow +28 * ~1073741824 = Overflow +28 * ~536870912 = Overflow +28 * ~268435456 = Overflow +28 * ~134217728 = Overflow +29 * ~2147483648 = Overflow +29 * ~1073741824 = Overflow +29 * ~536870912 = Overflow +29 * ~268435456 = Overflow +29 * ~134217728 = Overflow +30 * ~2147483648 = Overflow +30 * ~1073741824 = Overflow +30 * ~536870912 = Overflow +30 * ~268435456 = Overflow +30 * ~134217728 = Overflow +31 * ~2147483648 = Overflow +31 * ~1073741824 = Overflow +31 * ~536870912 = Overflow +31 * ~268435456 = Overflow +31 * ~134217728 = Overflow +32 * ~2147483648 = Overflow +32 * ~1073741824 = Overflow +32 * ~536870912 = Overflow +32 * ~268435456 = Overflow +32 * ~134217728 = Overflow +~2147483648 * 1 = ~2147483648 +~2147483648 * 2 = Overflow +~2147483648 * 4 = Overflow +~2147483648 * 8 = Overflow +~2147483648 * 16 = Overflow +~1073741824 * 1 = ~1073741824 +~1073741824 * 2 = ~2147483648 +~1073741824 * 4 = Overflow +~1073741824 * 8 = Overflow +~1073741824 * 16 = Overflow +~536870912 * 1 = ~536870912 +~536870912 * 2 = ~1073741824 +~536870912 * 4 = ~2147483648 +~536870912 * 8 = Overflow +~536870912 * 16 = Overflow +~268435456 * 1 = ~268435456 +~268435456 * 2 = ~536870912 +~268435456 * 4 = ~1073741824 +~268435456 * 8 = ~2147483648 +~268435456 * 16 = Overflow +~134217728 * 1 = ~134217728 +~134217728 * 2 = ~268435456 +~134217728 * 4 = ~536870912 +~134217728 * 8 = ~1073741824 +~134217728 * 16 = ~2147483648 +~67108864 * 1 = ~67108864 +~67108864 * 2 = ~134217728 +~67108864 * 4 = ~268435456 +~67108864 * 8 = ~536870912 +~67108864 * 16 = ~1073741824 +~4 * 1 = ~4 +~4 * 2 = ~8 +~4 * 4 = ~16 +~4 * 8 = ~32 +~4 * 16 = ~64 +~3 * 1 = ~3 +~3 * 2 = ~6 +~3 * 4 = ~12 +~3 * 8 = ~24 +~3 * 16 = ~48 +~2 * 1 = ~2 +~2 * 2 = ~4 +~2 * 4 = ~8 +~2 * 8 = ~16 +~2 * 16 = ~32 +~1 * 1 = ~1 +~1 * 2 = ~2 +~1 * 4 = ~4 +~1 * 8 = ~8 +~1 * 16 = ~16 +0 * 1 = 0 +0 * 2 = 0 +0 * 4 = 0 +0 * 8 = 0 +0 * 16 = 0 +1 * 1 = 1 +1 * 2 = 2 +1 * 4 = 4 +1 * 8 = 8 +1 * 16 = 16 +2 * 1 = 2 +2 * 2 = 4 +2 * 4 = 8 +2 * 8 = 16 +2 * 16 = 32 +3 * 1 = 3 +3 * 2 = 6 +3 * 4 = 12 +3 * 8 = 24 +3 * 16 = 48 +4 * 1 = 4 +4 * 2 = 8 +4 * 4 = 16 +4 * 8 = 32 +4 * 16 = 64 +33554432 * 1 = 33554432 +33554432 * 2 = 67108864 +33554432 * 4 = 134217728 +33554432 * 8 = 268435456 +33554432 * 16 = 536870912 +67108864 * 1 = 67108864 +67108864 * 2 = 134217728 +67108864 * 4 = 268435456 +67108864 * 8 = 536870912 +67108864 * 16 = 1073741824 +134217728 * 1 = 134217728 +134217728 * 2 = 268435456 +134217728 * 4 = 536870912 +134217728 * 8 = 1073741824 +134217728 * 16 = Overflow +268435456 * 1 = 268435456 +268435456 * 2 = 536870912 +268435456 * 4 = 1073741824 +268435456 * 8 = Overflow +268435456 * 16 = Overflow +536870912 * 1 = 536870912 +536870912 * 2 = 1073741824 +536870912 * 4 = Overflow +536870912 * 8 = Overflow +536870912 * 16 = Overflow +1073741824 * 1 = 1073741824 +1073741824 * 2 = Overflow +1073741824 * 4 = Overflow +1073741824 * 8 = Overflow +1073741824 * 16 = Overflow +~2147483648 * ~1 = Overflow +~2147483648 * ~2 = Overflow +~2147483648 * ~4 = Overflow +~2147483648 * ~8 = Overflow +~2147483648 * ~16 = Overflow +~1073741824 * ~1 = 1073741824 +~1073741824 * ~2 = Overflow +~1073741824 * ~4 = Overflow +~1073741824 * ~8 = Overflow +~1073741824 * ~16 = Overflow +~536870912 * ~1 = 536870912 +~536870912 * ~2 = 1073741824 +~536870912 * ~4 = Overflow +~536870912 * ~8 = Overflow +~536870912 * ~16 = Overflow +~268435456 * ~1 = 268435456 +~268435456 * ~2 = 536870912 +~268435456 * ~4 = 1073741824 +~268435456 * ~8 = Overflow +~268435456 * ~16 = Overflow +~134217728 * ~1 = 134217728 +~134217728 * ~2 = 268435456 +~134217728 * ~4 = 536870912 +~134217728 * ~8 = 1073741824 +~134217728 * ~16 = Overflow +~67108864 * ~1 = 67108864 +~67108864 * ~2 = 134217728 +~67108864 * ~4 = 268435456 +~67108864 * ~8 = 536870912 +~67108864 * ~16 = 1073741824 +~4 * ~1 = 4 +~4 * ~2 = 8 +~4 * ~4 = 16 +~4 * ~8 = 32 +~4 * ~16 = 64 +~3 * ~1 = 3 +~3 * ~2 = 6 +~3 * ~4 = 12 +~3 * ~8 = 24 +~3 * ~16 = 48 +~2 * ~1 = 2 +~2 * ~2 = 4 +~2 * ~4 = 8 +~2 * ~8 = 16 +~2 * ~16 = 32 +~1 * ~1 = 1 +~1 * ~2 = 2 +~1 * ~4 = 4 +~1 * ~8 = 8 +~1 * ~16 = 16 +0 * ~1 = 0 +0 * ~2 = 0 +0 * ~4 = 0 +0 * ~8 = 0 +0 * ~16 = 0 +1 * ~1 = ~1 +1 * ~2 = ~2 +1 * ~4 = ~4 +1 * ~8 = ~8 +1 * ~16 = ~16 +2 * ~1 = ~2 +2 * ~2 = ~4 +2 * ~4 = ~8 +2 * ~8 = ~16 +2 * ~16 = ~32 +3 * ~1 = ~3 +3 * ~2 = ~6 +3 * ~4 = ~12 +3 * ~8 = ~24 +3 * ~16 = ~48 +4 * ~1 = ~4 +4 * ~2 = ~8 +4 * ~4 = ~16 +4 * ~8 = ~32 +4 * ~16 = ~64 +33554432 * ~1 = ~33554432 +33554432 * ~2 = ~67108864 +33554432 * ~4 = ~134217728 +33554432 * ~8 = ~268435456 +33554432 * ~16 = ~536870912 +67108864 * ~1 = ~67108864 +67108864 * ~2 = ~134217728 +67108864 * ~4 = ~268435456 +67108864 * ~8 = ~536870912 +67108864 * ~16 = ~1073741824 +134217728 * ~1 = ~134217728 +134217728 * ~2 = ~268435456 +134217728 * ~4 = ~536870912 +134217728 * ~8 = ~1073741824 +134217728 * ~16 = ~2147483648 +268435456 * ~1 = ~268435456 +268435456 * ~2 = ~536870912 +268435456 * ~4 = ~1073741824 +268435456 * ~8 = ~2147483648 +268435456 * ~16 = Overflow +536870912 * ~1 = ~536870912 +536870912 * ~2 = ~1073741824 +536870912 * ~4 = ~2147483648 +536870912 * ~8 = Overflow +536870912 * ~16 = Overflow +1073741824 * ~1 = ~1073741824 +1073741824 * ~2 = ~2147483648 +1073741824 * ~4 = Overflow +1073741824 * ~8 = Overflow +1073741824 * ~16 = Overflow +~32 * 4611686018427387904 = Overflow +~32 * 2305843009213693952 = Overflow +~32 * 1152921504606846976 = Overflow +~32 * 576460752303423488 = Overflow +~32 * 288230376151711744 = ~9223372036854775808 +~31 * 4611686018427387904 = Overflow +~31 * 2305843009213693952 = Overflow +~31 * 1152921504606846976 = Overflow +~31 * 576460752303423488 = Overflow +~31 * 288230376151711744 = ~8935141660703064064 +~30 * 4611686018427387904 = Overflow +~30 * 2305843009213693952 = Overflow +~30 * 1152921504606846976 = Overflow +~30 * 576460752303423488 = Overflow +~30 * 288230376151711744 = ~8646911284551352320 +~29 * 4611686018427387904 = Overflow +~29 * 2305843009213693952 = Overflow +~29 * 1152921504606846976 = Overflow +~29 * 576460752303423488 = Overflow +~29 * 288230376151711744 = ~8358680908399640576 +~28 * 4611686018427387904 = Overflow +~28 * 2305843009213693952 = Overflow +~28 * 1152921504606846976 = Overflow +~28 * 576460752303423488 = Overflow +~28 * 288230376151711744 = ~8070450532247928832 +~27 * 4611686018427387904 = Overflow +~27 * 2305843009213693952 = Overflow +~27 * 1152921504606846976 = Overflow +~27 * 576460752303423488 = Overflow +~27 * 288230376151711744 = ~7782220156096217088 +~26 * 4611686018427387904 = Overflow +~26 * 2305843009213693952 = Overflow +~26 * 1152921504606846976 = Overflow +~26 * 576460752303423488 = Overflow +~26 * 288230376151711744 = ~7493989779944505344 +~25 * 4611686018427387904 = Overflow +~25 * 2305843009213693952 = Overflow +~25 * 1152921504606846976 = Overflow +~25 * 576460752303423488 = Overflow +~25 * 288230376151711744 = ~7205759403792793600 +~24 * 4611686018427387904 = Overflow +~24 * 2305843009213693952 = Overflow +~24 * 1152921504606846976 = Overflow +~24 * 576460752303423488 = Overflow +~24 * 288230376151711744 = ~6917529027641081856 +~23 * 4611686018427387904 = Overflow +~23 * 2305843009213693952 = Overflow +~23 * 1152921504606846976 = Overflow +~23 * 576460752303423488 = Overflow +~23 * 288230376151711744 = ~6629298651489370112 +~22 * 4611686018427387904 = Overflow +~22 * 2305843009213693952 = Overflow +~22 * 1152921504606846976 = Overflow +~22 * 576460752303423488 = Overflow +~22 * 288230376151711744 = ~6341068275337658368 +~21 * 4611686018427387904 = Overflow +~21 * 2305843009213693952 = Overflow +~21 * 1152921504606846976 = Overflow +~21 * 576460752303423488 = Overflow +~21 * 288230376151711744 = ~6052837899185946624 +~20 * 4611686018427387904 = Overflow +~20 * 2305843009213693952 = Overflow +~20 * 1152921504606846976 = Overflow +~20 * 576460752303423488 = Overflow +~20 * 288230376151711744 = ~5764607523034234880 +~19 * 4611686018427387904 = Overflow +~19 * 2305843009213693952 = Overflow +~19 * 1152921504606846976 = Overflow +~19 * 576460752303423488 = Overflow +~19 * 288230376151711744 = ~5476377146882523136 +~18 * 4611686018427387904 = Overflow +~18 * 2305843009213693952 = Overflow +~18 * 1152921504606846976 = Overflow +~18 * 576460752303423488 = Overflow +~18 * 288230376151711744 = ~5188146770730811392 +~17 * 4611686018427387904 = Overflow +~17 * 2305843009213693952 = Overflow +~17 * 1152921504606846976 = Overflow +~17 * 576460752303423488 = Overflow +~17 * 288230376151711744 = ~4899916394579099648 +~16 * 4611686018427387904 = Overflow +~16 * 2305843009213693952 = Overflow +~16 * 1152921504606846976 = Overflow +~16 * 576460752303423488 = ~9223372036854775808 +~16 * 288230376151711744 = ~4611686018427387904 +~15 * 4611686018427387904 = Overflow +~15 * 2305843009213693952 = Overflow +~15 * 1152921504606846976 = Overflow +~15 * 576460752303423488 = ~8646911284551352320 +~15 * 288230376151711744 = ~4323455642275676160 +~14 * 4611686018427387904 = Overflow +~14 * 2305843009213693952 = Overflow +~14 * 1152921504606846976 = Overflow +~14 * 576460752303423488 = ~8070450532247928832 +~14 * 288230376151711744 = ~4035225266123964416 +~13 * 4611686018427387904 = Overflow +~13 * 2305843009213693952 = Overflow +~13 * 1152921504606846976 = Overflow +~13 * 576460752303423488 = ~7493989779944505344 +~13 * 288230376151711744 = ~3746994889972252672 +~12 * 4611686018427387904 = Overflow +~12 * 2305843009213693952 = Overflow +~12 * 1152921504606846976 = Overflow +~12 * 576460752303423488 = ~6917529027641081856 +~12 * 288230376151711744 = ~3458764513820540928 +~11 * 4611686018427387904 = Overflow +~11 * 2305843009213693952 = Overflow +~11 * 1152921504606846976 = Overflow +~11 * 576460752303423488 = ~6341068275337658368 +~11 * 288230376151711744 = ~3170534137668829184 +~10 * 4611686018427387904 = Overflow +~10 * 2305843009213693952 = Overflow +~10 * 1152921504606846976 = Overflow +~10 * 576460752303423488 = ~5764607523034234880 +~10 * 288230376151711744 = ~2882303761517117440 +~9 * 4611686018427387904 = Overflow +~9 * 2305843009213693952 = Overflow +~9 * 1152921504606846976 = Overflow +~9 * 576460752303423488 = ~5188146770730811392 +~9 * 288230376151711744 = ~2594073385365405696 +~8 * 4611686018427387904 = Overflow +~8 * 2305843009213693952 = Overflow +~8 * 1152921504606846976 = ~9223372036854775808 +~8 * 576460752303423488 = ~4611686018427387904 +~8 * 288230376151711744 = ~2305843009213693952 +~7 * 4611686018427387904 = Overflow +~7 * 2305843009213693952 = Overflow +~7 * 1152921504606846976 = ~8070450532247928832 +~7 * 576460752303423488 = ~4035225266123964416 +~7 * 288230376151711744 = ~2017612633061982208 +~6 * 4611686018427387904 = Overflow +~6 * 2305843009213693952 = Overflow +~6 * 1152921504606846976 = ~6917529027641081856 +~6 * 576460752303423488 = ~3458764513820540928 +~6 * 288230376151711744 = ~1729382256910270464 +~5 * 4611686018427387904 = Overflow +~5 * 2305843009213693952 = Overflow +~5 * 1152921504606846976 = ~5764607523034234880 +~5 * 576460752303423488 = ~2882303761517117440 +~5 * 288230376151711744 = ~1441151880758558720 +~4 * 4611686018427387904 = Overflow +~4 * 2305843009213693952 = ~9223372036854775808 +~4 * 1152921504606846976 = ~4611686018427387904 +~4 * 576460752303423488 = ~2305843009213693952 +~4 * 288230376151711744 = ~1152921504606846976 +~3 * 4611686018427387904 = Overflow +~3 * 2305843009213693952 = ~6917529027641081856 +~3 * 1152921504606846976 = ~3458764513820540928 +~3 * 576460752303423488 = ~1729382256910270464 +~3 * 288230376151711744 = ~864691128455135232 +~2 * 4611686018427387904 = ~9223372036854775808 +~2 * 2305843009213693952 = ~4611686018427387904 +~2 * 1152921504606846976 = ~2305843009213693952 +~2 * 576460752303423488 = ~1152921504606846976 +~2 * 288230376151711744 = ~576460752303423488 +~1 * 4611686018427387904 = ~4611686018427387904 +~1 * 2305843009213693952 = ~2305843009213693952 +~1 * 1152921504606846976 = ~1152921504606846976 +~1 * 576460752303423488 = ~576460752303423488 +~1 * 288230376151711744 = ~288230376151711744 +0 * 4611686018427387904 = 0 +0 * 2305843009213693952 = 0 +0 * 1152921504606846976 = 0 +0 * 576460752303423488 = 0 +0 * 288230376151711744 = 0 +1 * 4611686018427387904 = 4611686018427387904 +1 * 2305843009213693952 = 2305843009213693952 +1 * 1152921504606846976 = 1152921504606846976 +1 * 576460752303423488 = 576460752303423488 +1 * 288230376151711744 = 288230376151711744 +2 * 4611686018427387904 = Overflow +2 * 2305843009213693952 = 4611686018427387904 +2 * 1152921504606846976 = 2305843009213693952 +2 * 576460752303423488 = 1152921504606846976 +2 * 288230376151711744 = 576460752303423488 +3 * 4611686018427387904 = Overflow +3 * 2305843009213693952 = 6917529027641081856 +3 * 1152921504606846976 = 3458764513820540928 +3 * 576460752303423488 = 1729382256910270464 +3 * 288230376151711744 = 864691128455135232 +4 * 4611686018427387904 = Overflow +4 * 2305843009213693952 = Overflow +4 * 1152921504606846976 = 4611686018427387904 +4 * 576460752303423488 = 2305843009213693952 +4 * 288230376151711744 = 1152921504606846976 +5 * 4611686018427387904 = Overflow +5 * 2305843009213693952 = Overflow +5 * 1152921504606846976 = 5764607523034234880 +5 * 576460752303423488 = 2882303761517117440 +5 * 288230376151711744 = 1441151880758558720 +6 * 4611686018427387904 = Overflow +6 * 2305843009213693952 = Overflow +6 * 1152921504606846976 = 6917529027641081856 +6 * 576460752303423488 = 3458764513820540928 +6 * 288230376151711744 = 1729382256910270464 +7 * 4611686018427387904 = Overflow +7 * 2305843009213693952 = Overflow +7 * 1152921504606846976 = 8070450532247928832 +7 * 576460752303423488 = 4035225266123964416 +7 * 288230376151711744 = 2017612633061982208 +8 * 4611686018427387904 = Overflow +8 * 2305843009213693952 = Overflow +8 * 1152921504606846976 = Overflow +8 * 576460752303423488 = 4611686018427387904 +8 * 288230376151711744 = 2305843009213693952 +9 * 4611686018427387904 = Overflow +9 * 2305843009213693952 = Overflow +9 * 1152921504606846976 = Overflow +9 * 576460752303423488 = 5188146770730811392 +9 * 288230376151711744 = 2594073385365405696 +10 * 4611686018427387904 = Overflow +10 * 2305843009213693952 = Overflow +10 * 1152921504606846976 = Overflow +10 * 576460752303423488 = 5764607523034234880 +10 * 288230376151711744 = 2882303761517117440 +11 * 4611686018427387904 = Overflow +11 * 2305843009213693952 = Overflow +11 * 1152921504606846976 = Overflow +11 * 576460752303423488 = 6341068275337658368 +11 * 288230376151711744 = 3170534137668829184 +12 * 4611686018427387904 = Overflow +12 * 2305843009213693952 = Overflow +12 * 1152921504606846976 = Overflow +12 * 576460752303423488 = 6917529027641081856 +12 * 288230376151711744 = 3458764513820540928 +13 * 4611686018427387904 = Overflow +13 * 2305843009213693952 = Overflow +13 * 1152921504606846976 = Overflow +13 * 576460752303423488 = 7493989779944505344 +13 * 288230376151711744 = 3746994889972252672 +14 * 4611686018427387904 = Overflow +14 * 2305843009213693952 = Overflow +14 * 1152921504606846976 = Overflow +14 * 576460752303423488 = 8070450532247928832 +14 * 288230376151711744 = 4035225266123964416 +15 * 4611686018427387904 = Overflow +15 * 2305843009213693952 = Overflow +15 * 1152921504606846976 = Overflow +15 * 576460752303423488 = 8646911284551352320 +15 * 288230376151711744 = 4323455642275676160 +16 * 4611686018427387904 = Overflow +16 * 2305843009213693952 = Overflow +16 * 1152921504606846976 = Overflow +16 * 576460752303423488 = Overflow +16 * 288230376151711744 = 4611686018427387904 +17 * 4611686018427387904 = Overflow +17 * 2305843009213693952 = Overflow +17 * 1152921504606846976 = Overflow +17 * 576460752303423488 = Overflow +17 * 288230376151711744 = 4899916394579099648 +18 * 4611686018427387904 = Overflow +18 * 2305843009213693952 = Overflow +18 * 1152921504606846976 = Overflow +18 * 576460752303423488 = Overflow +18 * 288230376151711744 = 5188146770730811392 +19 * 4611686018427387904 = Overflow +19 * 2305843009213693952 = Overflow +19 * 1152921504606846976 = Overflow +19 * 576460752303423488 = Overflow +19 * 288230376151711744 = 5476377146882523136 +20 * 4611686018427387904 = Overflow +20 * 2305843009213693952 = Overflow +20 * 1152921504606846976 = Overflow +20 * 576460752303423488 = Overflow +20 * 288230376151711744 = 5764607523034234880 +21 * 4611686018427387904 = Overflow +21 * 2305843009213693952 = Overflow +21 * 1152921504606846976 = Overflow +21 * 576460752303423488 = Overflow +21 * 288230376151711744 = 6052837899185946624 +22 * 4611686018427387904 = Overflow +22 * 2305843009213693952 = Overflow +22 * 1152921504606846976 = Overflow +22 * 576460752303423488 = Overflow +22 * 288230376151711744 = 6341068275337658368 +23 * 4611686018427387904 = Overflow +23 * 2305843009213693952 = Overflow +23 * 1152921504606846976 = Overflow +23 * 576460752303423488 = Overflow +23 * 288230376151711744 = 6629298651489370112 +24 * 4611686018427387904 = Overflow +24 * 2305843009213693952 = Overflow +24 * 1152921504606846976 = Overflow +24 * 576460752303423488 = Overflow +24 * 288230376151711744 = 6917529027641081856 +25 * 4611686018427387904 = Overflow +25 * 2305843009213693952 = Overflow +25 * 1152921504606846976 = Overflow +25 * 576460752303423488 = Overflow +25 * 288230376151711744 = 7205759403792793600 +26 * 4611686018427387904 = Overflow +26 * 2305843009213693952 = Overflow +26 * 1152921504606846976 = Overflow +26 * 576460752303423488 = Overflow +26 * 288230376151711744 = 7493989779944505344 +27 * 4611686018427387904 = Overflow +27 * 2305843009213693952 = Overflow +27 * 1152921504606846976 = Overflow +27 * 576460752303423488 = Overflow +27 * 288230376151711744 = 7782220156096217088 +28 * 4611686018427387904 = Overflow +28 * 2305843009213693952 = Overflow +28 * 1152921504606846976 = Overflow +28 * 576460752303423488 = Overflow +28 * 288230376151711744 = 8070450532247928832 +29 * 4611686018427387904 = Overflow +29 * 2305843009213693952 = Overflow +29 * 1152921504606846976 = Overflow +29 * 576460752303423488 = Overflow +29 * 288230376151711744 = 8358680908399640576 +30 * 4611686018427387904 = Overflow +30 * 2305843009213693952 = Overflow +30 * 1152921504606846976 = Overflow +30 * 576460752303423488 = Overflow +30 * 288230376151711744 = 8646911284551352320 +31 * 4611686018427387904 = Overflow +31 * 2305843009213693952 = Overflow +31 * 1152921504606846976 = Overflow +31 * 576460752303423488 = Overflow +31 * 288230376151711744 = 8935141660703064064 +32 * 4611686018427387904 = Overflow +32 * 2305843009213693952 = Overflow +32 * 1152921504606846976 = Overflow +32 * 576460752303423488 = Overflow +32 * 288230376151711744 = Overflow +~32 * ~9223372036854775808 = Overflow +~32 * ~4611686018427387904 = Overflow +~32 * ~2305843009213693952 = Overflow +~32 * ~1152921504606846976 = Overflow +~32 * ~576460752303423488 = Overflow +~31 * ~9223372036854775808 = Overflow +~31 * ~4611686018427387904 = Overflow +~31 * ~2305843009213693952 = Overflow +~31 * ~1152921504606846976 = Overflow +~31 * ~576460752303423488 = Overflow +~30 * ~9223372036854775808 = Overflow +~30 * ~4611686018427387904 = Overflow +~30 * ~2305843009213693952 = Overflow +~30 * ~1152921504606846976 = Overflow +~30 * ~576460752303423488 = Overflow +~29 * ~9223372036854775808 = Overflow +~29 * ~4611686018427387904 = Overflow +~29 * ~2305843009213693952 = Overflow +~29 * ~1152921504606846976 = Overflow +~29 * ~576460752303423488 = Overflow +~28 * ~9223372036854775808 = Overflow +~28 * ~4611686018427387904 = Overflow +~28 * ~2305843009213693952 = Overflow +~28 * ~1152921504606846976 = Overflow +~28 * ~576460752303423488 = Overflow +~27 * ~9223372036854775808 = Overflow +~27 * ~4611686018427387904 = Overflow +~27 * ~2305843009213693952 = Overflow +~27 * ~1152921504606846976 = Overflow +~27 * ~576460752303423488 = Overflow +~26 * ~9223372036854775808 = Overflow +~26 * ~4611686018427387904 = Overflow +~26 * ~2305843009213693952 = Overflow +~26 * ~1152921504606846976 = Overflow +~26 * ~576460752303423488 = Overflow +~25 * ~9223372036854775808 = Overflow +~25 * ~4611686018427387904 = Overflow +~25 * ~2305843009213693952 = Overflow +~25 * ~1152921504606846976 = Overflow +~25 * ~576460752303423488 = Overflow +~24 * ~9223372036854775808 = Overflow +~24 * ~4611686018427387904 = Overflow +~24 * ~2305843009213693952 = Overflow +~24 * ~1152921504606846976 = Overflow +~24 * ~576460752303423488 = Overflow +~23 * ~9223372036854775808 = Overflow +~23 * ~4611686018427387904 = Overflow +~23 * ~2305843009213693952 = Overflow +~23 * ~1152921504606846976 = Overflow +~23 * ~576460752303423488 = Overflow +~22 * ~9223372036854775808 = Overflow +~22 * ~4611686018427387904 = Overflow +~22 * ~2305843009213693952 = Overflow +~22 * ~1152921504606846976 = Overflow +~22 * ~576460752303423488 = Overflow +~21 * ~9223372036854775808 = Overflow +~21 * ~4611686018427387904 = Overflow +~21 * ~2305843009213693952 = Overflow +~21 * ~1152921504606846976 = Overflow +~21 * ~576460752303423488 = Overflow +~20 * ~9223372036854775808 = Overflow +~20 * ~4611686018427387904 = Overflow +~20 * ~2305843009213693952 = Overflow +~20 * ~1152921504606846976 = Overflow +~20 * ~576460752303423488 = Overflow +~19 * ~9223372036854775808 = Overflow +~19 * ~4611686018427387904 = Overflow +~19 * ~2305843009213693952 = Overflow +~19 * ~1152921504606846976 = Overflow +~19 * ~576460752303423488 = Overflow +~18 * ~9223372036854775808 = Overflow +~18 * ~4611686018427387904 = Overflow +~18 * ~2305843009213693952 = Overflow +~18 * ~1152921504606846976 = Overflow +~18 * ~576460752303423488 = Overflow +~17 * ~9223372036854775808 = Overflow +~17 * ~4611686018427387904 = Overflow +~17 * ~2305843009213693952 = Overflow +~17 * ~1152921504606846976 = Overflow +~17 * ~576460752303423488 = Overflow +~16 * ~9223372036854775808 = Overflow +~16 * ~4611686018427387904 = Overflow +~16 * ~2305843009213693952 = Overflow +~16 * ~1152921504606846976 = Overflow +~16 * ~576460752303423488 = Overflow +~15 * ~9223372036854775808 = Overflow +~15 * ~4611686018427387904 = Overflow +~15 * ~2305843009213693952 = Overflow +~15 * ~1152921504606846976 = Overflow +~15 * ~576460752303423488 = 8646911284551352320 +~14 * ~9223372036854775808 = Overflow +~14 * ~4611686018427387904 = Overflow +~14 * ~2305843009213693952 = Overflow +~14 * ~1152921504606846976 = Overflow +~14 * ~576460752303423488 = 8070450532247928832 +~13 * ~9223372036854775808 = Overflow +~13 * ~4611686018427387904 = Overflow +~13 * ~2305843009213693952 = Overflow +~13 * ~1152921504606846976 = Overflow +~13 * ~576460752303423488 = 7493989779944505344 +~12 * ~9223372036854775808 = Overflow +~12 * ~4611686018427387904 = Overflow +~12 * ~2305843009213693952 = Overflow +~12 * ~1152921504606846976 = Overflow +~12 * ~576460752303423488 = 6917529027641081856 +~11 * ~9223372036854775808 = Overflow +~11 * ~4611686018427387904 = Overflow +~11 * ~2305843009213693952 = Overflow +~11 * ~1152921504606846976 = Overflow +~11 * ~576460752303423488 = 6341068275337658368 +~10 * ~9223372036854775808 = Overflow +~10 * ~4611686018427387904 = Overflow +~10 * ~2305843009213693952 = Overflow +~10 * ~1152921504606846976 = Overflow +~10 * ~576460752303423488 = 5764607523034234880 +~9 * ~9223372036854775808 = Overflow +~9 * ~4611686018427387904 = Overflow +~9 * ~2305843009213693952 = Overflow +~9 * ~1152921504606846976 = Overflow +~9 * ~576460752303423488 = 5188146770730811392 +~8 * ~9223372036854775808 = Overflow +~8 * ~4611686018427387904 = Overflow +~8 * ~2305843009213693952 = Overflow +~8 * ~1152921504606846976 = Overflow +~8 * ~576460752303423488 = 4611686018427387904 +~7 * ~9223372036854775808 = Overflow +~7 * ~4611686018427387904 = Overflow +~7 * ~2305843009213693952 = Overflow +~7 * ~1152921504606846976 = 8070450532247928832 +~7 * ~576460752303423488 = 4035225266123964416 +~6 * ~9223372036854775808 = Overflow +~6 * ~4611686018427387904 = Overflow +~6 * ~2305843009213693952 = Overflow +~6 * ~1152921504606846976 = 6917529027641081856 +~6 * ~576460752303423488 = 3458764513820540928 +~5 * ~9223372036854775808 = Overflow +~5 * ~4611686018427387904 = Overflow +~5 * ~2305843009213693952 = Overflow +~5 * ~1152921504606846976 = 5764607523034234880 +~5 * ~576460752303423488 = 2882303761517117440 +~4 * ~9223372036854775808 = Overflow +~4 * ~4611686018427387904 = Overflow +~4 * ~2305843009213693952 = Overflow +~4 * ~1152921504606846976 = 4611686018427387904 +~4 * ~576460752303423488 = 2305843009213693952 +~3 * ~9223372036854775808 = Overflow +~3 * ~4611686018427387904 = Overflow +~3 * ~2305843009213693952 = 6917529027641081856 +~3 * ~1152921504606846976 = 3458764513820540928 +~3 * ~576460752303423488 = 1729382256910270464 +~2 * ~9223372036854775808 = Overflow +~2 * ~4611686018427387904 = Overflow +~2 * ~2305843009213693952 = 4611686018427387904 +~2 * ~1152921504606846976 = 2305843009213693952 +~2 * ~576460752303423488 = 1152921504606846976 +~1 * ~9223372036854775808 = Overflow +~1 * ~4611686018427387904 = 4611686018427387904 +~1 * ~2305843009213693952 = 2305843009213693952 +~1 * ~1152921504606846976 = 1152921504606846976 +~1 * ~576460752303423488 = 576460752303423488 +0 * ~9223372036854775808 = 0 +0 * ~4611686018427387904 = 0 +0 * ~2305843009213693952 = 0 +0 * ~1152921504606846976 = 0 +0 * ~576460752303423488 = 0 +1 * ~9223372036854775808 = ~9223372036854775808 +1 * ~4611686018427387904 = ~4611686018427387904 +1 * ~2305843009213693952 = ~2305843009213693952 +1 * ~1152921504606846976 = ~1152921504606846976 +1 * ~576460752303423488 = ~576460752303423488 +2 * ~9223372036854775808 = Overflow +2 * ~4611686018427387904 = ~9223372036854775808 +2 * ~2305843009213693952 = ~4611686018427387904 +2 * ~1152921504606846976 = ~2305843009213693952 +2 * ~576460752303423488 = ~1152921504606846976 +3 * ~9223372036854775808 = Overflow +3 * ~4611686018427387904 = Overflow +3 * ~2305843009213693952 = ~6917529027641081856 +3 * ~1152921504606846976 = ~3458764513820540928 +3 * ~576460752303423488 = ~1729382256910270464 +4 * ~9223372036854775808 = Overflow +4 * ~4611686018427387904 = Overflow +4 * ~2305843009213693952 = ~9223372036854775808 +4 * ~1152921504606846976 = ~4611686018427387904 +4 * ~576460752303423488 = ~2305843009213693952 +5 * ~9223372036854775808 = Overflow +5 * ~4611686018427387904 = Overflow +5 * ~2305843009213693952 = Overflow +5 * ~1152921504606846976 = ~5764607523034234880 +5 * ~576460752303423488 = ~2882303761517117440 +6 * ~9223372036854775808 = Overflow +6 * ~4611686018427387904 = Overflow +6 * ~2305843009213693952 = Overflow +6 * ~1152921504606846976 = ~6917529027641081856 +6 * ~576460752303423488 = ~3458764513820540928 +7 * ~9223372036854775808 = Overflow +7 * ~4611686018427387904 = Overflow +7 * ~2305843009213693952 = Overflow +7 * ~1152921504606846976 = ~8070450532247928832 +7 * ~576460752303423488 = ~4035225266123964416 +8 * ~9223372036854775808 = Overflow +8 * ~4611686018427387904 = Overflow +8 * ~2305843009213693952 = Overflow +8 * ~1152921504606846976 = ~9223372036854775808 +8 * ~576460752303423488 = ~4611686018427387904 +9 * ~9223372036854775808 = Overflow +9 * ~4611686018427387904 = Overflow +9 * ~2305843009213693952 = Overflow +9 * ~1152921504606846976 = Overflow +9 * ~576460752303423488 = ~5188146770730811392 +10 * ~9223372036854775808 = Overflow +10 * ~4611686018427387904 = Overflow +10 * ~2305843009213693952 = Overflow +10 * ~1152921504606846976 = Overflow +10 * ~576460752303423488 = ~5764607523034234880 +11 * ~9223372036854775808 = Overflow +11 * ~4611686018427387904 = Overflow +11 * ~2305843009213693952 = Overflow +11 * ~1152921504606846976 = Overflow +11 * ~576460752303423488 = ~6341068275337658368 +12 * ~9223372036854775808 = Overflow +12 * ~4611686018427387904 = Overflow +12 * ~2305843009213693952 = Overflow +12 * ~1152921504606846976 = Overflow +12 * ~576460752303423488 = ~6917529027641081856 +13 * ~9223372036854775808 = Overflow +13 * ~4611686018427387904 = Overflow +13 * ~2305843009213693952 = Overflow +13 * ~1152921504606846976 = Overflow +13 * ~576460752303423488 = ~7493989779944505344 +14 * ~9223372036854775808 = Overflow +14 * ~4611686018427387904 = Overflow +14 * ~2305843009213693952 = Overflow +14 * ~1152921504606846976 = Overflow +14 * ~576460752303423488 = ~8070450532247928832 +15 * ~9223372036854775808 = Overflow +15 * ~4611686018427387904 = Overflow +15 * ~2305843009213693952 = Overflow +15 * ~1152921504606846976 = Overflow +15 * ~576460752303423488 = ~8646911284551352320 +16 * ~9223372036854775808 = Overflow +16 * ~4611686018427387904 = Overflow +16 * ~2305843009213693952 = Overflow +16 * ~1152921504606846976 = Overflow +16 * ~576460752303423488 = ~9223372036854775808 +17 * ~9223372036854775808 = Overflow +17 * ~4611686018427387904 = Overflow +17 * ~2305843009213693952 = Overflow +17 * ~1152921504606846976 = Overflow +17 * ~576460752303423488 = Overflow +18 * ~9223372036854775808 = Overflow +18 * ~4611686018427387904 = Overflow +18 * ~2305843009213693952 = Overflow +18 * ~1152921504606846976 = Overflow +18 * ~576460752303423488 = Overflow +19 * ~9223372036854775808 = Overflow +19 * ~4611686018427387904 = Overflow +19 * ~2305843009213693952 = Overflow +19 * ~1152921504606846976 = Overflow +19 * ~576460752303423488 = Overflow +20 * ~9223372036854775808 = Overflow +20 * ~4611686018427387904 = Overflow +20 * ~2305843009213693952 = Overflow +20 * ~1152921504606846976 = Overflow +20 * ~576460752303423488 = Overflow +21 * ~9223372036854775808 = Overflow +21 * ~4611686018427387904 = Overflow +21 * ~2305843009213693952 = Overflow +21 * ~1152921504606846976 = Overflow +21 * ~576460752303423488 = Overflow +22 * ~9223372036854775808 = Overflow +22 * ~4611686018427387904 = Overflow +22 * ~2305843009213693952 = Overflow +22 * ~1152921504606846976 = Overflow +22 * ~576460752303423488 = Overflow +23 * ~9223372036854775808 = Overflow +23 * ~4611686018427387904 = Overflow +23 * ~2305843009213693952 = Overflow +23 * ~1152921504606846976 = Overflow +23 * ~576460752303423488 = Overflow +24 * ~9223372036854775808 = Overflow +24 * ~4611686018427387904 = Overflow +24 * ~2305843009213693952 = Overflow +24 * ~1152921504606846976 = Overflow +24 * ~576460752303423488 = Overflow +25 * ~9223372036854775808 = Overflow +25 * ~4611686018427387904 = Overflow +25 * ~2305843009213693952 = Overflow +25 * ~1152921504606846976 = Overflow +25 * ~576460752303423488 = Overflow +26 * ~9223372036854775808 = Overflow +26 * ~4611686018427387904 = Overflow +26 * ~2305843009213693952 = Overflow +26 * ~1152921504606846976 = Overflow +26 * ~576460752303423488 = Overflow +27 * ~9223372036854775808 = Overflow +27 * ~4611686018427387904 = Overflow +27 * ~2305843009213693952 = Overflow +27 * ~1152921504606846976 = Overflow +27 * ~576460752303423488 = Overflow +28 * ~9223372036854775808 = Overflow +28 * ~4611686018427387904 = Overflow +28 * ~2305843009213693952 = Overflow +28 * ~1152921504606846976 = Overflow +28 * ~576460752303423488 = Overflow +29 * ~9223372036854775808 = Overflow +29 * ~4611686018427387904 = Overflow +29 * ~2305843009213693952 = Overflow +29 * ~1152921504606846976 = Overflow +29 * ~576460752303423488 = Overflow +30 * ~9223372036854775808 = Overflow +30 * ~4611686018427387904 = Overflow +30 * ~2305843009213693952 = Overflow +30 * ~1152921504606846976 = Overflow +30 * ~576460752303423488 = Overflow +31 * ~9223372036854775808 = Overflow +31 * ~4611686018427387904 = Overflow +31 * ~2305843009213693952 = Overflow +31 * ~1152921504606846976 = Overflow +31 * ~576460752303423488 = Overflow +32 * ~9223372036854775808 = Overflow +32 * ~4611686018427387904 = Overflow +32 * ~2305843009213693952 = Overflow +32 * ~1152921504606846976 = Overflow +32 * ~576460752303423488 = Overflow +~9223372036854775808 * 1 = ~9223372036854775808 +~9223372036854775808 * 2 = Overflow +~9223372036854775808 * 4 = Overflow +~9223372036854775808 * 8 = Overflow +~9223372036854775808 * 16 = Overflow +~4611686018427387904 * 1 = ~4611686018427387904 +~4611686018427387904 * 2 = ~9223372036854775808 +~4611686018427387904 * 4 = Overflow +~4611686018427387904 * 8 = Overflow +~4611686018427387904 * 16 = Overflow +~2305843009213693952 * 1 = ~2305843009213693952 +~2305843009213693952 * 2 = ~4611686018427387904 +~2305843009213693952 * 4 = ~9223372036854775808 +~2305843009213693952 * 8 = Overflow +~2305843009213693952 * 16 = Overflow +~1152921504606846976 * 1 = ~1152921504606846976 +~1152921504606846976 * 2 = ~2305843009213693952 +~1152921504606846976 * 4 = ~4611686018427387904 +~1152921504606846976 * 8 = ~9223372036854775808 +~1152921504606846976 * 16 = Overflow +~576460752303423488 * 1 = ~576460752303423488 +~576460752303423488 * 2 = ~1152921504606846976 +~576460752303423488 * 4 = ~2305843009213693952 +~576460752303423488 * 8 = ~4611686018427387904 +~576460752303423488 * 16 = ~9223372036854775808 +~288230376151711744 * 1 = ~288230376151711744 +~288230376151711744 * 2 = ~576460752303423488 +~288230376151711744 * 4 = ~1152921504606846976 +~288230376151711744 * 8 = ~2305843009213693952 +~288230376151711744 * 16 = ~4611686018427387904 +~4 * 1 = ~4 +~4 * 2 = ~8 +~4 * 4 = ~16 +~4 * 8 = ~32 +~4 * 16 = ~64 +~3 * 1 = ~3 +~3 * 2 = ~6 +~3 * 4 = ~12 +~3 * 8 = ~24 +~3 * 16 = ~48 +~2 * 1 = ~2 +~2 * 2 = ~4 +~2 * 4 = ~8 +~2 * 8 = ~16 +~2 * 16 = ~32 +~1 * 1 = ~1 +~1 * 2 = ~2 +~1 * 4 = ~4 +~1 * 8 = ~8 +~1 * 16 = ~16 +0 * 1 = 0 +0 * 2 = 0 +0 * 4 = 0 +0 * 8 = 0 +0 * 16 = 0 +1 * 1 = 1 +1 * 2 = 2 +1 * 4 = 4 +1 * 8 = 8 +1 * 16 = 16 +2 * 1 = 2 +2 * 2 = 4 +2 * 4 = 8 +2 * 8 = 16 +2 * 16 = 32 +3 * 1 = 3 +3 * 2 = 6 +3 * 4 = 12 +3 * 8 = 24 +3 * 16 = 48 +4 * 1 = 4 +4 * 2 = 8 +4 * 4 = 16 +4 * 8 = 32 +4 * 16 = 64 +144115188075855872 * 1 = 144115188075855872 +144115188075855872 * 2 = 288230376151711744 +144115188075855872 * 4 = 576460752303423488 +144115188075855872 * 8 = 1152921504606846976 +144115188075855872 * 16 = 2305843009213693952 +288230376151711744 * 1 = 288230376151711744 +288230376151711744 * 2 = 576460752303423488 +288230376151711744 * 4 = 1152921504606846976 +288230376151711744 * 8 = 2305843009213693952 +288230376151711744 * 16 = 4611686018427387904 +576460752303423488 * 1 = 576460752303423488 +576460752303423488 * 2 = 1152921504606846976 +576460752303423488 * 4 = 2305843009213693952 +576460752303423488 * 8 = 4611686018427387904 +576460752303423488 * 16 = Overflow +1152921504606846976 * 1 = 1152921504606846976 +1152921504606846976 * 2 = 2305843009213693952 +1152921504606846976 * 4 = 4611686018427387904 +1152921504606846976 * 8 = Overflow +1152921504606846976 * 16 = Overflow +2305843009213693952 * 1 = 2305843009213693952 +2305843009213693952 * 2 = 4611686018427387904 +2305843009213693952 * 4 = Overflow +2305843009213693952 * 8 = Overflow +2305843009213693952 * 16 = Overflow +4611686018427387904 * 1 = 4611686018427387904 +4611686018427387904 * 2 = Overflow +4611686018427387904 * 4 = Overflow +4611686018427387904 * 8 = Overflow +4611686018427387904 * 16 = Overflow +~9223372036854775808 * ~1 = Overflow +~9223372036854775808 * ~2 = Overflow +~9223372036854775808 * ~4 = Overflow +~9223372036854775808 * ~8 = Overflow +~9223372036854775808 * ~16 = Overflow +~4611686018427387904 * ~1 = 4611686018427387904 +~4611686018427387904 * ~2 = Overflow +~4611686018427387904 * ~4 = Overflow +~4611686018427387904 * ~8 = Overflow +~4611686018427387904 * ~16 = Overflow +~2305843009213693952 * ~1 = 2305843009213693952 +~2305843009213693952 * ~2 = 4611686018427387904 +~2305843009213693952 * ~4 = Overflow +~2305843009213693952 * ~8 = Overflow +~2305843009213693952 * ~16 = Overflow +~1152921504606846976 * ~1 = 1152921504606846976 +~1152921504606846976 * ~2 = 2305843009213693952 +~1152921504606846976 * ~4 = 4611686018427387904 +~1152921504606846976 * ~8 = Overflow +~1152921504606846976 * ~16 = Overflow +~576460752303423488 * ~1 = 576460752303423488 +~576460752303423488 * ~2 = 1152921504606846976 +~576460752303423488 * ~4 = 2305843009213693952 +~576460752303423488 * ~8 = 4611686018427387904 +~576460752303423488 * ~16 = Overflow +~288230376151711744 * ~1 = 288230376151711744 +~288230376151711744 * ~2 = 576460752303423488 +~288230376151711744 * ~4 = 1152921504606846976 +~288230376151711744 * ~8 = 2305843009213693952 +~288230376151711744 * ~16 = 4611686018427387904 +~4 * ~1 = 4 +~4 * ~2 = 8 +~4 * ~4 = 16 +~4 * ~8 = 32 +~4 * ~16 = 64 +~3 * ~1 = 3 +~3 * ~2 = 6 +~3 * ~4 = 12 +~3 * ~8 = 24 +~3 * ~16 = 48 +~2 * ~1 = 2 +~2 * ~2 = 4 +~2 * ~4 = 8 +~2 * ~8 = 16 +~2 * ~16 = 32 +~1 * ~1 = 1 +~1 * ~2 = 2 +~1 * ~4 = 4 +~1 * ~8 = 8 +~1 * ~16 = 16 +0 * ~1 = 0 +0 * ~2 = 0 +0 * ~4 = 0 +0 * ~8 = 0 +0 * ~16 = 0 +1 * ~1 = ~1 +1 * ~2 = ~2 +1 * ~4 = ~4 +1 * ~8 = ~8 +1 * ~16 = ~16 +2 * ~1 = ~2 +2 * ~2 = ~4 +2 * ~4 = ~8 +2 * ~8 = ~16 +2 * ~16 = ~32 +3 * ~1 = ~3 +3 * ~2 = ~6 +3 * ~4 = ~12 +3 * ~8 = ~24 +3 * ~16 = ~48 +4 * ~1 = ~4 +4 * ~2 = ~8 +4 * ~4 = ~16 +4 * ~8 = ~32 +4 * ~16 = ~64 +144115188075855872 * ~1 = ~144115188075855872 +144115188075855872 * ~2 = ~288230376151711744 +144115188075855872 * ~4 = ~576460752303423488 +144115188075855872 * ~8 = ~1152921504606846976 +144115188075855872 * ~16 = ~2305843009213693952 +288230376151711744 * ~1 = ~288230376151711744 +288230376151711744 * ~2 = ~576460752303423488 +288230376151711744 * ~4 = ~1152921504606846976 +288230376151711744 * ~8 = ~2305843009213693952 +288230376151711744 * ~16 = ~4611686018427387904 +576460752303423488 * ~1 = ~576460752303423488 +576460752303423488 * ~2 = ~1152921504606846976 +576460752303423488 * ~4 = ~2305843009213693952 +576460752303423488 * ~8 = ~4611686018427387904 +576460752303423488 * ~16 = ~9223372036854775808 +1152921504606846976 * ~1 = ~1152921504606846976 +1152921504606846976 * ~2 = ~2305843009213693952 +1152921504606846976 * ~4 = ~4611686018427387904 +1152921504606846976 * ~8 = ~9223372036854775808 +1152921504606846976 * ~16 = Overflow +2305843009213693952 * ~1 = ~2305843009213693952 +2305843009213693952 * ~2 = ~4611686018427387904 +2305843009213693952 * ~4 = ~9223372036854775808 +2305843009213693952 * ~8 = Overflow +2305843009213693952 * ~16 = Overflow +4611686018427387904 * ~1 = ~4611686018427387904 +4611686018427387904 * ~2 = ~9223372036854775808 +4611686018427387904 * ~4 = Overflow +4611686018427387904 * ~8 = Overflow +4611686018427387904 * ~16 = Overflow diff --git a/regression/int-mul-pow2.sml b/regression/int-mul-pow2.sml new file mode 100644 index 0000000000..ac3c3f9461 --- /dev/null +++ b/regression/int-mul-pow2.sml @@ -0,0 +1,187 @@ +functor Test(structure Int: + sig + include INTEGER + val zero: int + val one: int + end) = +struct + +val zero = Int.zero +val one = Int.one +val two = Int.+ (one, one) +val three = Int.+ (two, one) +val four = Int.* (two, two) +val eight = Int.* (four, two) +val sixteen = Int.* (eight, two) +val thirtytwo = Int.* (sixteen, two) + +val maxposint = valOf Int.maxInt +val maxnegpow2 = Int.- (Int.~ maxposint, one) +val maxpospow2 = Int.+ (Int.quot (maxposint, two), one) + +fun doit k = +let + val i = maxpospow2 + val () = print (concat [Int.toString k, " * ", Int.toString i, " = ", + (Int.toString (Int.* (k, i)) + handle Overflow => "Overflow"), "\n"]) + val i = Int.quot (i, two) + val () = print (concat [Int.toString k, " * ", Int.toString i, " = ", + (Int.toString (Int.* (k, i)) + handle Overflow => "Overflow"), "\n"]) + val i = Int.quot (i, two) + val () = print (concat [Int.toString k, " * ", Int.toString i, " = ", + (Int.toString (Int.* (k, i)) + handle Overflow => "Overflow"), "\n"]) + val i = Int.quot (i, two) + val () = print (concat [Int.toString k, " * ", Int.toString i, " = ", + (Int.toString (Int.* (k, i)) + handle Overflow => "Overflow"), "\n"]) + val i = Int.quot (i, two) + val () = print (concat [Int.toString k, " * ", Int.toString i, " = ", + (Int.toString (Int.* (k, i)) + handle Overflow => "Overflow"), "\n"]) +in + () +end + +fun loop k = + if Int.> (k, thirtytwo) + then () + else (doit k; loop (Int.+ (k, one))) + +val () = loop (Int.~ thirtytwo) + +fun doit k = +let + val i = maxnegpow2 + val () = print (concat [Int.toString k, " * ", Int.toString i, " = ", + (Int.toString (Int.* (k, i)) + handle Overflow => "Overflow"), "\n"]) + val i = Int.quot (i, two) + val () = print (concat [Int.toString k, " * ", Int.toString i, " = ", + (Int.toString (Int.* (k, i)) + handle Overflow => "Overflow"), "\n"]) + val i = Int.quot (i, two) + val () = print (concat [Int.toString k, " * ", Int.toString i, " = ", + (Int.toString (Int.* (k, i)) + handle Overflow => "Overflow"), "\n"]) + val i = Int.quot (i, two) + val () = print (concat [Int.toString k, " * ", Int.toString i, " = ", + (Int.toString (Int.* (k, i)) + handle Overflow => "Overflow"), "\n"]) + val i = Int.quot (i, two) + val () = print (concat [Int.toString k, " * ", Int.toString i, " = ", + (Int.toString (Int.* (k, i)) + handle Overflow => "Overflow"), "\n"]) +in + () +end + +fun loop k = + if Int.> (k, thirtytwo) + then () + else (doit k; loop (Int.+ (k, one))) + +val () = loop (Int.~ thirtytwo) + +val ks = [maxnegpow2, Int.quot (maxnegpow2, two), Int.quot (maxnegpow2, four), + Int.quot (maxnegpow2, eight), Int.quot (maxnegpow2, sixteen), Int.quot (maxnegpow2, thirtytwo), + Int.~ four, Int.~ three, Int.~ two, Int.~ one, + zero, + one, two, three, four, + Int.quot (maxpospow2, thirtytwo), Int.quot (maxpospow2, sixteen), Int.quot (maxpospow2, eight), + Int.quot (maxpospow2, four), Int.quot (maxpospow2, two), maxpospow2] + +fun doit k = +let + val i = one + val () = print (concat [Int.toString k, " * ", Int.toString i, " = ", + (Int.toString (Int.* (k, i)) + handle Overflow => "Overflow"), "\n"]) + val i = Int.* (i, two) + val () = print (concat [Int.toString k, " * ", Int.toString i, " = ", + (Int.toString (Int.* (k, i)) + handle Overflow => "Overflow"), "\n"]) + val i = Int.* (i, two) + val () = print (concat [Int.toString k, " * ", Int.toString i, " = ", + (Int.toString (Int.* (k, i)) + handle Overflow => "Overflow"), "\n"]) + val i = Int.* (i, two) + val () = print (concat [Int.toString k, " * ", Int.toString i, " = ", + (Int.toString (Int.* (k, i)) + handle Overflow => "Overflow"), "\n"]) + val i = Int.* (i, two) + val () = print (concat [Int.toString k, " * ", Int.toString i, " = ", + (Int.toString (Int.* (k, i)) + handle Overflow => "Overflow"), "\n"]) +in + () +end + +fun loop ks = + case ks of + [] => () + | k::ks => (doit k; loop ks) + +val () = loop ks + +fun doit k = +let + val i = Int.~ one + val () = print (concat [Int.toString k, " * ", Int.toString i, " = ", + (Int.toString (Int.* (k, i)) + handle Overflow => "Overflow"), "\n"]) + val i = Int.* (i, two) + val () = print (concat [Int.toString k, " * ", Int.toString i, " = ", + (Int.toString (Int.* (k, i)) + handle Overflow => "Overflow"), "\n"]) + val i = Int.* (i, two) + val () = print (concat [Int.toString k, " * ", Int.toString i, " = ", + (Int.toString (Int.* (k, i)) + handle Overflow => "Overflow"), "\n"]) + val i = Int.* (i, two) + val () = print (concat [Int.toString k, " * ", Int.toString i, " = ", + (Int.toString (Int.* (k, i)) + handle Overflow => "Overflow"), "\n"]) + val i = Int.* (i, two) + val () = print (concat [Int.toString k, " * ", Int.toString i, " = ", + (Int.toString (Int.* (k, i)) + handle Overflow => "Overflow"), "\n"]) +in + () +end + +fun loop ks = + case ks of + [] => () + | k::ks => (doit k; loop ks) + +val () = loop ks + +end + +structure Test8 = Test(structure Int = + struct + open Int8 + val zero: int = 0 + val one: int = 1 + end) +structure Test16 = Test(structure Int = + struct + open Int16 + val zero: int = 0 + val one: int = 1 + end) +structure Test32 = Test(structure Int = + struct + open Int32 + val zero: int = 0 + val one: int = 1 + end) +structure Test64 = Test(structure Int = + struct + open Int64 + val zero: int = 0 + val one: int = 1 + end) From 8fea7b6f4f97fc2a427bf7e79045636255c0c608 Mon Sep 17 00:00:00 2001 From: Daman Morris Date: Tue, 28 Aug 2018 09:31:14 -0400 Subject: [PATCH 37/57] Fix `int-mul-pow2` bug --- mlton/codegen/amd64-codegen/amd64-simplify.fun | 10 ++++++---- mlton/codegen/x86-codegen/x86-simplify.fun | 10 ++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/mlton/codegen/amd64-codegen/amd64-simplify.fun b/mlton/codegen/amd64-codegen/amd64-simplify.fun index 4a10eb5592..b7ed9a7970 100644 --- a/mlton/codegen/amd64-codegen/amd64-simplify.fun +++ b/mlton/codegen/amd64-codegen/amd64-simplify.fun @@ -1514,7 +1514,7 @@ struct (* elimBinAL0L:: *) (* elimBinAL0R:: *) elimAddSub1:: - elimMDPow2:: +(* elimMDPow2:: *) elimCMPTEST:: nil val optimizations_pre_msg @@ -1522,18 +1522,20 @@ struct (* elimBinAL0L_msg:: *) (* elimBinAL0R_msg:: *) elimAddSub1_msg:: - elimMDPow2_msg:: +(* elimMDPow2_msg:: *) nil val optimizations_post - = elimBinALMDDouble:: + = elimMDPow2:: + elimBinALMDDouble:: elimSSEBinASDouble:: elimCMPTEST:: elimCMP0:: elimALTEST:: nil val optimizations_post_msg - = elimBinALMDDouble_msg:: + = elimMDPow2_msg:: + elimBinALMDDouble_msg:: elimSSEBinASDouble_msg:: elimCMPTEST_msg:: elimCMP0_msg:: diff --git a/mlton/codegen/x86-codegen/x86-simplify.fun b/mlton/codegen/x86-codegen/x86-simplify.fun index e3b3f18c61..992ac2ab58 100644 --- a/mlton/codegen/x86-codegen/x86-simplify.fun +++ b/mlton/codegen/x86-codegen/x86-simplify.fun @@ -1608,7 +1608,7 @@ struct (* elimBinAL0L:: *) (* elimBinAL0R:: *) elimAddSub1:: - elimMDPow2:: +(* elimMDPow2:: *) elimCMPTEST:: nil val optimizations_pre_msg @@ -1616,18 +1616,20 @@ struct (* elimBinAL0L_msg:: *) (* elimBinAL0R_msg:: *) elimAddSub1_msg:: - elimMDPow2_msg:: +(* elimMDPow2_msg:: *) nil val optimizations_post - = elimBinALMDDouble:: + = elimMDPow2:: + elimBinALMDDouble:: elimFltBinADouble:: elimCMPTEST:: elimCMP0:: elimALTEST:: nil val optimizations_post_msg - = elimBinALMDDouble_msg:: + = elimMDPow2_msg:: + elimBinALMDDouble_msg:: elimFltBinADouble_msg:: elimCMPTEST_msg:: elimCMP0_msg:: From 0da9dfe8cba5ec7f8580a76ab3518e4c4f41f4d6 Mon Sep 17 00:00:00 2001 From: Daman Morris Date: Tue, 4 Sep 2018 12:28:47 -0400 Subject: [PATCH 38/57] Remove debug printing from `amd64-simplify.fun` --- mlton/codegen/amd64-codegen/amd64-simplify.fun | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/mlton/codegen/amd64-codegen/amd64-simplify.fun b/mlton/codegen/amd64-codegen/amd64-simplify.fun index b7ed9a7970..44b7b08823 100644 --- a/mlton/codegen/amd64-codegen/amd64-simplify.fun +++ b/mlton/codegen/amd64-codegen/amd64-simplify.fun @@ -4507,15 +4507,6 @@ struct changed = false, msg = "amd64Liveness.LivenessBlock.toLivenessBlock"} - - val _ = if !Control.debug then - (print "\n***** BEGIN PRE-PEEPHOLE *****\n" - ; Block.layouts (amd64Liveness.LivenessBlock.toBlock - {block = block}, - print o Layout.toString) - ; print "\n***** END PRE-PEEPHOLE *****\n") - else () - (***************************************************) (* peepholeLivenessBlock_pre *) (***************************************************) @@ -4536,14 +4527,6 @@ struct val block = block' val changed = changed orelse changed' - val _ = if !Control.debug then - (print "\n***** BEGIN POST-PEEPHOLE *****\n" - ; Block.layouts (amd64Liveness.LivenessBlock.toBlock - {block = block}, - print o Layout.toString) - ; print "\n***** END POST-PEEPHOLE *****\n") - else () - (***************************************************) (* moveHoist *) (***************************************************) From 56d4362945a373d75b68ec15b83e5c2d08e587d0 Mon Sep 17 00:00:00 2001 From: Daman Morris Date: Wed, 5 Sep 2018 07:40:20 -0400 Subject: [PATCH 39/57] Remove superfluous `elimALRedundant_pseudo` optimization --- .../codegen/amd64-codegen/amd64-simplify.fun | 111 ------------------ 1 file changed, 111 deletions(-) diff --git a/mlton/codegen/amd64-codegen/amd64-simplify.fun b/mlton/codegen/amd64-codegen/amd64-simplify.fun index 44b7b08823..1f373f0062 100644 --- a/mlton/codegen/amd64-codegen/amd64-simplify.fun +++ b/mlton/codegen/amd64-codegen/amd64-simplify.fun @@ -3089,115 +3089,6 @@ struct val elimALCopy_msg = elimALCopy_msg end - local - fun isInstructionMOV_aux (check) : statement_type -> bool - = fn (Assembly.Instruction (Instruction.MOV - {dst = Operand.MemLoc memloc, ...}), - _) - => check memloc - | _ => false - - val isInstructionMOV : statement_type -> bool - = isInstructionMOV_aux (fn _ => true) - val isInstructionMOV_dstTemp : statement_type -> bool - = isInstructionMOV_aux amd64Liveness.track - - fun isInstructionBinAL_aux (check) : statement_type -> bool - = fn (Assembly.Instruction (Instruction.BinAL - {dst = Operand.MemLoc memloc, ...}), - _) - => check memloc - | _ => false - - val isInstructionBinAL : statement_type -> bool - = isInstructionBinAL_aux (fn _ => true) - - fun isDeadTemp dead memloc - = amd64Liveness.track memloc andalso LiveSet.contains (dead, memloc) - val isInstructionBinAL_dstDeadTemp : statement_type -> bool - = fn (instr, liveness as Liveness.T {dead, ...}) - => isInstructionBinAL_aux (isDeadTemp dead) (instr, liveness) - - val template : template - = {start = EmptyOrNonEmpty, - statements = [One isInstructionMOV, - All isComment, - One isInstructionBinAL, - All isComment, - One isInstructionMOV_dstTemp, - All isComment, - One isInstructionBinAL_dstDeadTemp], - finish = EmptyOrNonEmpty, - transfer = fn _ => true} - - val rewriter : rewriter - = fn {entry, - profileLabel, - start, - statements = - [[(stmtMov as Assembly.Instruction (Instruction.MOV - {src = src1x, - dst = dst1z, ...}), - _)], - comments1, - [(stmtAL as Assembly.Instruction (Instruction.BinAL - {src = src1, - dst = dst1, ...}), - _)], - comments2, - [(Assembly.Instruction (Instruction.MOV - {src = src2x, - dst = dst2z, ...}), - _)], - comments3, - [(Assembly.Instruction (Instruction.BinAL - {src = src2, - dst = dst2, ...}), - Liveness.T {liveOut = liveOut2, ...})]], - finish, - transfer} - => if !Control.Native.elimALRedundant andalso - Operand.eq (src1x, src2x) andalso - Operand.eq (src1, dst1) andalso - Operand.eq (src2, dst2) andalso - Operand.eq (dst1z, src1) andalso - Operand.eq (dst2z, src2) - then - let - val excomm = fn comm => List.map (comm, fn (c, _) => c) - val comments1 = excomm comments1 - val comments2 = excomm comments2 - val comments3 = excomm comments3 - - val statements = - stmtMov::(comments1 @ (stmtAL::(comments2 @ comments3))) - val {statements, ...} - = LivenessBlock.toLivenessStatements - {statements = statements, live = liveOut2} - val statements - = List.fold (start, - List.concat [statements, finish], - op ::) - in - SOME (LivenessBlock.T - {entry = entry, - profileLabel = profileLabel, - statements = statements, - transfer = transfer}) - end - else NONE - | _ => Error.bug "amd64Simplify.PeepholeBlock: elimALRedundant_pseudo" - - val (callback, elimALRedundant_pseudo_msg) - = make_callback_msg "elimALRedundant_pseudo" - in - val elimALRedundant_pseudo : optimization - = {template = template, - rewriter = rewriter, - callback = callback} - val elimALRedundant_pseudo_msg = elimALRedundant_pseudo_msg - end - local fun isInstructionMOV_aux (check) : statement_type -> bool = fn (Assembly.Instruction (Instruction.MOV @@ -4201,11 +4092,9 @@ struct local val optimizations_pre = elimALRedundant:: - elimALRedundant_pseudo:: nil val optimizations_pre_msg = elimALRedundant_msg:: - elimALRedundant_pseudo_msg:: nil val optimizations From 03e41a01e29e55f471a4066da583a5d9c9f3a518 Mon Sep 17 00:00:00 2001 From: Daman Morris Date: Thu, 6 Sep 2018 11:31:44 -0400 Subject: [PATCH 40/57] Correct initial refactoring of overflow primitives --- basis-library/arrays-and-vectors/sequence.fun | 46 ++++---- .../arrays-and-vectors/sequence0.sml | 100 +++++++++--------- basis-library/integer/int-inf.sig | 8 +- basis-library/integer/int-inf0.sml | 8 -- 4 files changed, 77 insertions(+), 85 deletions(-) diff --git a/basis-library/arrays-and-vectors/sequence.fun b/basis-library/arrays-and-vectors/sequence.fun index 8adb237c8a..4340e4e0bb 100644 --- a/basis-library/arrays-and-vectors/sequence.fun +++ b/basis-library/arrays-and-vectors/sequence.fun @@ -68,9 +68,9 @@ structure SeqIndex = functor Sequence (S: PRIM_SEQUENCE): SEQUENCE = struct - val op +$ = SeqIndex.+$ val op +! = SeqIndex.+! - val op -$ = SeqIndex.-$ + val op +$ = SeqIndex.+$ + val op -! = SeqIndex.-! val op <= = SeqIndex.<= val op > = SeqIndex.> val op >= = SeqIndex.>= @@ -258,7 +258,7 @@ functor Sequence (S: PRIM_SEQUENCE): SEQUENCE = let val sl = toSlice x in S.Slice.unsafeCopy {dst = a, di = di, src = sl} - ; loop (di +$ S.Slice.length sl, xs) + ; loop (di +! S.Slice.length sl, xs) end in loop (0, xs) @@ -279,7 +279,7 @@ functor Sequence (S: PRIM_SEQUENCE): SEQUENCE = (s +$ sepn +$ S.Slice.length (toSlice x)) handle Overflow => raise Size) else (fn (x, s) => - (s +$ sepn +$ S.Slice.length (toSlice x))) + (s +! sepn +! S.Slice.length (toSlice x))) val n = List.foldl add (S.Slice.length (toSlice x)) xs val a = Primitive.Array.alloc n fun loop (di, xs) = @@ -296,9 +296,9 @@ functor Sequence (S: PRIM_SEQUENCE): SEQUENCE = let val sl = toSlice x val _ = S.Slice.unsafeCopy {dst = a, di = di, src = sl} - val di = di +$ S.Slice.length sl + val di = di +! S.Slice.length sl val _ = S.Slice.unsafeCopy {dst = a, di = di, src = sep} - val di = di +$ sepn + val di = di +! sepn in loop (di, xs) end @@ -318,9 +318,9 @@ functor Sequence (S: PRIM_SEQUENCE): SEQUENCE = in if SeqIndex.> (k, len) then S.Slice.unsafeSubslice (sl, len, SOME 0) - else S.Slice.unsafeSubslice (sl, k, SOME (len -$ k)) + else S.Slice.unsafeSubslice (sl, k, SOME (len -! k)) end handle Overflow => - (* k is positive, so behavior is specified? *) + (* k is positive, so behavior is specified! *) S.Slice.unsafeSubslice (sl, S.Slice.length sl, SOME 0) fun trimr k sl = if Primitive.Controls.safe andalso Int.< (k, 0) @@ -334,9 +334,9 @@ functor Sequence (S: PRIM_SEQUENCE): SEQUENCE = in if SeqIndex.> (k, len) then S.Slice.unsafeSubslice (sl, 0, SOME 0) - else S.Slice.unsafeSubslice (sl, 0, SOME (len -$ k)) + else S.Slice.unsafeSubslice (sl, 0, SOME (len -! k)) end handle Overflow => - (* k is positive, so behavior is specified? *) + (* k is positive, so behavior is specified! *) S.Slice.unsafeSubslice (sl, 0, SOME 0) fun isSubsequence (eq: 'a elt * 'a elt -> bool) (seq: 'a sequence) @@ -347,16 +347,16 @@ functor Sequence (S: PRIM_SEQUENCE): SEQUENCE = in if n <= n' then let - val n'' = n' -$ n + val n'' = n' -! n fun loop (i, j) = if i > n'' then false else if j >= n then true else if eq (S.unsafeSub (seq, j), - S.Slice.unsafeSub (sl, i +$ j)) - then loop (i, j +$ 1) - else loop (i +$ 1, 0) + S.Slice.unsafeSub (sl, i +! j)) + then loop (i, j +! 1) + else loop (i +! 1, 0) in loop (0, 0) end @@ -376,7 +376,7 @@ functor Sequence (S: PRIM_SEQUENCE): SEQUENCE = then true else if eq (S.unsafeSub (seq, j), S.Slice.unsafeSub (sl, j)) - then loop (j +$ 1) + then loop (j +! 1) else false in loop (0) @@ -392,13 +392,13 @@ functor Sequence (S: PRIM_SEQUENCE): SEQUENCE = in if n <= n' then let - val n'' = n' -$ n + val n'' = n' -! n fun loop (j) = if j >= n then true else if eq (S.unsafeSub (seq, j), - S.Slice.unsafeSub (sl, n'' +$ j)) - then loop (j +$ 1) + S.Slice.unsafeSub (sl, n'' +! j)) + then loop (j +! 1) else false in loop (0) @@ -423,14 +423,14 @@ functor Sequence (S: PRIM_SEQUENCE): SEQUENCE = fun make finish p sl = let val (seq, start, len) = S.Slice.base sl - val max = start +$ len + val max = start +! len fun loop (i, start, sls) = if i >= max then List.rev (finish (seq, start, i, sls)) else if p (S.unsafeSub (seq, i)) - then loop (i +$ 1, i +$ 1, finish (seq, start, i, sls)) - else loop (i +$ 1, start, sls) + then loop (i +! 1, i +! 1, finish (seq, start, i, sls)) + else loop (i +! 1, start, sls) in loop (start, start, []) end in @@ -441,14 +441,14 @@ functor Sequence (S: PRIM_SEQUENCE): SEQUENCE = else (fromSlice (S.Slice.unsafeSlice - (seq, start, SOME (stop -$ start)))) + (seq, start, SOME (stop -! start)))) :: sls) p sl fun fieldsGen fromSlice p sl = make (fn (seq, start, stop, sls) => (fromSlice (S.Slice.unsafeSlice - (seq, start, SOME (stop -$ start)))) + (seq, start, SOME (stop -! start)))) :: sls) p sl end diff --git a/basis-library/arrays-and-vectors/sequence0.sml b/basis-library/arrays-and-vectors/sequence0.sml index 90c39c035f..b5de282628 100644 --- a/basis-library/arrays-and-vectors/sequence0.sml +++ b/basis-library/arrays-and-vectors/sequence0.sml @@ -27,9 +27,9 @@ functor PrimSequence (S: sig struct structure Array = Primitive.Array - val op +$ = SeqIndex.+$ + val op +! = SeqIndex.+! val op + = SeqIndex.+ - val op -$ = SeqIndex.-$ + val op -! = SeqIndex.-! val op < = SeqIndex.< val op <= = SeqIndex.<= val op > = SeqIndex.> @@ -130,7 +130,7 @@ functor PrimSequence (S: sig val (x, b) = f (i, b) val () = Array.updateUnsafe (a, i, x) in - loop (i +$ 1, b) + loop (i +! 1, b) end val b = loop (0, b) in @@ -154,13 +154,13 @@ functor PrimSequence (S: sig fun length (T {len, ...}) = len fun unsafeSub (T {seq, start, ...}, i) = - S.subUnsafe (seq, start +$ i) + S.subUnsafe (seq, start +! i) fun sub (sl as T {len, ...}, i) = if Primitive.Controls.safe andalso geu (i, len) then raise Subscript else unsafeSub (sl, i) fun unsafeUpdate (T {seq, start, ...}, i, x) = - S.updateUnsafe (seq, start +$ i, x) + S.updateUnsafe (seq, start +! i, x) fun update (sl as T {len, ...}, i, x) = if Primitive.Controls.safe andalso geu (i, len) then raise Subscript @@ -168,7 +168,7 @@ functor PrimSequence (S: sig fun uninitIsNop (T {seq, ...}) = S.uninitIsNop seq fun unsafeUninit (T {seq, start, ...}, i) = - S.uninitUnsafe (seq, start +$ i) + S.uninitUnsafe (seq, start +! i) fun uninit (sl as T {len, ...}, i) = if Primitive.Controls.safe andalso geu (i, len) then raise Subscript @@ -179,15 +179,15 @@ functor PrimSequence (S: sig len: SeqIndex.int, overlap: unit -> bool} = let - fun move i = Array.updateUnsafe (dst, di +$ i, S.subUnsafe (src, si +$ i)) - val len = len -$ 1 + fun move i = Array.updateUnsafe (dst, di +! i, S.subUnsafe (src, si +! i)) + val len = len -! 1 in if overlap () then let fun loop i = if i < 0 then () - else (move i; loop (i -$ 1)) + else (move i; loop (i -! 1)) in loop len end @@ -195,7 +195,7 @@ functor PrimSequence (S: sig fun loop i = if i > len then () - else (move i; loop (i +$ 1)) + else (move i; loop (i +! 1)) in loop 0 end @@ -222,13 +222,13 @@ functor PrimSequence (S: sig src = T {seq = src, start = si, len}} = if Primitive.Controls.safe andalso (gtu (di, Array.length dst) - orelse gtu (di +$ len, Array.length dst)) + orelse gtu (di +! len, Array.length dst)) then raise Subscript else let fun overlap () = S.sameArray (dst, src) andalso si < di - andalso di <= si +$ len + andalso di <= si +! len in maybeSmallCopy {dst = dst, di = di, src = src, si = si, @@ -240,9 +240,9 @@ functor PrimSequence (S: sig T {seq = seq, start = 0, len = S.length seq} fun unsafeSubslice (T {seq, start, len}, start', len') = T {seq = seq, - start = start +$ start', + start = start +! start', len = (case len' of - NONE => len -$ start' + NONE => len -! start' | SOME len' => len')} fun unsafeSlice (seq, start, len) = unsafeSubslice (full seq, start, len) @@ -253,15 +253,15 @@ functor PrimSequence (S: sig andalso gtu (start', len) then raise Subscript else T {seq = seq, - start = start +$ start', - len = len -$ start'} + start = start +! start', + len = len -! start'} | SOME len' => if Primitive.Controls.safe andalso (gtu (start', len) - orelse gtu (len', len -$ start')) + orelse gtu (len', len -! start')) then raise Subscript else T {seq = seq, - start = start +$ start', + start = start +! start', len = len'} fun slice (seq: 'a sequence, start, len) = subslice (full seq, start, len) @@ -273,26 +273,26 @@ functor PrimSequence (S: sig then NONE else SOME (S.subUnsafe (seq, start), T {seq = seq, - start = start +$ 1, - len = len -$ 1}) + start = start +! 1, + len = len -! 1}) fun foldli f b (T {seq, start, len}) = let val min = start - val len = len -$ 1 - val max = start +$ len + val len = len -! 1 + val max = start +! len fun loop (i, b) = if i > max then b - else loop (i +$ 1, f (i -$ min, S.subUnsafe (seq, i), b)) + else loop (i +! 1, f (i -! min, S.subUnsafe (seq, i), b)) in loop (min, b) end fun foldri f b (T {seq, start, len}) = let val min = start - val len = len -$ 1 - val max = start +$ len + val len = len -! 1 + val max = start +! len fun loop (i, b) = if i < min then b - else loop (i -$ 1, f (i -$ min, S.subUnsafe (seq, i), b)) + else loop (i -! 1, f (i -! min, S.subUnsafe (seq, i), b)) in loop (max, b) end local @@ -304,20 +304,20 @@ functor PrimSequence (S: sig fun appi f sl = foldli (fn (i, x, ()) => f (i, x)) () sl fun app f sl = appi (f o #2) sl fun mapi f (T {seq, start, len}) = - tabulate (len, fn i => f (i, S.subUnsafe (seq, start +$ i))) + tabulate (len, fn i => f (i, S.subUnsafe (seq, start +! i))) fun map f sl = mapi (f o #2) sl fun findi p (T {seq, start, len}) = let val min = start - val len = len -$ 1 - val max = start +$ len + val len = len -! 1 + val max = start +! len fun loop i = if i > max then NONE - else let val z = (i -$ min, S.subUnsafe (seq, i)) + else let val z = (i -! min, S.subUnsafe (seq, i)) in if p z then SOME z - else loop (i +$ 1) + else loop (i +! 1) end in loop min end @@ -337,8 +337,8 @@ functor PrimSequence (S: sig let val min1 = start1 val min2 = start2 - val max1 = start1 +$ len1 - val max2 = start2 +$ len2 + val max1 = start1 +! len1 + val max2 = start2 +! len2 fun loop (i, j) = case (i >= max1, j >= max2) of (true, true) => EQUAL @@ -347,7 +347,7 @@ functor PrimSequence (S: sig | (false, false) => (case cmp (S.subUnsafe (seq1, i), S.subUnsafe (seq2, j)) of - EQUAL => loop (i +$ 1, j +$ 1) + EQUAL => loop (i +! 1, j +! 1) | ans => ans) in loop (min1, min2) end @@ -369,7 +369,7 @@ functor PrimSequence (S: sig let val (seq1, start1, len1) = base sl1 val (seq2, start2, len2) = base sl2 - val n = len1 +$ len2 + val n = len1 +! len2 val a = arrayAlloc n in S.copyUnsafe (a, 0, seq1, start1, len1) @@ -377,16 +377,16 @@ functor PrimSequence (S: sig ; S.fromArray a end fun split (T {seq, start, len}, i) = - (unsafeSlice (seq, start, SOME (i -$ start)), - unsafeSlice (seq, i, SOME (len -$ (i -$ start)))) + (unsafeSlice (seq, start, SOME (i -! start)), + unsafeSlice (seq, i, SOME (len -! (i -! start)))) fun splitl f (sl as T {seq, start, len}) = let - val stop = start +$ len + val stop = start +! len fun loop i = if i >= stop then i else if f (S.subUnsafe (seq, i)) - then loop (i +$ 1) + then loop (i +! 1) else i in split (sl, loop start) end @@ -396,15 +396,15 @@ functor PrimSequence (S: sig if i < start then start else if f (S.subUnsafe (seq, i)) - then loop (i -$ 1) - else i +$ 1 - in split (sl, loop (start +$ len -$ 1)) + then loop (i -! 1) + else i +! 1 + in split (sl, loop (start +! len -! 1)) end fun splitAt (T {seq, start, len}, i) = if Primitive.Controls.safe andalso gtu (i, len) then raise Subscript else (unsafeSlice (seq, start, SOME i), - unsafeSlice (seq, start +$ i, SOME (len -$ i))) + unsafeSlice (seq, start +! i, SOME (len -! i))) fun dropl p s = #2 (splitl p s) fun dropr p s = #1 (splitr p s) fun takel p s = #1 (splitl p s) @@ -414,19 +414,19 @@ functor PrimSequence (S: sig (sl as T {seq, start, len}) = let val len' = S.length seq' - val max = start +$ len -$ len' +$ 1 + val max = start +! len -! len' +! 1 (* loop returns the index of the front of the suffix. *) fun loop i = if i >= max - then start +$ len + then start +! len else let fun loop' j = if j >= len' then i - else if eq (S.subUnsafe (seq, i +$ j), + else if eq (S.subUnsafe (seq, i +! j), S.subUnsafe (seq', j)) - then loop' (j +$ 1) - else loop (i +$ 1) + then loop' (j +! 1) + else loop (i +! 1) in loop' 0 end in split (sl, loop start) @@ -435,9 +435,9 @@ functor PrimSequence (S: sig (T {seq, start, ...}, T {seq = seq', start = start', len = len'}) = if Primitive.Controls.safe andalso - (not (eq (seq, seq')) orelse start' +$ len' < start) + (not (eq (seq, seq')) orelse start' +! len' < start) then raise Span - else unsafeSlice (seq, start, SOME ((start' +$ len') -$ start)) + else unsafeSlice (seq, start, SOME ((start' +! len') -! start)) end local diff --git a/basis-library/integer/int-inf.sig b/basis-library/integer/int-inf.sig index 6574491516..c2f9149c80 100644 --- a/basis-library/integer/int-inf.sig +++ b/basis-library/integer/int-inf.sig @@ -34,10 +34,10 @@ signature INT_INF_EXTRA = val zero: int val one: int - val +? : int * int -> int - val *? : int * int -> int - val -? : int * int -> int - val ~? : int -> int + val +! : int * int -> int + val *! : int * int -> int + val -! : int * int -> int + val ~! : int -> int val ltu: int * int -> bool val leu: int * int -> bool diff --git a/basis-library/integer/int-inf0.sml b/basis-library/integer/int-inf0.sml index 331f2bb74e..1b6a2e4b82 100644 --- a/basis-library/integer/int-inf0.sml +++ b/basis-library/integer/int-inf0.sml @@ -31,23 +31,19 @@ signature PRIM_INT_INF = val areSmall: int * int -> bool val abs: int -> int - val +? : int * int -> int val +! : int * int -> int val + : int * int -> int val divMod: int * int -> int * int val div: int * int -> int val gcd: int * int -> int val mod: int * int -> int - val *? : int * int -> int val *! : int * int -> int val * : int * int -> int - val ~? : int -> int val ~! : int -> int val ~ : int -> int val quotRem: int * int -> int * int val quot: int * int -> int val rem: int * int -> int - val -? : int * int -> int val -! : int * int -> int val - : int * int -> int @@ -1324,23 +1320,19 @@ structure IntInf = val minInt = NONE val abs = bigAbs - val op +? = bigAdd val op +! = bigAdd val op + = bigAdd val divMod = bigDivMod val op div = bigDiv val gcd = bigGcd val op mod = bigMod - val op *? = bigMul val op *! = bigMul val op * = bigMul - val op ~? = bigNeg val op ~! = bigNeg val op ~ = bigNeg val quotRem = bigQuotRem val quot = bigQuot val rem = bigRem - val op -? = bigSub val op -! = bigSub val op - = bigSub From 724f1d19ff93607dac2f1a41ad742726f5c39436 Mon Sep 17 00:00:00 2001 From: Matthew Fluet Date: Mon, 10 Sep 2018 06:05:08 -0400 Subject: [PATCH 41/57] Correct initial refactoring of unchecked/checked arithmetic fs --- basis-library/arrays-and-vectors/array2.sml | 38 ++++++++++----------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/basis-library/arrays-and-vectors/array2.sml b/basis-library/arrays-and-vectors/array2.sml index 3ffb268a09..bbd4688892 100644 --- a/basis-library/arrays-and-vectors/array2.sml +++ b/basis-library/arrays-and-vectors/array2.sml @@ -10,11 +10,11 @@ structure Array2 : ARRAY2 = struct - val op +$ = SeqIndex.+$ + val op +! = SeqIndex.+! val op + = SeqIndex.+ - val op -$ = SeqIndex.-$ + val op -! = SeqIndex.-! val op - = SeqIndex.- - val op *$ = SeqIndex.*$ + val op *! = SeqIndex.*! val op * = SeqIndex.* val op < = SeqIndex.< val op <= = SeqIndex.<= @@ -66,12 +66,12 @@ structure Array2 : ARRAY2 = handle Overflow => raise Subscript in if (start < 0 orelse num < 0 - orelse start +$ num > max) + orelse start +! num > max) then raise Subscript - else (start, start +$ num) + else (start, start +! num) end else (SeqIndex.fromIntUnsafe start, - SeqIndex.fromIntUnsafe start +$ num) + SeqIndex.fromIntUnsafe start +! num) fun checkSliceMax (start: int, num: int option, max: SeqIndex.int): SeqIndex.int * SeqIndex.int = @@ -147,7 +147,7 @@ structure Array2 : ARRAY2 = cols = 0} fun unsafeSpot' ({cols, ...}: 'a array, r, c) = - r *$ cols +$ c + r *! cols +! c fun spot' (a as {rows, cols, ...}: 'a array, r, c) = if Primitive.Controls.safe andalso (geu (r, rows) orelse geu (c, cols)) @@ -197,13 +197,13 @@ structure Array2 : ARRAY2 = List.foldl (fn (row: 'a list, i) => let - val max = i +$ cols' + val max = i +! cols' val i' = List.foldl (fn (x: 'a, i) => (if i >= max then raise Size else (Primitive.Array.unsafeUpdate (array, i, x) - ; i +$ 1))) + ; i +! 1))) i row in if i' = max then i' @@ -218,7 +218,7 @@ structure Array2 : ARRAY2 = if Primitive.Controls.safe andalso geu (r, rows) then raise Subscript else - ArraySlice.vector (Primitive.Array.Slice.slice (array, r *$ cols, SOME cols)) + ArraySlice.vector (Primitive.Array.Slice.slice (array, r *! cols, SOME cols)) fun row (a, r) = if Primitive.Controls.safe then let @@ -257,9 +257,9 @@ structure Array2 : ARRAY2 = else let fun loopCol (c, b) = if c >= stopCol then b - else loopCol (c +$ 1, f (r, c, sub' (base, r, c), b)) + else loopCol (c +! 1, f (r, c, sub' (base, r, c), b)) in - loopRow (r +$ 1, loopCol (startCol, b)) + loopRow (r +! 1, loopCol (startCol, b)) end in loopRow (startRow, b) @@ -271,9 +271,9 @@ structure Array2 : ARRAY2 = else let fun loopRow (r, b) = if r >= stopRow then b - else loopRow (r +$ 1, f (r, c, sub' (base, r, c), b)) + else loopRow (r +! 1, f (r, c, sub' (base, r, c), b)) in - loopCol (c +$ 1, loopRow (startRow, b)) + loopCol (c +! 1, loopRow (startRow, b)) end in loopCol (startCol, b) @@ -310,8 +310,8 @@ structure Array2 : ARRAY2 = dst, dst_row, dst_col} = let val {startRow, stopRow, startCol, stopCol} = checkRegion src - val nrows = stopRow -$ startRow - val ncols = stopCol -$ startCol + val nrows = stopRow -! startRow + val ncols = stopCol -! startCol val {startRow = dst_row, startCol = dst_col, ...} = checkRegion' {base = dst, row = dst_row, col = dst_col, nrows = SOME nrows, @@ -330,13 +330,13 @@ structure Array2 : ARRAY2 = if i < start then () else (f i; loop (i - 1)) - in loop (stop -$ 1) + in loop (stop -! 1) end val forRows = if startRow <= dst_row then forDown else forUp val forCols = if startCol <= dst_col then forUp else forDown in forRows (0, nrows, fn r => forCols (0, ncols, fn c => - unsafeUpdate' (dst, dst_row +$ r, dst_col +$ c, - unsafeSub' (base, startRow +$ r, startCol +$ c)))) + unsafeUpdate' (dst, dst_row +! r, dst_col +! c, + unsafeSub' (base, startRow +! r, startCol +! c)))) end end From 83d69553a2bd78f63c60e5d6a1b093c97e429f2e Mon Sep 17 00:00:00 2001 From: Matthew Fluet Date: Mon, 10 Sep 2018 06:06:30 -0400 Subject: [PATCH 42/57] Alphabetize symbols in `include/amd64-main.h` --- include/amd64-main.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/amd64-main.h b/include/amd64-main.h index 81954b50e9..3b75f48481 100644 --- a/include/amd64-main.h +++ b/include/amd64-main.h @@ -23,10 +23,10 @@ PRIVATE Word64 fpcvtTemp; PRIVATE Word32 fpeqTemp; PRIVATE Word64 divTemp; PRIVATE Word64 indexTemp; +PRIVATE Word64 overflowCheckTemp; PRIVATE Word64 raTemp1; PRIVATE Word64 spill[32]; PRIVATE Word64 stackTopTemp; -PRIVATE Word64 overflowCheckTemp; #ifndef DEBUG_AMD64CODEGEN #define DEBUG_AMD64CODEGEN FALSE From 315ccce3ed2a40cb52a1beb2e80647fd4105a2f6 Mon Sep 17 00:00:00 2001 From: Matthew Fluet Date: Mon, 10 Sep 2018 06:07:17 -0400 Subject: [PATCH 43/57] Avoid using `@llvm.{s,u}mul.with.overflow.i64` on x86entrytransfer Like `Word_mulCheck`, `Word_mulCheckP` should not use the `@llvm.{s,u}mul.with.overflow.i64` intrinsics, because they compile to calls to `__mulodi4` and `__udivdi3`, which are provided by compiler-rt and not always by libgcc. --- mlton/codegen/llvm-codegen/llvm-codegen.fun | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/mlton/codegen/llvm-codegen/llvm-codegen.fun b/mlton/codegen/llvm-codegen/llvm-codegen.fun index 5a2f549f09..fc3362c8d6 100644 --- a/mlton/codegen/llvm-codegen/llvm-codegen.fun +++ b/mlton/codegen/llvm-codegen/llvm-codegen.fun @@ -171,7 +171,16 @@ fun implementsPrim (p: 'a Prim.t): bool = *) not (WordSize.equals (ws, WordSize.word64)) | _ => true) - | Word_mulCheckP _ => true (* TODO? *) + | Word_mulCheckP (ws, _) => + (case (!Control.Target.arch, ws) of + (Control.Target.X86, ws) => + (* @llvm.smul.with.overflow.i64 becomes a call to __mulodi4. + * @llvm.umul.with.overflow.i64 becomes a call to __udivdi3. + * These are provided by compiler-rt and not always by libgcc. + * In any case, do not depend on non-standard libraries. + *) + not (WordSize.equals (ws, WordSize.word64)) + | _ => true) | Word_neg _ => true | Word_negCheck _ => true | Word_negCheckP _ => true From a1a4c0f00bcd3086b5435e81750ac38f850d9897 Mon Sep 17 00:00:00 2001 From: Matthew Fluet Date: Mon, 10 Sep 2018 06:09:42 -0400 Subject: [PATCH 44/57] Remove superfluous `elimALRedundant_pseudo` optimization The `elimALRedundant_pseudo` peephole optimization was removed from the amd64 codegen by 56d4362, but should also be removed from the x86 codegen. --- mlton/codegen/x86-codegen/x86-simplify.fun | 108 --------------------- 1 file changed, 108 deletions(-) diff --git a/mlton/codegen/x86-codegen/x86-simplify.fun b/mlton/codegen/x86-codegen/x86-simplify.fun index 992ac2ab58..c660396a4c 100644 --- a/mlton/codegen/x86-codegen/x86-simplify.fun +++ b/mlton/codegen/x86-codegen/x86-simplify.fun @@ -3183,112 +3183,6 @@ struct val elimALCopy_msg = elimALCopy_msg end - local - fun isInstructionMOV_aux (check) : statement_type -> bool - = fn (Assembly.Instruction (Instruction.MOV - {dst = Operand.MemLoc memloc, ...}), - _) - => check memloc - | _ => false - - val isInstructionMOV = isInstructionMOV_aux (fn _ => true) - val isInstructionMOV_dstTemp = isInstructionMOV_aux x86Liveness.track - - fun isInstructionBinAL_aux (check) : statement_type -> bool - = fn (Assembly.Instruction (Instruction.BinAL - {dst = Operand.MemLoc memloc, ...}), - _) - => check memloc - | _ => false - - val isInstructionBinAL = isInstructionBinAL_aux (fn _ => true) - - fun isDeadTemp dead memloc - = x86Liveness.track memloc andalso LiveSet.contains (dead, memloc) - val isInstructionBinAL_dstDeadTemp : statement_type -> bool - = fn (instr, liveness as Liveness.T {dead, ...}) - => isInstructionBinAL_aux (isDeadTemp dead) (instr, liveness) - - val template : template - = {start = EmptyOrNonEmpty, - statements = [One isInstructionMOV, - All isComment, - One isInstructionBinAL, - All isComment, - One isInstructionMOV_dstTemp, - All isComment, - One isInstructionBinAL_dstDeadTemp], - finish = EmptyOrNonEmpty, - transfer = fn _ => true} - - val rewriter : rewriter - = fn {entry, - profileLabel, - start, - statements = - [[(stmtMov as Assembly.Instruction (Instruction.MOV - {src = src1x, - dst = dst1z, ...}), - _)], - comments1, - [(stmtAL as Assembly.Instruction (Instruction.BinAL - {src = src1, - dst = dst1, ...}), - _)], - comments2, - [(Assembly.Instruction (Instruction.MOV - {src = src2x, - dst = dst2z, ...}), - _)], - comments3, - [(Assembly.Instruction (Instruction.BinAL - {src = src2, - dst = dst2, ...}), - Liveness.T {liveOut = liveOut2, ...})]], - finish, - transfer} - => if !Control.Native.elimALRedundant andalso - Operand.eq (src1x, src2x) andalso - Operand.eq (src1, dst1) andalso - Operand.eq (src2, dst2) andalso - Operand.eq (dst1z, src1) andalso - Operand.eq (dst2z, src2) - then - let - val excomm = fn comm => List.map (comm, fn (c, _) => c) - val comments1 = excomm comments1 - val comments2 = excomm comments2 - val comments3 = excomm comments3 - - val statements = - stmtMov::(comments1 @ (stmtAL::(comments2 @ comments3))) - val {statements, ...} - = LivenessBlock.toLivenessStatements - {statements = statements, live = liveOut2} - val statements - = List.fold (start, - List.concat [statements, finish], - op ::) - in - SOME (LivenessBlock.T - {entry = entry, - profileLabel = profileLabel, - statements = statements, - transfer = transfer}) - end - else NONE - | _ => Error.bug "x86Simplify.PeepholeBlock: elimALRedundant_pseudo" - - val (callback, elimALRedundant_pseudo_msg) - = make_callback_msg "elimALRedundant_pseudo" - in - val elimALRedundant_pseudo : optimization - = {template = template, - rewriter = rewriter, - callback = callback} - val elimALRedundant_pseudo_msg = elimALRedundant_pseudo_msg - end - local fun isInstructionMOV_aux (check) : statement_type -> bool = fn (Assembly.Instruction (Instruction.MOV @@ -4323,11 +4217,9 @@ struct local val optimizations_pre = elimALRedundant:: - elimALRedundant_pseudo:: nil val optimizations_pre_msg = elimALRedundant_msg:: - elimALRedundant_pseudo_msg:: nil val optimizations From df2e9e111d29ff83a3c2e63231f442291f758b38 Mon Sep 17 00:00:00 2001 From: Matthew Fluet Date: Mon, 10 Sep 2018 06:11:06 -0400 Subject: [PATCH 45/57] Delete trailing whitespace --- mlton/atoms/prim.fun | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mlton/atoms/prim.fun b/mlton/atoms/prim.fun index 485dc9b10c..ebb1a0b991 100644 --- a/mlton/atoms/prim.fun +++ b/mlton/atoms/prim.fun @@ -956,7 +956,7 @@ val kind: 'a t -> Kind.t = | Word_lt _ => Functional | Word_mul _ => Functional | Word_mulCheck _ => SideEffect - | Word_mulCheckP _ => Functional + | Word_mulCheckP _ => Functional | Word_neg _ => Functional | Word_negCheck _ => SideEffect | Word_negCheckP _ => Functional From cf7c3a72a693af4c0d8e6505fc22748bb2b101b9 Mon Sep 17 00:00:00 2001 From: Matthew Fluet Date: Mon, 10 Sep 2018 06:11:56 -0400 Subject: [PATCH 46/57] Tweak code formatting and style --- mlton/atoms/prim.fun | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/mlton/atoms/prim.fun b/mlton/atoms/prim.fun index ebb1a0b991..3abc04024d 100644 --- a/mlton/atoms/prim.fun +++ b/mlton/atoms/prim.fun @@ -2056,9 +2056,10 @@ fun ('a, 'b) apply (p: 'a t, else Unknown | Word_add _ => add () | Word_addCheck _ => add () - | Word_addCheckP _ => if WordX.isZero w - then f - else Unknown + | Word_addCheckP _ => + if WordX.isZero w + then f + else Unknown | Word_andb s => if WordX.isZero w then zero s @@ -2072,9 +2073,10 @@ fun ('a, 'b) apply (p: 'a t, else if WordX.isMax (w, sg) then f else Unknown | Word_mul s => mul (s, wordNeg) | Word_mulCheck s => mul (s, wordNegCheck) - | Word_mulCheckP _ => if WordX.isZero w orelse WordX.isOne w - then f - else Unknown + | Word_mulCheckP _ => + if WordX.isZero w orelse WordX.isOne w + then f + else Unknown | Word_orb _ => if WordX.isZero w then Var x @@ -2110,9 +2112,10 @@ fun ('a, 'b) apply (p: 'a t, shift s | Word_sub s => sub (s, wordNeg) | Word_subCheck s => sub (s, wordNegCheck o #1) - | Word_subCheckP _ => if WordX.isZero w andalso inOrder - then f - else Unknown + | Word_subCheckP _ => + if WordX.isZero w andalso inOrder + then f + else Unknown | Word_xorb s => if WordX.isZero w then Var x From 939e827525eb17a48164a50bd1ba9e89cbb1dd19 Mon Sep 17 00:00:00 2001 From: Matthew Fluet Date: Mon, 10 Sep 2018 06:12:15 -0400 Subject: [PATCH 47/57] Refactor to share code for simplifying arithmetic check primitives --- mlton/atoms/prim.fun | 37 ++++++++++++++++--------------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/mlton/atoms/prim.fun b/mlton/atoms/prim.fun index 3abc04024d..d2a82a5700 100644 --- a/mlton/atoms/prim.fun +++ b/mlton/atoms/prim.fun @@ -1683,27 +1683,22 @@ fun ('a, 'b) apply (p: 'a t, if WordSize.isInRange (s, w, sg) then word (WordX.fromIntInf (w, s)) else ApplyResult.Overflow - fun wcheck (f: IntInf.t * IntInf.t -> IntInf.t, - (s: WordSize.t, sg as {signed}), - w: WordX.t, - w': WordX.t) = - let - val conv = if signed then WordX.toIntInfX else WordX.toIntInf - in - wordOrOverflow (s, sg, f (conv w, conv w')) - end - fun wordOrTrue (s, sg, w) = if WordSize.isInRange (s, w, sg) - then f - else t - fun wcheckp (f: IntInf.t * IntInf.t -> IntInf.t, - (s: WordSize.t, sg as {signed}), - w: WordX.t, - w': WordX.t) = - let - val conv = if signed then WordX.toIntInfX else WordX.toIntInf - in - wordOrTrue (s, sg, f (conv w, conv w')) - end + fun wordOrTrue (s, sg, w) = bool (not (WordSize.isInRange (s, w, sg))) + local + fun mkCheck toAppRes = + fn (f: IntInf.t * IntInf.t -> IntInf.t, + (s: WordSize.t, sg as {signed}), + w: WordX.t, + w': WordX.t) => + let + val conv = if signed then WordX.toIntInfX else WordX.toIntInf + in + toAppRes (s, sg, f (conv w, conv w')) + end + in + val wcheck = mkCheck wordOrOverflow + val wcheckp = mkCheck wordOrTrue + end val eq = fn (Word w1, Word w2) => bool (WordX.equals (w1, w2)) | _ => ApplyResult.Unknown From 9666e8ac4f0a6db673406e4fd59edf2d7a55bb10 Mon Sep 17 00:00:00 2001 From: Matthew Fluet Date: Mon, 10 Sep 2018 06:13:10 -0400 Subject: [PATCH 48/57] Share code for type-checking comparisons and overflow-checking prims --- mlton/backend/rep-type.fun | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/mlton/backend/rep-type.fun b/mlton/backend/rep-type.fun index 273c0e40da..36fbcea1cc 100644 --- a/mlton/backend/rep-type.fun +++ b/mlton/backend/rep-type.fun @@ -582,15 +582,11 @@ fun checkPrimApp {args, prim, result} = val realBinary = make real val wordBinary = make wordOrBitsOrSeq end - local - fun make f s = let val t = f s in done ([t, t], SOME bool) end - in - val wordBinaryP = make wordOrBitsOrSeq - end local fun make f s = let val t = f s in done ([t, t], SOME bool) end in val realCompare = make real + val wordBinaryP = make wordOrBitsOrSeq val wordCompare = make wordOrBitsOrSeq val objptrCompare = make (fn _ => objptr) () end From a720283930c62a5fab10fc3df4b77a6d0faacd0f Mon Sep 17 00:00:00 2001 From: Matthew Fluet Date: Mon, 10 Sep 2018 06:14:54 -0400 Subject: [PATCH 49/57] Code formatting --- mlton/codegen/amd64-codegen/amd64-mlton-basic.fun | 1 + 1 file changed, 1 insertion(+) diff --git a/mlton/codegen/amd64-codegen/amd64-mlton-basic.fun b/mlton/codegen/amd64-codegen/amd64-mlton-basic.fun index 99281b83aa..7828aee684 100644 --- a/mlton/codegen/amd64-codegen/amd64-mlton-basic.fun +++ b/mlton/codegen/amd64-codegen/amd64-mlton-basic.fun @@ -231,6 +231,7 @@ struct class = Classes.StaticTemp} fun fpeqTempContentsOperand size = Operand.memloc (fpeqTempContents size) + val overflowCheckTemp = Label.fromString "overflowCheckTemp" fun overflowCheckTempContents size = makeContents {base = Immediate.label overflowCheckTemp, From ce4352da076da5e534e49f1516d806e0b754ced4 Mon Sep 17 00:00:00 2001 From: Matthew Fluet Date: Thu, 13 Sep 2018 13:05:02 -0400 Subject: [PATCH 50/57] Fix `#undef Word_negCheckP` (had been `#undef WordS_negCheckP`) --- runtime/basis/Word/Word-check.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/basis/Word/Word-check.h b/runtime/basis/Word/Word-check.h index 581f63a994..4a5105e5d4 100644 --- a/runtime/basis/Word/Word-check.h +++ b/runtime/basis/Word/Word-check.h @@ -131,7 +131,7 @@ all(64) #undef all #undef WordS_subCheckP -#undef WordS_negCheckP +#undef Word_negCheckP #undef WordU_mulCheckP #undef WordS_mulCheckP #undef WordU_addCheckP From b91bb9a1cfecda29dbd57c5ead0338e9ee4e2337 Mon Sep 17 00:00:00 2001 From: Matthew Fluet Date: Thu, 13 Sep 2018 13:08:31 -0400 Subject: [PATCH 51/57] Fix translation of `Word_*Check` primitives to C functions Commit f9e1cb6 renamed the `Word_*CheckOverflows` C functions to `Word_*CheckP` C functions. --- mlton/backend/ssa-to-rssa.fun | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/mlton/backend/ssa-to-rssa.fun b/mlton/backend/ssa-to-rssa.fun index 4a59a6fa80..5f85b5b1f4 100644 --- a/mlton/backend/ssa-to-rssa.fun +++ b/mlton/backend/ssa-to-rssa.fun @@ -466,17 +466,17 @@ structure Name = prototype = (Vector.new (n, ct), SOME ct), return = t} end - fun makeOverflows n (s, sg) = + fun makeCheck n (s, sg) = let val t = word s val ct = CType.word (s, sg) in vanilla {args = Vector.new (n, t), - name = name ^ "Overflows", + name = name ^ "P", prototype = (Vector.new (n, ct), SOME CType.bool), return = Type.bool} end - fun makeP n (s, sg) = + fun makeCheckP n (s, sg) = let val t = word s val ct = CType.word (s, sg) @@ -486,14 +486,13 @@ structure Name = prototype = (Vector.new (n, ct), SOME CType.bool), return = Type.bool} end - in val wordBinary = make 2 - val wordBinaryOverflows = makeOverflows 2 - val wordBinaryP = makeP 2 + val wordBinaryCheck = makeCheck 2 + val wordBinaryCheckP = makeCheckP 2 val wordUnary = make 1 - val wordUnaryOverflows = makeOverflows 1 - val wordUnaryP = makeP 1 + val wordUnaryCheck = makeCheck 1 + val wordUnaryCheckP = makeCheckP 1 end fun wordCompare (s, sg) = let @@ -563,8 +562,8 @@ structure Name = | Real_sub s => realBinary s | Thread_returnToC => CFunction.returnToC () | Word_add s => wordBinary (s, {signed = false}) - | Word_addCheck (s, sg) => wordBinaryOverflows (s, sg) - | Word_addCheckP (s, sg) => wordBinaryP (s, sg) + | Word_addCheck (s, sg) => wordBinaryCheck (s, sg) + | Word_addCheckP (s, sg) => wordBinaryCheckP (s, sg) | Word_andb s => wordBinary (s, {signed = false}) | Word_castToReal (s1, s2) => coerce (word s1, wordCType (s1, {signed = false}), @@ -576,11 +575,11 @@ structure Name = | Word_lshift s => wordShift (s, {signed = false}) | Word_lt z => wordCompare z | Word_mul z => wordBinary z - | Word_mulCheck (s, sg) => wordBinaryOverflows (s, sg) - | Word_mulCheckP (s, sg) => wordBinaryP (s, sg) + | Word_mulCheck (s, sg) => wordBinaryCheck (s, sg) + | Word_mulCheckP (s, sg) => wordBinaryCheckP (s, sg) | Word_neg s => wordUnary (s, {signed = true}) - | Word_negCheck s => wordUnaryOverflows (s, {signed = true}) - | Word_negCheckP s => wordUnaryP (s, {signed = true}) + | Word_negCheck s => wordUnaryCheck (s, {signed = true}) + | Word_negCheckP s => wordUnaryCheckP (s, {signed = true}) | Word_notb s => wordUnary (s, {signed = false}) | Word_orb s => wordBinary (s, {signed = false}) | Word_quot z => wordBinary z @@ -593,8 +592,8 @@ structure Name = | Word_ror s => wordShift (s, {signed = false}) | Word_rshift z => wordShift z | Word_sub s => wordBinary (s, {signed = false}) - | Word_subCheck (s, sg) => wordBinaryOverflows (s, sg) - | Word_subCheckP (s, sg) => wordBinaryP (s, sg) + | Word_subCheck (s, sg) => wordBinaryCheck (s, sg) + | Word_subCheckP (s, sg) => wordBinaryCheckP (s, sg) | _ => Error.bug "SsaToRssa.Name.cFunctionRaise" end From eda6021848af7cec8711da5152f06147fe6c330f Mon Sep 17 00:00:00 2001 From: Matthew Fluet Date: Mon, 17 Sep 2018 09:59:57 -0400 Subject: [PATCH 52/57] Fix x86-codegen translation of `Word64_{add,sub,neg}CheckP` prims Addition, subtraction, and negation of 64bit operands on a 32bit platform must first add/sub the low bits and then addc/subb the high bits in order to correctly set the overflow flag. However, this does not yet pass all the regression tests: testing fixed-integer 15a16,21 > Int64: abs ~9223372036854775807 = Overflow <> 9223372036854775807 > Int64: ~ ~9223372036854775807 = Overflow <> 9223372036854775807 > Int64: fromString o toString 9223372036854775807 = Overflow <> 9223372036854775807 > Int64: fromString o toString 9223372036854775806 = Overflow <> 9223372036854775806 > unhandled exception: Overflow > Nonzero exit status. fixed-integer: difference with -type-check true -const MLton.newOverflow true --- mlton/codegen/x86-codegen/x86-mlton.fun | 45 +++++++++++++++---------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/mlton/codegen/x86-codegen/x86-mlton.fun b/mlton/codegen/x86-codegen/x86-mlton.fun index 2829770e3e..0a2ed37f3e 100644 --- a/mlton/codegen/x86-codegen/x86-mlton.fun +++ b/mlton/codegen/x86-codegen/x86-mlton.fun @@ -369,16 +369,19 @@ struct transfer = NONE}] end - fun binal64cc (oper, condition) + fun binal64cc (oper1, oper2, condition) = let - val ((src1,src1size), _, - (src3,src3size), _) = getSrc4 () + val ((src1,src1size), + (src2,src2size), + (src3,src3size), + (src4,src4size)) = getSrc4 () val (dst,dstsize) = getDst1 () val tmp = overflowCheckTempContentsOperand src1size val _ = Assert.assert - ("x86MLton.prim: binal64cc, src1size/src3size", - fn () => src1size = src3size) + ("x86MLton.prim: binal64cc, src1size/src2size/src3size/src4size", + fn () => src1size = src3size andalso + src2size = src4size) in AppendList.fromList [Block.mkBlock' @@ -389,10 +392,19 @@ struct src = src1, size = src1size}, Assembly.instruction_binal - {oper = oper, + {oper = oper1, dst = tmp, src = src3, size = src1size}, + Assembly.instruction_mov + {dst = tmp, + src = src2, + size = src2size}, + Assembly.instruction_binal + {oper = oper2, + dst = tmp, + src = src4, + size = src2size}, Assembly.instruction_setcc {condition = condition, dst = dst, @@ -611,29 +623,28 @@ struct = Assert.assert ("x86MLton.prim: neg64cc, src1size/src2size", fn () => src1size = src2size) - val tdst1 = wordTemp1ContentsOperand src1size - val tdst2 = wordTemp1ContentsOperand src2size + val tmp = overflowCheckTempContentsOperand src1size in AppendList.fromList [Block.mkBlock' {entry = NONE, statements = [Assembly.instruction_mov - {dst = tdst1, + {dst = tmp, src = Operand.immediate_zero, size = src1size}, - Assembly.instruction_mov - {dst = tdst2, - src = Operand.immediate_zero, - size = src2size}, Assembly.instruction_binal {oper = Instruction.SUB, - dst = tdst1, + dst = tmp, src = src1, size = src1size}, + Assembly.instruction_mov + {dst = tmp, + src = Operand.immediate_zero, + size = src2size}, Assembly.instruction_binal {oper = Instruction.SBB, - dst = tdst2, + dst = tmp, src = src2, size = src2size}, Assembly.instruction_setcc @@ -1602,7 +1613,7 @@ struct W8 => binalcc (Instruction.ADD, cond) | W16 => binalcc (Instruction.ADD, cond) | W32 => binalcc (Instruction.ADD, cond) - | W64 => binal64cc (Instruction.ADD, cond) + | W64 => binal64cc (Instruction.ADD, Instruction.ADC, cond) end | Word_andb s => bitop (s, Instruction.AND) | Word_equal _ => cmp Instruction.E @@ -1676,7 +1687,7 @@ struct W8 => binalcc (Instruction.SUB, cond) | W16 => binalcc (Instruction.SUB, cond) | W32 => binalcc (Instruction.SUB, cond) - | W64 => binal64cc (Instruction.SUB, cond) + | W64 => binal64cc (Instruction.SUB, Instruction.SBB, cond) end | Word_rndToReal (s, s', _) => let From 97315a4a4c928350640e41b8622e2745ae8d63fd Mon Sep 17 00:00:00 2001 From: Matthew Fluet Date: Thu, 11 Oct 2018 22:07:54 -0400 Subject: [PATCH 53/57] Fix `elimDeadDsts` peephole optimization in native codegens The `elimDeadDsts` peephole optimization attempts to eliminate instructions whose destinations are dead. There was limited code for preserving instructions that are immediately followed by a `setcc` instruction or a `if` transfer. However, it did not preserve instructions that were immediately followed by an `adc` or `sbb` instruction. This would lead to mis-compilation of `Word64_{add,neg,sub}CheckP` primitives. For example, a `Word64_addCheckP` could initially be translated to: movl src1Lo,tmpLo movl src1Hi,tmpHi addl src2Lo,tmpLo adcl src2Hi,tmpHi seto dst The "tmpLo" destination in the "addl src2Lo,tmpLo" instruction is dead and so the instruction would be eliminated; in turn, the "tmpLo" destination in the "movl src1Lo,tmpLo" instruction is dead and so the instruction would be eliminated. However, although the "tmpHi" destination in the "adcl src2Hi,tmpHi" instruction is dead, the instruction is preserved because of the subsequent "seto" instruction. The end result would be: movl src1Hi,tmpHi adcl src2Hi,tmpHi seto dst which fails to set "dst" appropriately. Now, in addition to preserving instructions that are immediately followed by a `setcc` instruction or an `if` transfer, an instruction immediately preserved by a `adc` or `sbb` instruction is preserved. --- mlton/codegen/amd64-codegen/amd64-simplify.fun | 6 ++++++ mlton/codegen/x86-codegen/x86-simplify.fun | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/mlton/codegen/amd64-codegen/amd64-simplify.fun b/mlton/codegen/amd64-codegen/amd64-simplify.fun index 1f373f0062..683dce2cc7 100644 --- a/mlton/codegen/amd64-codegen/amd64-simplify.fun +++ b/mlton/codegen/amd64-codegen/amd64-simplify.fun @@ -2847,6 +2847,12 @@ struct (finish, (false, false), fn ((asm, _), (b, b')) => case asm of Assembly.Comment _ => (b, b') + | Assembly.Instruction + (Instruction.BinAL {oper = Instruction.ADC, ...}) + => (true, if b then b' else true) + | Assembly.Instruction + (Instruction.BinAL {oper = Instruction.SBB, ...}) + => (true, if b then b' else true) | Assembly.Instruction (Instruction.SETcc _) => (true, if b then b' else true) diff --git a/mlton/codegen/x86-codegen/x86-simplify.fun b/mlton/codegen/x86-codegen/x86-simplify.fun index c660396a4c..763c3d6c41 100644 --- a/mlton/codegen/x86-codegen/x86-simplify.fun +++ b/mlton/codegen/x86-codegen/x86-simplify.fun @@ -2941,6 +2941,12 @@ struct (finish, (false, false), fn ((asm, _), (b, b')) => case asm of Assembly.Comment _ => (b, b') + | Assembly.Instruction + (Instruction.BinAL {oper = Instruction.ADC, ...}) + => (true, if b then b' else true) + | Assembly.Instruction + (Instruction.BinAL {oper = Instruction.SBB, ...}) + => (true, if b then b' else true) | Assembly.Instruction (Instruction.SETcc _) => (true, if b then b' else true) From 5b9520e112a2bf6e38be8c4d7ad5e1addf208e9c Mon Sep 17 00:00:00 2001 From: Matthew Fluet Date: Thu, 11 Oct 2018 22:18:19 -0400 Subject: [PATCH 54/57] Whitespace fixes --- mlton/codegen/x86-codegen/x86-mlton.fun | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/mlton/codegen/x86-codegen/x86-mlton.fun b/mlton/codegen/x86-codegen/x86-mlton.fun index 0a2ed37f3e..fd4972f72c 100644 --- a/mlton/codegen/x86-codegen/x86-mlton.fun +++ b/mlton/codegen/x86-codegen/x86-mlton.fun @@ -412,7 +412,6 @@ struct transfer = NONE}] end - fun pmd oper = let val ((src1,src1size), @@ -462,7 +461,7 @@ struct val ((src1,src1size), (src2,src2size)) = getSrc2 () val (dst,dstsize) = getDst1 () - val tmp= overflowCheckTempContentsOperand src1size + val tmp = overflowCheckTempContentsOperand src1size val _ = Assert.assert ("x86MLton.prim: pmdcc, src1size/src2size", @@ -550,7 +549,7 @@ struct val ((src1,src1size), (src2,src2size)) = getSrc2 () val (dst,dstsize) = getDst1 () - val tmp= overflowCheckTempContentsOperand src1size + val tmp = overflowCheckTempContentsOperand src1size val _ = Assert.assert ("x86MLton.prim: imul2, src1size/src2size", From 3a0a42d080fbb96f242ba7a7be7ebb9890587ff6 Mon Sep 17 00:00:00 2001 From: Matthew Fluet Date: Thu, 11 Oct 2018 22:25:28 -0400 Subject: [PATCH 55/57] Strengthen `elimAddSub1` and `elimDeadDsts` peephole optimizations A `mov` instruction does not change the condition code flags, so continue looking for flag-dependent instructions past a `mov` instruction. --- mlton/codegen/amd64-codegen/amd64-simplify.fun | 6 ++++++ mlton/codegen/x86-codegen/x86-simplify.fun | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/mlton/codegen/amd64-codegen/amd64-simplify.fun b/mlton/codegen/amd64-codegen/amd64-simplify.fun index 683dce2cc7..7401c88d14 100644 --- a/mlton/codegen/amd64-codegen/amd64-simplify.fun +++ b/mlton/codegen/amd64-codegen/amd64-simplify.fun @@ -561,6 +561,9 @@ struct (Instruction.BinAL {oper = Instruction.SBB, ...}) => (true, if b then b' else true) + | Assembly.Instruction + (Instruction.MOV _) + => (b, b') | Assembly.Instruction (Instruction.SETcc {condition = Instruction.C, ...}) @@ -2853,6 +2856,9 @@ struct | Assembly.Instruction (Instruction.BinAL {oper = Instruction.SBB, ...}) => (true, if b then b' else true) + | Assembly.Instruction + (Instruction.MOV _) + => (b, b') | Assembly.Instruction (Instruction.SETcc _) => (true, if b then b' else true) diff --git a/mlton/codegen/x86-codegen/x86-simplify.fun b/mlton/codegen/x86-codegen/x86-simplify.fun index 763c3d6c41..5336db5293 100644 --- a/mlton/codegen/x86-codegen/x86-simplify.fun +++ b/mlton/codegen/x86-codegen/x86-simplify.fun @@ -655,6 +655,9 @@ struct (Instruction.BinAL {oper = Instruction.SBB, ...}) => (true, if b then b' else true) + | Assembly.Instruction + (Instruction.MOV _) + => (b, b') | Assembly.Instruction (Instruction.SETcc {condition = Instruction.C, ...}) @@ -2947,6 +2950,9 @@ struct | Assembly.Instruction (Instruction.BinAL {oper = Instruction.SBB, ...}) => (true, if b then b' else true) + | Assembly.Instruction + (Instruction.MOV _) + => (b, b') | Assembly.Instruction (Instruction.SETcc _) => (true, if b then b' else true) From 14df405d15667af51c041ec68eb172fdee960cd0 Mon Sep 17 00:00:00 2001 From: Matthew Fluet Date: Thu, 11 Oct 2018 22:44:21 -0400 Subject: [PATCH 56/57] Fix x86-codegen translation of `Word64_{add,neg,sub}CheckP` prims Previously, a `Word64_negCheckP` was initially translated to: movl $0,tmp subl srcLo,tmp movl $0,tmp sbbl srcHi,tmp seto dst With commits 97315a4 and 3a0a42d, the "subl srcLo,tmp" instruction is not eliminated by the `elimDeadDsts` peephole optimization. However, register allocation unconditionally rewrites `movl $0,dst` as `xorl dst,dst`, leaving code like: xorl tmp,tmp subl srcLo,tmp xorl tmp,tmp sbbl srcHi,tmp However, while a `mov` preserves the condition code flags, a `xorl` instruction clears the CF flag, which leads to incorrect flags being used and set by the `sbb` instruction. Similarly, a `Word64_addCheckP` was initially translated to: movl src1Lo,tmp addl src2Lo,tmp movl src1Hi,tmp adcl src2Hi,tmp seto dst which, if src1Hi were 0, would result in movl src1Lo,tmp addl src2Lo,tmp xorl tmp,tmp adcl src2Hi,tmp which leads to incorrect flags being used and set by the `adc` instruction. The existing 64-bit primitives avoid this problem by performing all of the `mov` instructions before the arithmetic instruction. Now, a `Word64_negCheckP` primitive is initially translated to: movl $0,tmpLo movl $0,tmpHi subl srcLo,tmpLo sbbl srcHi,tmpHi seto dst which can be correctly rewritten to: xorl tmpLo,tmpLo xorl tmpHi,tmpHi subl srcLo,tmpLo sbbl srcHi,tmpHi seto dst and a `Word64_addCheckP` primitive is initially translated to: movl src1Lo,tmpLo movl src1Hi,tmpHi addl src2Lo,tmpLo adcl src2Hi,tmpHi seto dst which, if src1Hi were 0, can be correctly rewritten to: movl src1Lo,tmpLo xorl tmpHi,tmpHi addl src2Lo,tmpLo adcl src2Hi,tmpHi --- mlton/codegen/x86-codegen/x86-mlton.fun | 34 +++++++++++++------------ 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/mlton/codegen/x86-codegen/x86-mlton.fun b/mlton/codegen/x86-codegen/x86-mlton.fun index fd4972f72c..a3c0886ed1 100644 --- a/mlton/codegen/x86-codegen/x86-mlton.fun +++ b/mlton/codegen/x86-codegen/x86-mlton.fun @@ -376,7 +376,8 @@ struct (src3,src3size), (src4,src4size)) = getSrc4 () val (dst,dstsize) = getDst1 () - val tmp = overflowCheckTempContentsOperand src1size + val tmp1 = overflowCheckTempContentsOperand src1size + val tmp2 = wordTemp1ContentsOperand src2size val _ = Assert.assert ("x86MLton.prim: binal64cc, src1size/src2size/src3size/src4size", @@ -388,21 +389,21 @@ struct {entry = NONE, statements = [Assembly.instruction_mov - {dst = tmp, + {dst = tmp1, src = src1, size = src1size}, + Assembly.instruction_mov + {dst = tmp2, + src = src2, + size = src2size}, Assembly.instruction_binal {oper = oper1, - dst = tmp, + dst = tmp1, src = src3, size = src1size}, - Assembly.instruction_mov - {dst = tmp, - src = src2, - size = src2size}, Assembly.instruction_binal {oper = oper2, - dst = tmp, + dst = tmp2, src = src4, size = src2size}, Assembly.instruction_setcc @@ -622,28 +623,29 @@ struct = Assert.assert ("x86MLton.prim: neg64cc, src1size/src2size", fn () => src1size = src2size) - val tmp = overflowCheckTempContentsOperand src1size + val tmp1 = overflowCheckTempContentsOperand src1size + val tmp2 = wordTemp1ContentsOperand src2size in AppendList.fromList [Block.mkBlock' {entry = NONE, statements = [Assembly.instruction_mov - {dst = tmp, + {dst = tmp1, src = Operand.immediate_zero, size = src1size}, + Assembly.instruction_mov + {dst = tmp2, + src = Operand.immediate_zero, + size = src2size}, Assembly.instruction_binal {oper = Instruction.SUB, - dst = tmp, + dst = tmp1, src = src1, size = src1size}, - Assembly.instruction_mov - {dst = tmp, - src = Operand.immediate_zero, - size = src2size}, Assembly.instruction_binal {oper = Instruction.SBB, - dst = tmp, + dst = tmp2, src = src2, size = src2size}, Assembly.instruction_setcc From 2dc39682fb62651492463304175c02582f4b99c6 Mon Sep 17 00:00:00 2001 From: Matthew Fluet Date: Mon, 15 Oct 2018 12:18:29 -0400 Subject: [PATCH 57/57] Add `CHANGELOG` entry for new `Overflow`-checking primitives --- CHANGELOG.adoc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index ab1d1a32ee..6147ca0d53 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -8,6 +8,10 @@ Here are the changes from versoin 20180206 to version YYYYMMDD. === Details +* 2018-10-15 + ** Introduce new `Overflow`-checking primitives. Undertaken by Daman Morris + at RIT supported by NSF CISE Research Infrastructure (CRI) award. + * 2018-05-18 ** Add a parser for the SSA IR (`functor ParseSsa`). Undertaken by James Reilly at RIT supported by NSF CISE Research Infrastructure (CRI) award.