[m-rev.] for review: More robust compile-time evaluation of `int' operations.

Peter Wang novalazy at gmail.com
Tue Mar 17 13:52:30 AEDT 2015


More robust compile-time evaluation of `int' operations.

Compile-time evaluation of `int' operations previously required that
the target have the same number of bits per int as the host compiler.
In other cases, the user would have to pass `--cross-compiling' to avoid
the compiler silently producing a different result at compile time to
what would be produced at run time.

This change makes the compiler aware of the target's `int' width when
evaluating operations at compile-time.

Passing `--cross-compiling' is no longer required to avoid the problems
that this change addresses, but it MAY still be required for other reasons.
As of now, the one problem it would avoid is generating incorrect trie
string switches containing non-ASCII strings when targeting a high-level
C grade from a compiler built in Java or C# grades (not really
supported, but something we can fix anyway).  I have not removed any
references to the `--cross-compiling' option in the documentation.

compiler/libs.m:
compiler/int_emu.m:
	Add new module to emulate `int' operations for the target
	bits-per-int.  The predicates will only succeed if the result
	would be well-defined (including no overflow), and the result
	fits in the host's `int' type (no truncation).

compiler/const_prop.m:
	Evaluate `int' operations at compile time using `int_emu'
	predicates.

	Delete now unnecessary checks for cross_compiling=no.

	Delete comment about checking for overflow, now done.

compiler/simplify_goal_call.m:
	Use the target's value of bits-per-int in relevant
	simplifications.

	Delete check for cross_compiling=no.

compiler/handle_options.m:
	Don't imply `--cross-compiling' when targeting java, csharp and
	erlang grades.  This was a temporary workaround in case the
	Mercury compiler itself uses 64-bit ints.

tests/hard_coded/Mercury.options:
tests/hard_coded/Mmakefile:
tests/hard_coded/constant_prop_int.exp:
tests/hard_coded/constant_prop_int.exp2:
tests/hard_coded/constant_prop_int.m:
	Add test case.

diff --git a/compiler/const_prop.m b/compiler/const_prop.m
index 4e3293b..32803bf 100644
--- a/compiler/const_prop.m
+++ b/compiler/const_prop.m
@@ -13,11 +13,6 @@
 % routines at compile time, transforming them to simpler goals such as
 % construction unifications.
 %
-% XXX We should check for overflow.  This is particularly important when
-% cross-compiling, since the overflow behaviour of the host machine might not
-% be the same as that of the target machine, e.g. if they have different word
-% sizes.
-%
 %---------------------------------------------------------------------------%
 
 :- module transform_hlds.const_prop.
@@ -55,6 +50,7 @@
 :- import_module hlds.make_goal.
 :- import_module hlds.instmap.
 :- import_module libs.globals.
+:- import_module libs.int_emu.
 :- import_module libs.options.
 :- import_module parse_tree.prog_data.
 
@@ -199,9 +195,8 @@ evaluate_det_call_int_1(Globals, ProcName, ModeNum, X,
     (
         ProcName = "bits_per_int",
         ModeNum = 0,
-        globals.lookup_bool_option(Globals, cross_compiling, no),
         OutputArg = X,
-        OutputArgVal = int.bits_per_int
+        target_bits_per_int(Globals, bits_per_int(OutputArgVal))
     ).
 
 :- pred evaluate_det_call_int_2(globals::in, string::in, int::in,
@@ -221,7 +216,8 @@ evaluate_det_call_int_2(Globals, ProcName, ModeNum, X, Y,
         ModeNum = 0,
         X ^ arg_inst = bound(_, _, [bound_functor(int_const(XVal), [])]),
         OutputArg = Y,
-        OutputArgVal = -XVal
+        int_emu.target_bits_per_int(Globals, BitsPerInt),
+        int_emu.minus(BitsPerInt, 0, XVal, OutputArgVal)
     ;
         ProcName = "\\",
         ModeNum = 0,
@@ -231,31 +227,32 @@ evaluate_det_call_int_2(Globals, ProcName, ModeNum, X, Y,
     ;
         ProcName = "floor_to_multiple_of_bits_per_int",
         ModeNum = 0,
-        globals.lookup_bool_option(Globals, cross_compiling, no),
         X ^ arg_inst = bound(_, _, [bound_functor(int_const(XVal), [])]),
         OutputArg = Y,
-        OutputArgVal = int.floor_to_multiple_of_bits_per_int(XVal)
+        int_emu.target_bits_per_int(Globals, BitsPerInt),
+        int_emu.floor_to_multiple_of_bits_per_int(XVal, BitsPerInt,
+            OutputArgVal)
     ;
         ProcName = "quot_bits_per_int",
         ModeNum = 0,
-        globals.lookup_bool_option(Globals, cross_compiling, no),
         X ^ arg_inst = bound(_, _, [bound_functor(int_const(XVal), [])]),
         OutputArg = Y,
-        OutputArgVal = int.quot_bits_per_int(XVal)
+        int_emu.target_bits_per_int(Globals, BitsPerInt),
+        int_emu.quot_bits_per_int(XVal, BitsPerInt, OutputArgVal)
     ;
         ProcName = "times_bits_per_int",
         ModeNum = 0,
-        globals.lookup_bool_option(Globals, cross_compiling, no),
         X ^ arg_inst = bound(_, _, [bound_functor(int_const(XVal), [])]),
         OutputArg = Y,
-        OutputArgVal = int.times_bits_per_int(XVal)
+        int_emu.target_bits_per_int(Globals, BitsPerInt),
+        int_emu.times_bits_per_int(XVal, BitsPerInt, OutputArgVal)
     ;
         ProcName = "rem_bits_per_int",
         ModeNum = 0,
-        globals.lookup_bool_option(Globals, cross_compiling, no),
         X ^ arg_inst = bound(_, _, [bound_functor(int_const(XVal), [])]),
         OutputArg = Y,
-        OutputArgVal = int.rem_bits_per_int(XVal)
+        int_emu.target_bits_per_int(Globals, BitsPerInt),
+        int_emu.rem_bits_per_int(XVal, BitsPerInt, OutputArgVal)
     ).
 
 :- pred evaluate_det_call_float_2(globals::in, string::in, int::in,
@@ -295,7 +292,7 @@ evaluate_det_call_string_2(_Globals, ProcName, ModeNum, X, Y,
     arg_hlds_info::in, arg_hlds_info::in, arg_hlds_info::in,
     arg_hlds_info::out, cons_id::out) is semidet.
 
-evaluate_det_call_int_3(_Globals, ProcName, ModeNum, X, Y, Z,
+evaluate_det_call_int_3(Globals, ProcName, ModeNum, X, Y, Z,
         OutputArg, int_const(OutputArgVal)) :-
     (
         ProcName = "plus",
@@ -303,70 +300,80 @@ evaluate_det_call_int_3(_Globals, ProcName, ModeNum, X, Y, Z,
         X ^ arg_inst = bound(_, _, [bound_functor(int_const(XVal), [])]),
         Y ^ arg_inst = bound(_, _, [bound_functor(int_const(YVal), [])]),
         OutputArg = Z,
-        OutputArgVal = XVal + YVal
+        int_emu.target_bits_per_int(Globals, BitsPerInt),
+        int_emu.plus(BitsPerInt, XVal, YVal, OutputArgVal)
     ;
         ProcName = "+",
         ModeNum = 0,
         X ^ arg_inst = bound(_, _, [bound_functor(int_const(XVal), [])]),
         Y ^ arg_inst = bound(_, _, [bound_functor(int_const(YVal), [])]),
         OutputArg = Z,
-        OutputArgVal = XVal + YVal
+        int_emu.target_bits_per_int(Globals, BitsPerInt),
+        int_emu.plus(BitsPerInt, XVal, YVal, OutputArgVal)
     ;
         ProcName = "+",
         ModeNum = 1,
         Y ^ arg_inst = bound(_, _, [bound_functor(int_const(YVal), [])]),
         Z ^ arg_inst = bound(_, _, [bound_functor(int_const(ZVal), [])]),
         OutputArg = X,
-        OutputArgVal = ZVal - YVal
+        int_emu.target_bits_per_int(Globals, BitsPerInt),
+        int_emu.minus(BitsPerInt, ZVal, YVal, OutputArgVal)
     ;
         ProcName = "+",
         ModeNum = 2,
         X ^ arg_inst = bound(_, _, [bound_functor(int_const(XVal), [])]),
         Z ^ arg_inst = bound(_, _, [bound_functor(int_const(ZVal), [])]),
         OutputArg = Y,
-        OutputArgVal = ZVal - XVal
+        int_emu.target_bits_per_int(Globals, BitsPerInt),
+        int_emu.minus(BitsPerInt, ZVal, XVal, OutputArgVal)
     ;
         ProcName = "minus",
         ModeNum = 0,
         X ^ arg_inst = bound(_, _, [bound_functor(int_const(XVal), [])]),
         Y ^ arg_inst = bound(_, _, [bound_functor(int_const(YVal), [])]),
         OutputArg = Z,
-        OutputArgVal = XVal - YVal
+        int_emu.target_bits_per_int(Globals, BitsPerInt),
+        int_emu.minus(BitsPerInt, XVal, YVal, OutputArgVal)
     ;
         ProcName = "-",
         ModeNum = 0,
         X ^ arg_inst = bound(_, _, [bound_functor(int_const(XVal), [])]),
         Y ^ arg_inst = bound(_, _, [bound_functor(int_const(YVal), [])]),
         OutputArg = Z,
-        OutputArgVal = XVal - YVal
+        int_emu.target_bits_per_int(Globals, BitsPerInt),
+        int_emu.minus(BitsPerInt, XVal, YVal, OutputArgVal)
     ;
         ProcName = "-",
         ModeNum = 1,
         Y ^ arg_inst = bound(_, _, [bound_functor(int_const(YVal), [])]),
         Z ^ arg_inst = bound(_, _, [bound_functor(int_const(ZVal), [])]),
         OutputArg = X,
-        OutputArgVal = YVal + ZVal
+        int_emu.target_bits_per_int(Globals, BitsPerInt),
+        int_emu.plus(BitsPerInt, YVal, ZVal, OutputArgVal)
     ;
         ProcName = "-",
         ModeNum = 2,
         X ^ arg_inst = bound(_, _, [bound_functor(int_const(XVal), [])]),
         Z ^ arg_inst = bound(_, _, [bound_functor(int_const(ZVal), [])]),
         OutputArg = Y,
-        OutputArgVal = XVal - ZVal
+        int_emu.target_bits_per_int(Globals, BitsPerInt),
+        int_emu.minus(BitsPerInt, XVal, ZVal, OutputArgVal)
     ;
         ProcName = "times",
         ModeNum = 0,
         X ^ arg_inst = bound(_, _, [bound_functor(int_const(XVal), [])]),
         Y ^ arg_inst = bound(_, _, [bound_functor(int_const(YVal), [])]),
         OutputArg = Z,
-        OutputArgVal = XVal * YVal
+        int_emu.target_bits_per_int(Globals, BitsPerInt),
+        int_emu.times(BitsPerInt, XVal, YVal, OutputArgVal)
     ;
         ProcName = "*",
         ModeNum = 0,
         X ^ arg_inst = bound(_, _, [bound_functor(int_const(XVal), [])]),
         Y ^ arg_inst = bound(_, _, [bound_functor(int_const(YVal), [])]),
         OutputArg = Z,
-        OutputArgVal = XVal * YVal
+        int_emu.target_bits_per_int(Globals, BitsPerInt),
+        int_emu.times(BitsPerInt, XVal, YVal, OutputArgVal)
     ;
         ProcName = "unchecked_quotient",
         ModeNum = 0,
@@ -374,7 +381,8 @@ evaluate_det_call_int_3(_Globals, ProcName, ModeNum, X, Y, Z,
         Y ^ arg_inst = bound(_, _, [bound_functor(int_const(YVal), [])]),
         YVal \= 0,
         OutputArg = Z,
-        OutputArgVal = unchecked_quotient(XVal, YVal)
+        int_emu.target_bits_per_int(Globals, BitsPerInt),
+        int_emu.unchecked_quotient(BitsPerInt, XVal, YVal, OutputArgVal)
     ;
         ProcName = "//",
         ModeNum = 0,
@@ -382,7 +390,8 @@ evaluate_det_call_int_3(_Globals, ProcName, ModeNum, X, Y, Z,
         Y ^ arg_inst = bound(_, _, [bound_functor(int_const(YVal), [])]),
         YVal \= 0,
         OutputArg = Z,
-        OutputArgVal = XVal // YVal
+        int_emu.target_bits_per_int(Globals, BitsPerInt),
+        int_emu.quotient(BitsPerInt, XVal, YVal, OutputArgVal)
     ;
         ProcName = "mod",
         ModeNum = 0,
@@ -390,7 +399,8 @@ evaluate_det_call_int_3(_Globals, ProcName, ModeNum, X, Y, Z,
         Y ^ arg_inst = bound(_, _, [bound_functor(int_const(YVal), [])]),
         YVal \= 0,
         OutputArg = Z,
-        OutputArgVal = XVal mod YVal
+        int_emu.target_bits_per_int(Globals, BitsPerInt),
+        int_emu.mod(BitsPerInt, XVal, YVal, OutputArgVal)
     ;
         ProcName = "rem",
         ModeNum = 0,
@@ -398,7 +408,8 @@ evaluate_det_call_int_3(_Globals, ProcName, ModeNum, X, Y, Z,
         Y ^ arg_inst = bound(_, _, [bound_functor(int_const(YVal), [])]),
         YVal \= 0,
         OutputArg = Z,
-        OutputArgVal = XVal rem YVal
+        int_emu.target_bits_per_int(Globals, BitsPerInt),
+        int_emu.rem(BitsPerInt, XVal, YVal, OutputArgVal)
     ;
         ProcName = "unchecked_rem",
         ModeNum = 0,
@@ -406,35 +417,40 @@ evaluate_det_call_int_3(_Globals, ProcName, ModeNum, X, Y, Z,
         Y ^ arg_inst = bound(_, _, [bound_functor(int_const(YVal), [])]),
         YVal \= 0,
         OutputArg = Z,
-        OutputArgVal = unchecked_rem(XVal, YVal)
+        int_emu.target_bits_per_int(Globals, BitsPerInt),
+        int_emu.unchecked_rem(BitsPerInt, XVal, YVal, OutputArgVal)
     ;
         ProcName = "unchecked_left_shift",
         ModeNum = 0,
         X ^ arg_inst = bound(_, _, [bound_functor(int_const(XVal), [])]),
         Y ^ arg_inst = bound(_, _, [bound_functor(int_const(YVal), [])]),
         OutputArg = Z,
-        OutputArgVal = unchecked_left_shift(XVal, YVal)
+        int_emu.target_bits_per_int(Globals, BitsPerInt),
+        int_emu.unchecked_left_shift(BitsPerInt, XVal, YVal, OutputArgVal)
     ;
         ProcName = "<<",
         ModeNum = 0,
         X ^ arg_inst = bound(_, _, [bound_functor(int_const(XVal), [])]),
         Y ^ arg_inst = bound(_, _, [bound_functor(int_const(YVal), [])]),
         OutputArg = Z,
-        OutputArgVal = XVal << YVal
+        int_emu.target_bits_per_int(Globals, BitsPerInt),
+        int_emu.left_shift(BitsPerInt, XVal, YVal, OutputArgVal)
     ;
         ProcName = "unchecked_right_shift",
         ModeNum = 0,
         X ^ arg_inst = bound(_, _, [bound_functor(int_const(XVal), [])]),
         Y ^ arg_inst = bound(_, _, [bound_functor(int_const(YVal), [])]),
         OutputArg = Z,
-        OutputArgVal = unchecked_right_shift(XVal, YVal)
+        int_emu.target_bits_per_int(Globals, BitsPerInt),
+        int_emu.unchecked_right_shift(BitsPerInt, XVal, YVal, OutputArgVal)
     ;
         ProcName = ">>",
         ModeNum = 0,
         X ^ arg_inst = bound(_, _, [bound_functor(int_const(XVal), [])]),
         Y ^ arg_inst = bound(_, _, [bound_functor(int_const(YVal), [])]),
         OutputArg = Z,
-        OutputArgVal = XVal >> YVal
+        int_emu.target_bits_per_int(Globals, BitsPerInt),
+        int_emu.right_shift(BitsPerInt, XVal, YVal, OutputArgVal)
     ;
         ProcName = "/\\",
         ModeNum = 0,
diff --git a/compiler/handle_options.m b/compiler/handle_options.m
index 5add9c3..47ffbe1 100644
--- a/compiler/handle_options.m
+++ b/compiler/handle_options.m
@@ -885,9 +885,6 @@ convert_options_to_globals(OptionTable0, Target, GC_Method, TagsMethod0,
     %             So we should investigate re-enabling static ground terms.
     %         Currently mlds_to_il.m doesn't support them yet?
     %   - no library grade installation check with `mmc --make'.
-    %   - cross compiling
-    %     Because we use 32-bit integers which may be different to that of
-    %     the host compiler.
 
     (
         Target = target_il,
@@ -907,7 +904,6 @@ convert_options_to_globals(OptionTable0, Target, GC_Method, TagsMethod0,
         % globals.set_option(num_reserved_addresses, int(1), !Globals)
         globals.set_option(static_ground_cells, bool(no), !Globals),
         globals.set_option(libgrade_install_check, bool(no), !Globals),
-        globals.set_option(cross_compiling, bool(yes), !Globals),
 
         % On the .NET backend we will be using a language independent
         % debugger not mdb.  Thus --debug has to imply --target-debug.
@@ -969,9 +965,6 @@ convert_options_to_globals(OptionTable0, Target, GC_Method, TagsMethod0,
     %         Because Java has no way of allocating structs on the stack.
     %   - pretest-equality-cast-pointers
     %   - no library grade installation check with `mmc --make'.
-    %   - cross compiling
-    %     Because ints in Java are 32-bits wide which may be different to
-    %     that of the host compiler.
     %
     % C# should be the same as Java, except that:
     %   - C# supports pass-by-reference, but for reasons explained in
@@ -999,7 +992,6 @@ convert_options_to_globals(OptionTable0, Target, GC_Method, TagsMethod0,
         globals.set_option(pretest_equality_cast_pointers, bool(yes),
             !Globals),
         globals.set_option(libgrade_install_check, bool(no), !Globals),
-        globals.set_option(cross_compiling, bool(yes), !Globals),
         (
             Target = target_csharp,
             globals.set_option(executable_file_extension, string(".exe"),
@@ -1024,9 +1016,6 @@ convert_options_to_globals(OptionTable0, Target, GC_Method, TagsMethod0,
     %   - can-compare-compound-values
     %   - lexically-compare-constructors
     %   - no library grade installation check with `mmc --make'
-    %   - cross compiling
-    %     Because Erlang has arbitrary precision integers which may
-    %     different to that of the host compiler.
 
     (
         Target = target_erlang,
@@ -1046,7 +1035,6 @@ convert_options_to_globals(OptionTable0, Target, GC_Method, TagsMethod0,
         globals.set_option(lexically_order_constructors, bool(yes),
             !Globals),
         globals.set_option(libgrade_install_check, bool(no), !Globals),
-        globals.set_option(cross_compiling, bool(yes), !Globals),
 
         % The following options do not directly affect the Erlang backend,
         % however we need to ensure they are set to values that are consistent
diff --git a/compiler/int_emu.m b/compiler/int_emu.m
new file mode 100644
index 0000000..d0562c5
--- /dev/null
+++ b/compiler/int_emu.m
@@ -0,0 +1,180 @@
+%----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%----------------------------------------------------------------------------%
+% Copyright (C) 2015 The University of Melbourne.
+% This file may only be copied under the terms of the GNU General
+% Public License - see the file COPYING in the Mercury distribution.
+%----------------------------------------------------------------------------%
+%
+% File: int_emu.m.
+% Main author: wangp.
+%
+% Emulate `int' operations for a given number of bits per int. These predicates
+% succeed only if the result is defined for the given arguments, and the result
+% can be represented by the `int' type of the host compiler.
+%
+%----------------------------------------------------------------------------%
+
+:- module libs.int_emu.
+:- interface.
+
+:- import_module libs.globals.
+
+%----------------------------------------------------------------------------%
+
+:- type bits_per_int
+    --->    bits_per_int(int).
+
+    % Return the number of bits per int for the selected compilation target.
+    %
+:- pred target_bits_per_int(globals::in, bits_per_int::out) is det.
+
+%----------------------------------------------------------------------------%
+
+:- pred plus(bits_per_int::in, int::in, int::in, int::out) is semidet.
+
+:- pred minus(bits_per_int::in, int::in, int::in, int::out) is semidet.
+
+:- pred times(bits_per_int::in, int::in, int::in, int::out) is semidet.
+
+:- pred quotient(bits_per_int::in, int::in, int::in, int::out) is semidet.
+
+:- pred unchecked_quotient(bits_per_int::in, int::in, int::in, int::out)
+    is semidet.
+
+:- pred mod(bits_per_int::in, int::in, int::in, int::out) is semidet.
+
+:- pred rem(bits_per_int::in, int::in, int::in, int::out) is semidet.
+
+:- pred unchecked_rem(bits_per_int::in, int::in, int::in, int::out)
+    is semidet.
+
+:- pred left_shift(bits_per_int::in, int::in, int::in, int::out) is semidet.
+
+:- pred unchecked_left_shift(bits_per_int::in, int::in, int::in, int::out)
+    is semidet.
+
+:- pred right_shift(bits_per_int::in, int::in, int::in, int::out) is semidet.
+
+:- pred unchecked_right_shift(bits_per_int::in, int::in, int::in, int::out)
+    is semidet.
+
+:- pred floor_to_multiple_of_bits_per_int(int::in, bits_per_int::in, int::out)
+    is semidet.
+
+:- pred quot_bits_per_int(int::in, bits_per_int::in, int::out) is semidet.
+
+:- pred times_bits_per_int(int::in, bits_per_int::in, int::out) is semidet.
+
+:- pred rem_bits_per_int(int::in, bits_per_int::in, int::out) is semidet.
+
+%----------------------------------------------------------------------------%
+%----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module int.
+:- import_module integer.
+
+:- import_module libs.options.
+
+%----------------------------------------------------------------------------%
+
+target_bits_per_int(Globals, bits_per_int(BitsPerInt)) :-
+    globals.get_target(Globals, Target),
+    (
+        Target = target_c,
+        globals.lookup_int_option(Globals, bits_per_word, BitsPerInt)
+    ;
+        ( Target = target_il
+        ; Target = target_csharp
+        ; Target = target_java
+        ; Target = target_erlang
+        ),
+        BitsPerInt = 32
+    ).
+
+%----------------------------------------------------------------------------%
+
+plus(BitsPerInt, X, Y, Z) :-
+    to_int_in_range(BitsPerInt, integer(X) + integer(Y), Z).
+
+minus(BitsPerInt, X, Y, Z) :-
+    to_int_in_range(BitsPerInt, integer(X) - integer(Y), Z).
+
+times(BitsPerInt, X, Y, Z) :-
+    to_int_in_range(BitsPerInt, integer(X) * integer(Y), Z).
+
+quotient(BitsPerInt, X, Y, Z) :-
+    to_int_in_range(BitsPerInt, integer(X) // integer(Y), Z).
+
+unchecked_quotient(BitsPerInt, X, Y, Z) :-
+    Y \= 0,
+    quotient(BitsPerInt, X, Y, Z).
+
+mod(BitsPerInt, X, Y, Z) :-
+    to_int_in_range(BitsPerInt, integer(X) mod integer(Y), Z).
+
+rem(BitsPerInt, X, Y, Z) :-
+    to_int_in_range(BitsPerInt, integer(X) rem integer(Y), Z).
+
+unchecked_rem(BitsPerInt, X, Y, Z) :-
+    Y \= 0,
+    rem(BitsPerInt, X, Y, Z).
+
+left_shift(BitsPerInt, X, Y, Z) :-
+    BitsPerInt = bits_per_int(N),
+    to_int_in_range(BitsPerInt, integer(X) << min(Y, N), Z).
+
+unchecked_left_shift(BitsPerInt, X, Y, Z) :-
+    BitsPerInt = bits_per_int(N),
+    Y >= 0,
+    Y < N,
+    left_shift(BitsPerInt, X, Y, Z).
+
+right_shift(BitsPerInt, X, Y, Z) :-
+    ( Y < 0 ->
+        left_shift(BitsPerInt, X, -Y, Z)
+    ;
+        to_int_in_range(BitsPerInt, integer(X) >> Y, Z)
+    ).
+
+unchecked_right_shift(BitsPerInt, X, Y, Z) :-
+    BitsPerInt = bits_per_int(N),
+    Y >= 0,
+    Y < N,
+    right_shift(BitsPerInt, X, Y, Z).
+
+floor_to_multiple_of_bits_per_int(X, BitsPerInt, FloorInt) :-
+    BitsPerInt = bits_per_int(N),
+    Trunc = integer(X) // integer(N),
+    Floor0 = Trunc * integer(N),
+    ( Floor0 > integer(X) ->
+        Floor = Floor0 - integer(N)
+    ;
+        Floor = Floor0
+    ),
+    to_int_in_range(BitsPerInt, Floor, FloorInt).
+
+quot_bits_per_int(X, BitsPerInt, Z) :-
+    BitsPerInt = bits_per_int(Y),
+    quotient(BitsPerInt, X, Y, Z).
+
+times_bits_per_int(X, BitsPerInt, Z) :-
+    BitsPerInt = bits_per_int(Y),
+    times(BitsPerInt, X, Y, Z).
+
+rem_bits_per_int(X, BitsPerInt, Z) :-
+    BitsPerInt = bits_per_int(Y),
+    rem(BitsPerInt, X, Y, Z).
+
+:- pred to_int_in_range(bits_per_int::in, integer::in, int::out) is semidet.
+
+to_int_in_range(bits_per_int(BitsPerInt), Integer, Int) :-
+    Integer >= -pow(integer(2), integer(BitsPerInt - 1)),
+    Integer =< pow(integer(2), integer(BitsPerInt - 1)) - one,
+    integer.to_int(Integer, Int).
+
+%----------------------------------------------------------------------------%
+:- end_module libs.int_emu.
+%----------------------------------------------------------------------------%
diff --git a/compiler/libs.m b/compiler/libs.m
index 2a26fff..b0e9306 100644
--- a/compiler/libs.m
+++ b/compiler/libs.m
@@ -26,6 +26,7 @@
 :- include_module atsort.
 :- include_module file_util.
 :- include_module graph_colour.
+:- include_module int_emu.
 :- include_module md4.
 :- include_module pickle.
 
diff --git a/compiler/simplify_goal_call.m b/compiler/simplify_goal_call.m
index 7e4eafc..656db36 100644
--- a/compiler/simplify_goal_call.m
+++ b/compiler/simplify_goal_call.m
@@ -64,6 +64,7 @@
 :- import_module hlds.pred_table.
 :- import_module libs.
 :- import_module libs.globals.
+:- import_module libs.int_emu.
 :- import_module libs.options.
 :- import_module mdbcomp.
 :- import_module mdbcomp.builtin_modules.
@@ -670,20 +671,20 @@ simplify_improve_int_call(InstMap0, PredName, _ModeNum, Args, ImprovedGoalExpr,
         !GoalInfo, !Info) :-
     simplify_info_get_module_info(!.Info, ModuleInfo),
     module_info_get_globals(ModuleInfo, Globals),
-    globals.lookup_bool_option(Globals, cross_compiling, no),
+    target_bits_per_int(Globals, bits_per_int(TargetBitsPerInt)),
     (
         PredName = "quot_bits_per_int",
         Args = [X, Y],
         % There is no point in checking whether bits_per_int is 0;
         % it isn't.
         Op = "unchecked_quotient",
-        simplify_make_int_ico_op(Op, X, int.bits_per_int, Y, ImprovedGoalExpr,
+        simplify_make_int_ico_op(Op, X, TargetBitsPerInt, Y, ImprovedGoalExpr,
             !.GoalInfo, !Info)
     ;
         PredName = "times_bits_per_int",
         Args = [X, Y],
         Op = "*",
-        simplify_make_int_ico_op(Op, X, int.bits_per_int, Y, ImprovedGoalExpr,
+        simplify_make_int_ico_op(Op, X, TargetBitsPerInt, Y, ImprovedGoalExpr,
             !.GoalInfo, !Info)
     ;
         PredName = "rem_bits_per_int",
@@ -691,7 +692,7 @@ simplify_improve_int_call(InstMap0, PredName, _ModeNum, Args, ImprovedGoalExpr,
         % There is no point in checking whether bits_per_int is 0;
         % it isn't.
         Op = "unchecked_rem",
-        simplify_make_int_ico_op(Op, X, int.bits_per_int, Y, ImprovedGoalExpr,
+        simplify_make_int_ico_op(Op, X, TargetBitsPerInt, Y, ImprovedGoalExpr,
             !.GoalInfo, !Info)
     ;
         ( PredName = "/"
@@ -719,7 +720,7 @@ simplify_improve_int_call(InstMap0, PredName, _ModeNum, Args, ImprovedGoalExpr,
         instmap_lookup_var(InstMap0, Y, InstY),
         InstY = bound(_, _, [bound_functor(int_const(YVal), [])]),
         YVal >= 0,
-        YVal < int.bits_per_int,
+        YVal < TargetBitsPerInt,
         Op = "unchecked_left_shift",
         simplify_make_int_binary_op_goal_expr(!.Info, Op, inline_builtin,
             X, Y, Z, ImprovedGoalExpr)
@@ -729,7 +730,7 @@ simplify_improve_int_call(InstMap0, PredName, _ModeNum, Args, ImprovedGoalExpr,
         instmap_lookup_var(InstMap0, Y, InstY),
         InstY = bound(_, _, [bound_functor(int_const(YVal), [])]),
         YVal >= 0,
-        YVal < int.bits_per_int,
+        YVal < TargetBitsPerInt,
         Op = "unchecked_right_shift",
         simplify_make_int_binary_op_goal_expr(!.Info, Op, inline_builtin,
             X, Y, Z, ImprovedGoalExpr)
diff --git a/tests/hard_coded/Mercury.options b/tests/hard_coded/Mercury.options
index f2b3bc8..b784e77 100644
--- a/tests/hard_coded/Mercury.options
+++ b/tests/hard_coded/Mercury.options
@@ -202,3 +202,4 @@ MCFLAGS-constant_prop_1 = --optimize-constant-propagation \
 		--trace-optimized
 MCFLAGS-constant_prop_2 = --optimize-constant-propagation \
 		--optimize-dead-procs --trace-optimized
+MCFLAGS-constant_prop_int = --optimize-constant-propagation
diff --git a/tests/hard_coded/Mmakefile b/tests/hard_coded/Mmakefile
index 3cfdb0f..3ea8543 100644
--- a/tests/hard_coded/Mmakefile
+++ b/tests/hard_coded/Mmakefile
@@ -384,6 +384,7 @@ JAVA_PASS_PROGS = \
 	calendar_test \
 	compare_spec \
 	constant_prop_2 \
+	constant_prop_int \
 	contains_char \
 	contains_char_2 \
 	constraint \
diff --git a/tests/hard_coded/constant_prop_int.exp b/tests/hard_coded/constant_prop_int.exp
new file mode 100644
index 0000000..660b547
--- /dev/null
+++ b/tests/hard_coded/constant_prop_int.exp
@@ -0,0 +1,409 @@
+plus(1, 0) = 1
+plus(1, 1) = 2
+plus(1, -1) = 0
+plus(1, 31) = 32
+plus(1, -31) = -30
+plus(1, 2147483647) = -2147483648
+plus(1, -2147483648) = -2147483647
+plus(-1, 0) = -1
+plus(-1, 1) = 0
+plus(-1, -1) = -2
+plus(-1, 31) = 30
+plus(-1, -31) = -32
+plus(-1, 2147483647) = 2147483646
+plus(-1, -2147483648) = 2147483647
+plus(31, 0) = 31
+plus(31, 1) = 32
+plus(31, -1) = 30
+plus(31, 31) = 62
+plus(31, -31) = 0
+plus(31, 2147483647) = -2147483618
+plus(31, -2147483648) = -2147483617
+plus(-31, 0) = -31
+plus(-31, 1) = -30
+plus(-31, -1) = -32
+plus(-31, 31) = 0
+plus(-31, -31) = -62
+plus(-31, 2147483647) = 2147483616
+plus(-31, -2147483648) = 2147483617
+plus(2147483647, 0) = 2147483647
+plus(2147483647, 1) = -2147483648
+plus(2147483647, -1) = 2147483646
+plus(2147483647, 31) = -2147483618
+plus(2147483647, -31) = 2147483616
+plus(2147483647, 2147483647) = -2
+plus(2147483647, -2147483648) = -1
+plus(-2147483648, 0) = -2147483648
+plus(-2147483648, 1) = -2147483647
+plus(-2147483648, -1) = 2147483647
+plus(-2147483648, 31) = -2147483617
+plus(-2147483648, -31) = 2147483617
+plus(-2147483648, 2147483647) = -1
+plus(-2147483648, -2147483648) = 0
+
+minus(1, 0) = 1
+minus(1, 1) = 0
+minus(1, -1) = 2
+minus(1, 31) = -30
+minus(1, -31) = 32
+minus(1, 2147483647) = -2147483646
+minus(1, -2147483648) = -2147483647
+minus(-1, 0) = -1
+minus(-1, 1) = -2
+minus(-1, -1) = 0
+minus(-1, 31) = -32
+minus(-1, -31) = 30
+minus(-1, 2147483647) = -2147483648
+minus(-1, -2147483648) = 2147483647
+minus(31, 0) = 31
+minus(31, 1) = 30
+minus(31, -1) = 32
+minus(31, 31) = 0
+minus(31, -31) = 62
+minus(31, 2147483647) = -2147483616
+minus(31, -2147483648) = -2147483617
+minus(-31, 0) = -31
+minus(-31, 1) = -32
+minus(-31, -1) = -30
+minus(-31, 31) = -62
+minus(-31, -31) = 0
+minus(-31, 2147483647) = 2147483618
+minus(-31, -2147483648) = 2147483617
+minus(2147483647, 0) = 2147483647
+minus(2147483647, 1) = 2147483646
+minus(2147483647, -1) = -2147483648
+minus(2147483647, 31) = 2147483616
+minus(2147483647, -31) = -2147483618
+minus(2147483647, 2147483647) = 0
+minus(2147483647, -2147483648) = -1
+minus(-2147483648, 0) = -2147483648
+minus(-2147483648, 1) = 2147483647
+minus(-2147483648, -1) = -2147483647
+minus(-2147483648, 31) = 2147483617
+minus(-2147483648, -31) = -2147483617
+minus(-2147483648, 2147483647) = 1
+minus(-2147483648, -2147483648) = 0
+
+times(1, 0) = 0
+times(1, 1) = 1
+times(1, -1) = -1
+times(1, 31) = 31
+times(1, -31) = -31
+times(1, 2147483647) = 2147483647
+times(1, -2147483648) = -2147483648
+times(-1, 0) = 0
+times(-1, 1) = -1
+times(-1, -1) = 1
+times(-1, 31) = -31
+times(-1, -31) = 31
+times(-1, 2147483647) = -2147483647
+times(-1, -2147483648) = -2147483648
+times(31, 0) = 0
+times(31, 1) = 31
+times(31, -1) = -31
+times(31, 31) = 961
+times(31, -31) = -961
+times(31, 2147483647) = 2147483617
+times(31, -2147483648) = -2147483648
+times(-31, 0) = 0
+times(-31, 1) = -31
+times(-31, -1) = 31
+times(-31, 31) = -961
+times(-31, -31) = 961
+times(-31, 2147483647) = -2147483617
+times(-31, -2147483648) = -2147483648
+times(2147483647, 0) = 0
+times(2147483647, 1) = 2147483647
+times(2147483647, -1) = -2147483647
+times(2147483647, 31) = 2147483617
+times(2147483647, -31) = -2147483617
+times(2147483647, 2147483647) = 1
+times(2147483647, -2147483648) = -2147483648
+times(-2147483648, 0) = 0
+times(-2147483648, 1) = -2147483648
+times(-2147483648, -1) = -2147483648
+times(-2147483648, 31) = -2147483648
+times(-2147483648, -31) = -2147483648
+times(-2147483648, 2147483647) = -2147483648
+times(-2147483648, -2147483648) = 0
+
+quotient(1, 1) = 1
+quotient(1, -1) = -1
+quotient(1, 31) = 0
+quotient(1, -31) = 0
+quotient(1, 2147483647) = 0
+quotient(1, -2147483648) = 0
+quotient(-1, 1) = -1
+quotient(-1, -1) = 1
+quotient(-1, 31) = 0
+quotient(-1, -31) = 0
+quotient(-1, 2147483647) = 0
+quotient(-1, -2147483648) = 0
+quotient(31, 1) = 31
+quotient(31, -1) = -31
+quotient(31, 31) = 1
+quotient(31, -31) = -1
+quotient(31, 2147483647) = 0
+quotient(31, -2147483648) = 0
+quotient(-31, 1) = -31
+quotient(-31, -1) = 31
+quotient(-31, 31) = -1
+quotient(-31, -31) = 1
+quotient(-31, 2147483647) = 0
+quotient(-31, -2147483648) = 0
+quotient(2147483647, 1) = 2147483647
+quotient(2147483647, -1) = -2147483647
+quotient(2147483647, 31) = 69273666
+quotient(2147483647, -31) = -69273666
+quotient(2147483647, 2147483647) = 1
+quotient(2147483647, -2147483648) = 0
+quotient(-2147483648, 1) = -2147483648
+quotient(-2147483648, 31) = -69273666
+quotient(-2147483648, -31) = 69273666
+quotient(-2147483648, 2147483647) = -1
+quotient(-2147483648, -2147483648) = 1
+
+unchecked_quotient(1, 1) = 1
+unchecked_quotient(1, -1) = -1
+unchecked_quotient(1, 31) = 0
+unchecked_quotient(1, -31) = 0
+unchecked_quotient(1, 2147483647) = 0
+unchecked_quotient(1, -2147483648) = 0
+unchecked_quotient(-1, 1) = -1
+unchecked_quotient(-1, -1) = 1
+unchecked_quotient(-1, 31) = 0
+unchecked_quotient(-1, -31) = 0
+unchecked_quotient(-1, 2147483647) = 0
+unchecked_quotient(-1, -2147483648) = 0
+unchecked_quotient(31, 1) = 31
+unchecked_quotient(31, -1) = -31
+unchecked_quotient(31, 31) = 1
+unchecked_quotient(31, -31) = -1
+unchecked_quotient(31, 2147483647) = 0
+unchecked_quotient(31, -2147483648) = 0
+unchecked_quotient(-31, 1) = -31
+unchecked_quotient(-31, -1) = 31
+unchecked_quotient(-31, 31) = -1
+unchecked_quotient(-31, -31) = 1
+unchecked_quotient(-31, 2147483647) = 0
+unchecked_quotient(-31, -2147483648) = 0
+unchecked_quotient(2147483647, 1) = 2147483647
+unchecked_quotient(2147483647, -1) = -2147483647
+unchecked_quotient(2147483647, 31) = 69273666
+unchecked_quotient(2147483647, -31) = -69273666
+unchecked_quotient(2147483647, 2147483647) = 1
+unchecked_quotient(2147483647, -2147483648) = 0
+unchecked_quotient(-2147483648, 1) = -2147483648
+unchecked_quotient(-2147483648, 31) = -69273666
+unchecked_quotient(-2147483648, -31) = 69273666
+unchecked_quotient(-2147483648, 2147483647) = -1
+unchecked_quotient(-2147483648, -2147483648) = 1
+
+mod(1, 1) = 0
+mod(1, -1) = 0
+mod(1, 31) = 1
+mod(1, -31) = -30
+mod(1, 2147483647) = 1
+mod(1, -2147483648) = -2147483647
+mod(-1, 1) = 0
+mod(-1, -1) = 0
+mod(-1, 31) = 30
+mod(-1, -31) = -1
+mod(-1, 2147483647) = 2147483646
+mod(-1, -2147483648) = -1
+mod(31, 1) = 0
+mod(31, -1) = 0
+mod(31, 31) = 0
+mod(31, -31) = 0
+mod(31, 2147483647) = 31
+mod(31, -2147483648) = -2147483617
+mod(-31, 1) = 0
+mod(-31, -1) = 0
+mod(-31, 31) = 0
+mod(-31, -31) = 0
+mod(-31, 2147483647) = 2147483616
+mod(-31, -2147483648) = -31
+mod(2147483647, 1) = 0
+mod(2147483647, -1) = 0
+mod(2147483647, 31) = 1
+mod(2147483647, -31) = -30
+mod(2147483647, 2147483647) = 0
+mod(2147483647, -2147483648) = -1
+mod(-2147483648, 1) = 0
+mod(-2147483648, 31) = 29
+mod(-2147483648, -31) = -2
+mod(-2147483648, 2147483647) = 2147483646
+mod(-2147483648, -2147483648) = 0
+
+rem(1, 1) = 0
+rem(1, -1) = 0
+rem(1, 31) = 1
+rem(1, -31) = 1
+rem(1, 2147483647) = 1
+rem(1, -2147483648) = 1
+rem(-1, 1) = 0
+rem(-1, -1) = 0
+rem(-1, 31) = -1
+rem(-1, -31) = -1
+rem(-1, 2147483647) = -1
+rem(-1, -2147483648) = -1
+rem(31, 1) = 0
+rem(31, -1) = 0
+rem(31, 31) = 0
+rem(31, -31) = 0
+rem(31, 2147483647) = 31
+rem(31, -2147483648) = 31
+rem(-31, 1) = 0
+rem(-31, -1) = 0
+rem(-31, 31) = 0
+rem(-31, -31) = 0
+rem(-31, 2147483647) = -31
+rem(-31, -2147483648) = -31
+rem(2147483647, 1) = 0
+rem(2147483647, -1) = 0
+rem(2147483647, 31) = 1
+rem(2147483647, -31) = 1
+rem(2147483647, 2147483647) = 0
+rem(2147483647, -2147483648) = 2147483647
+rem(-2147483648, 1) = 0
+rem(-2147483648, 31) = -2
+rem(-2147483648, -31) = -2
+rem(-2147483648, 2147483647) = -1
+rem(-2147483648, -2147483648) = 0
+
+unchecked_rem(1, 1) = 0
+unchecked_rem(1, -1) = 0
+unchecked_rem(1, 31) = 1
+unchecked_rem(1, -31) = 1
+unchecked_rem(1, 2147483647) = 1
+unchecked_rem(1, -2147483648) = 1
+unchecked_rem(-1, 1) = 0
+unchecked_rem(-1, -1) = 0
+unchecked_rem(-1, 31) = -1
+unchecked_rem(-1, -31) = -1
+unchecked_rem(-1, 2147483647) = -1
+unchecked_rem(-1, -2147483648) = -1
+unchecked_rem(31, 1) = 0
+unchecked_rem(31, -1) = 0
+unchecked_rem(31, 31) = 0
+unchecked_rem(31, -31) = 0
+unchecked_rem(31, 2147483647) = 31
+unchecked_rem(31, -2147483648) = 31
+unchecked_rem(-31, 1) = 0
+unchecked_rem(-31, -1) = 0
+unchecked_rem(-31, 31) = 0
+unchecked_rem(-31, -31) = 0
+unchecked_rem(-31, 2147483647) = -31
+unchecked_rem(-31, -2147483648) = -31
+unchecked_rem(2147483647, 1) = 0
+unchecked_rem(2147483647, -1) = 0
+unchecked_rem(2147483647, 31) = 1
+unchecked_rem(2147483647, -31) = 1
+unchecked_rem(2147483647, 2147483647) = 0
+unchecked_rem(2147483647, -2147483648) = 2147483647
+unchecked_rem(-2147483648, 1) = 0
+unchecked_rem(-2147483648, 31) = -2
+unchecked_rem(-2147483648, -31) = -2
+unchecked_rem(-2147483648, 2147483647) = -1
+unchecked_rem(-2147483648, -2147483648) = 0
+
+left_shift(1, 0) = 1
+left_shift(1, 1) = 2
+left_shift(1, -1) = 0
+left_shift(1, 31) = -2147483648
+left_shift(1, -31) = 0
+left_shift(-1, 0) = -1
+left_shift(-1, 1) = -2
+left_shift(-1, -1) = -1
+left_shift(-1, 31) = -2147483648
+left_shift(-1, -31) = -1
+left_shift(31, 0) = 31
+left_shift(31, 1) = 62
+left_shift(31, -1) = 15
+left_shift(31, 31) = -2147483648
+left_shift(31, -31) = 0
+left_shift(-31, 0) = -31
+left_shift(-31, 1) = -62
+left_shift(-31, -1) = -16
+left_shift(-31, 31) = -2147483648
+left_shift(-31, -31) = -1
+left_shift(2147483647, 0) = 2147483647
+left_shift(2147483647, 1) = -2
+left_shift(2147483647, -1) = 1073741823
+left_shift(2147483647, 31) = -2147483648
+left_shift(2147483647, -31) = 0
+left_shift(-2147483648, 0) = -2147483648
+left_shift(-2147483648, 1) = 0
+left_shift(-2147483648, -1) = -1073741824
+left_shift(-2147483648, 31) = 0
+left_shift(-2147483648, -31) = -1
+
+unchecked_left_shift(1, 0) = 1
+unchecked_left_shift(1, 1) = 2
+unchecked_left_shift(1, 31) = -2147483648
+unchecked_left_shift(-1, 0) = -1
+unchecked_left_shift(-1, 1) = -2
+unchecked_left_shift(-1, 31) = -2147483648
+unchecked_left_shift(31, 0) = 31
+unchecked_left_shift(31, 1) = 62
+unchecked_left_shift(31, 31) = -2147483648
+unchecked_left_shift(-31, 0) = -31
+unchecked_left_shift(-31, 1) = -62
+unchecked_left_shift(-31, 31) = -2147483648
+unchecked_left_shift(2147483647, 0) = 2147483647
+unchecked_left_shift(2147483647, 1) = -2
+unchecked_left_shift(2147483647, 31) = -2147483648
+unchecked_left_shift(-2147483648, 0) = -2147483648
+unchecked_left_shift(-2147483648, 1) = 0
+unchecked_left_shift(-2147483648, 31) = 0
+
+right_shift(1, 0) = 1
+right_shift(1, 1) = 0
+right_shift(1, -1) = 2
+right_shift(1, 31) = 0
+right_shift(1, -31) = -2147483648
+right_shift(-1, 0) = -1
+right_shift(-1, 1) = -1
+right_shift(-1, -1) = -2
+right_shift(-1, 31) = -1
+right_shift(-1, -31) = -2147483648
+right_shift(31, 0) = 31
+right_shift(31, 1) = 15
+right_shift(31, -1) = 62
+right_shift(31, 31) = 0
+right_shift(31, -31) = -2147483648
+right_shift(-31, 0) = -31
+right_shift(-31, 1) = -16
+right_shift(-31, -1) = -62
+right_shift(-31, 31) = -1
+right_shift(-31, -31) = -2147483648
+right_shift(2147483647, 0) = 2147483647
+right_shift(2147483647, 1) = 1073741823
+right_shift(2147483647, -1) = -2
+right_shift(2147483647, 31) = 0
+right_shift(2147483647, -31) = -2147483648
+right_shift(-2147483648, 0) = -2147483648
+right_shift(-2147483648, 1) = -1073741824
+right_shift(-2147483648, -1) = 0
+right_shift(-2147483648, 31) = -1
+right_shift(-2147483648, -31) = 0
+
+unchecked_right_shift(1, 0) = 1
+unchecked_right_shift(1, 1) = 0
+unchecked_right_shift(1, 31) = 0
+unchecked_right_shift(-1, 0) = -1
+unchecked_right_shift(-1, 1) = -1
+unchecked_right_shift(-1, 31) = -1
+unchecked_right_shift(31, 0) = 31
+unchecked_right_shift(31, 1) = 15
+unchecked_right_shift(31, 31) = 0
+unchecked_right_shift(-31, 0) = -31
+unchecked_right_shift(-31, 1) = -16
+unchecked_right_shift(-31, 31) = -1
+unchecked_right_shift(2147483647, 0) = 2147483647
+unchecked_right_shift(2147483647, 1) = 1073741823
+unchecked_right_shift(2147483647, 31) = 0
+unchecked_right_shift(-2147483648, 0) = -2147483648
+unchecked_right_shift(-2147483648, 1) = -1073741824
+unchecked_right_shift(-2147483648, 31) = -1
+
diff --git a/tests/hard_coded/constant_prop_int.exp2 b/tests/hard_coded/constant_prop_int.exp2
new file mode 100644
index 0000000..28167e0
--- /dev/null
+++ b/tests/hard_coded/constant_prop_int.exp2
@@ -0,0 +1,409 @@
+plus(1, 0) = 1
+plus(1, 1) = 2
+plus(1, -1) = 0
+plus(1, 31) = 32
+plus(1, -31) = -30
+plus(1, 2147483647) = 2147483648
+plus(1, -2147483648) = -2147483647
+plus(-1, 0) = -1
+plus(-1, 1) = 0
+plus(-1, -1) = -2
+plus(-1, 31) = 30
+plus(-1, -31) = -32
+plus(-1, 2147483647) = 2147483646
+plus(-1, -2147483648) = -2147483649
+plus(31, 0) = 31
+plus(31, 1) = 32
+plus(31, -1) = 30
+plus(31, 31) = 62
+plus(31, -31) = 0
+plus(31, 2147483647) = 2147483678
+plus(31, -2147483648) = -2147483617
+plus(-31, 0) = -31
+plus(-31, 1) = -30
+plus(-31, -1) = -32
+plus(-31, 31) = 0
+plus(-31, -31) = -62
+plus(-31, 2147483647) = 2147483616
+plus(-31, -2147483648) = -2147483679
+plus(2147483647, 0) = 2147483647
+plus(2147483647, 1) = 2147483648
+plus(2147483647, -1) = 2147483646
+plus(2147483647, 31) = 2147483678
+plus(2147483647, -31) = 2147483616
+plus(2147483647, 2147483647) = 4294967294
+plus(2147483647, -2147483648) = -1
+plus(-2147483648, 0) = -2147483648
+plus(-2147483648, 1) = -2147483647
+plus(-2147483648, -1) = -2147483649
+plus(-2147483648, 31) = -2147483617
+plus(-2147483648, -31) = -2147483679
+plus(-2147483648, 2147483647) = -1
+plus(-2147483648, -2147483648) = -4294967296
+
+minus(1, 0) = 1
+minus(1, 1) = 0
+minus(1, -1) = 2
+minus(1, 31) = -30
+minus(1, -31) = 32
+minus(1, 2147483647) = -2147483646
+minus(1, -2147483648) = 2147483649
+minus(-1, 0) = -1
+minus(-1, 1) = -2
+minus(-1, -1) = 0
+minus(-1, 31) = -32
+minus(-1, -31) = 30
+minus(-1, 2147483647) = -2147483648
+minus(-1, -2147483648) = 2147483647
+minus(31, 0) = 31
+minus(31, 1) = 30
+minus(31, -1) = 32
+minus(31, 31) = 0
+minus(31, -31) = 62
+minus(31, 2147483647) = -2147483616
+minus(31, -2147483648) = 2147483679
+minus(-31, 0) = -31
+minus(-31, 1) = -32
+minus(-31, -1) = -30
+minus(-31, 31) = -62
+minus(-31, -31) = 0
+minus(-31, 2147483647) = -2147483678
+minus(-31, -2147483648) = 2147483617
+minus(2147483647, 0) = 2147483647
+minus(2147483647, 1) = 2147483646
+minus(2147483647, -1) = 2147483648
+minus(2147483647, 31) = 2147483616
+minus(2147483647, -31) = 2147483678
+minus(2147483647, 2147483647) = 0
+minus(2147483647, -2147483648) = 4294967295
+minus(-2147483648, 0) = -2147483648
+minus(-2147483648, 1) = -2147483649
+minus(-2147483648, -1) = -2147483647
+minus(-2147483648, 31) = -2147483679
+minus(-2147483648, -31) = -2147483617
+minus(-2147483648, 2147483647) = -4294967295
+minus(-2147483648, -2147483648) = 0
+
+times(1, 0) = 0
+times(1, 1) = 1
+times(1, -1) = -1
+times(1, 31) = 31
+times(1, -31) = -31
+times(1, 2147483647) = 2147483647
+times(1, -2147483648) = -2147483648
+times(-1, 0) = 0
+times(-1, 1) = -1
+times(-1, -1) = 1
+times(-1, 31) = -31
+times(-1, -31) = 31
+times(-1, 2147483647) = -2147483647
+times(-1, -2147483648) = 2147483648
+times(31, 0) = 0
+times(31, 1) = 31
+times(31, -1) = -31
+times(31, 31) = 961
+times(31, -31) = -961
+times(31, 2147483647) = 66571993057
+times(31, -2147483648) = -66571993088
+times(-31, 0) = 0
+times(-31, 1) = -31
+times(-31, -1) = 31
+times(-31, 31) = -961
+times(-31, -31) = 961
+times(-31, 2147483647) = -66571993057
+times(-31, -2147483648) = 66571993088
+times(2147483647, 0) = 0
+times(2147483647, 1) = 2147483647
+times(2147483647, -1) = -2147483647
+times(2147483647, 31) = 66571993057
+times(2147483647, -31) = -66571993057
+times(2147483647, 2147483647) = 4611686014132420609
+times(2147483647, -2147483648) = -4611686016279904256
+times(-2147483648, 0) = 0
+times(-2147483648, 1) = -2147483648
+times(-2147483648, -1) = 2147483648
+times(-2147483648, 31) = -66571993088
+times(-2147483648, -31) = 66571993088
+times(-2147483648, 2147483647) = -4611686016279904256
+times(-2147483648, -2147483648) = 4611686018427387904
+
+quotient(1, 1) = 1
+quotient(1, -1) = -1
+quotient(1, 31) = 0
+quotient(1, -31) = 0
+quotient(1, 2147483647) = 0
+quotient(1, -2147483648) = 0
+quotient(-1, 1) = -1
+quotient(-1, -1) = 1
+quotient(-1, 31) = 0
+quotient(-1, -31) = 0
+quotient(-1, 2147483647) = 0
+quotient(-1, -2147483648) = 0
+quotient(31, 1) = 31
+quotient(31, -1) = -31
+quotient(31, 31) = 1
+quotient(31, -31) = -1
+quotient(31, 2147483647) = 0
+quotient(31, -2147483648) = 0
+quotient(-31, 1) = -31
+quotient(-31, -1) = 31
+quotient(-31, 31) = -1
+quotient(-31, -31) = 1
+quotient(-31, 2147483647) = 0
+quotient(-31, -2147483648) = 0
+quotient(2147483647, 1) = 2147483647
+quotient(2147483647, -1) = -2147483647
+quotient(2147483647, 31) = 69273666
+quotient(2147483647, -31) = -69273666
+quotient(2147483647, 2147483647) = 1
+quotient(2147483647, -2147483648) = 0
+quotient(-2147483648, 1) = -2147483648
+quotient(-2147483648, 31) = -69273666
+quotient(-2147483648, -31) = 69273666
+quotient(-2147483648, 2147483647) = -1
+quotient(-2147483648, -2147483648) = 1
+
+unchecked_quotient(1, 1) = 1
+unchecked_quotient(1, -1) = -1
+unchecked_quotient(1, 31) = 0
+unchecked_quotient(1, -31) = 0
+unchecked_quotient(1, 2147483647) = 0
+unchecked_quotient(1, -2147483648) = 0
+unchecked_quotient(-1, 1) = -1
+unchecked_quotient(-1, -1) = 1
+unchecked_quotient(-1, 31) = 0
+unchecked_quotient(-1, -31) = 0
+unchecked_quotient(-1, 2147483647) = 0
+unchecked_quotient(-1, -2147483648) = 0
+unchecked_quotient(31, 1) = 31
+unchecked_quotient(31, -1) = -31
+unchecked_quotient(31, 31) = 1
+unchecked_quotient(31, -31) = -1
+unchecked_quotient(31, 2147483647) = 0
+unchecked_quotient(31, -2147483648) = 0
+unchecked_quotient(-31, 1) = -31
+unchecked_quotient(-31, -1) = 31
+unchecked_quotient(-31, 31) = -1
+unchecked_quotient(-31, -31) = 1
+unchecked_quotient(-31, 2147483647) = 0
+unchecked_quotient(-31, -2147483648) = 0
+unchecked_quotient(2147483647, 1) = 2147483647
+unchecked_quotient(2147483647, -1) = -2147483647
+unchecked_quotient(2147483647, 31) = 69273666
+unchecked_quotient(2147483647, -31) = -69273666
+unchecked_quotient(2147483647, 2147483647) = 1
+unchecked_quotient(2147483647, -2147483648) = 0
+unchecked_quotient(-2147483648, 1) = -2147483648
+unchecked_quotient(-2147483648, 31) = -69273666
+unchecked_quotient(-2147483648, -31) = 69273666
+unchecked_quotient(-2147483648, 2147483647) = -1
+unchecked_quotient(-2147483648, -2147483648) = 1
+
+mod(1, 1) = 0
+mod(1, -1) = 0
+mod(1, 31) = 1
+mod(1, -31) = -30
+mod(1, 2147483647) = 1
+mod(1, -2147483648) = -2147483647
+mod(-1, 1) = 0
+mod(-1, -1) = 0
+mod(-1, 31) = 30
+mod(-1, -31) = -1
+mod(-1, 2147483647) = 2147483646
+mod(-1, -2147483648) = -1
+mod(31, 1) = 0
+mod(31, -1) = 0
+mod(31, 31) = 0
+mod(31, -31) = 0
+mod(31, 2147483647) = 31
+mod(31, -2147483648) = -2147483617
+mod(-31, 1) = 0
+mod(-31, -1) = 0
+mod(-31, 31) = 0
+mod(-31, -31) = 0
+mod(-31, 2147483647) = 2147483616
+mod(-31, -2147483648) = -31
+mod(2147483647, 1) = 0
+mod(2147483647, -1) = 0
+mod(2147483647, 31) = 1
+mod(2147483647, -31) = -30
+mod(2147483647, 2147483647) = 0
+mod(2147483647, -2147483648) = -1
+mod(-2147483648, 1) = 0
+mod(-2147483648, 31) = 29
+mod(-2147483648, -31) = -2
+mod(-2147483648, 2147483647) = 2147483646
+mod(-2147483648, -2147483648) = 0
+
+rem(1, 1) = 0
+rem(1, -1) = 0
+rem(1, 31) = 1
+rem(1, -31) = 1
+rem(1, 2147483647) = 1
+rem(1, -2147483648) = 1
+rem(-1, 1) = 0
+rem(-1, -1) = 0
+rem(-1, 31) = -1
+rem(-1, -31) = -1
+rem(-1, 2147483647) = -1
+rem(-1, -2147483648) = -1
+rem(31, 1) = 0
+rem(31, -1) = 0
+rem(31, 31) = 0
+rem(31, -31) = 0
+rem(31, 2147483647) = 31
+rem(31, -2147483648) = 31
+rem(-31, 1) = 0
+rem(-31, -1) = 0
+rem(-31, 31) = 0
+rem(-31, -31) = 0
+rem(-31, 2147483647) = -31
+rem(-31, -2147483648) = -31
+rem(2147483647, 1) = 0
+rem(2147483647, -1) = 0
+rem(2147483647, 31) = 1
+rem(2147483647, -31) = 1
+rem(2147483647, 2147483647) = 0
+rem(2147483647, -2147483648) = 2147483647
+rem(-2147483648, 1) = 0
+rem(-2147483648, 31) = -2
+rem(-2147483648, -31) = -2
+rem(-2147483648, 2147483647) = -1
+rem(-2147483648, -2147483648) = 0
+
+unchecked_rem(1, 1) = 0
+unchecked_rem(1, -1) = 0
+unchecked_rem(1, 31) = 1
+unchecked_rem(1, -31) = 1
+unchecked_rem(1, 2147483647) = 1
+unchecked_rem(1, -2147483648) = 1
+unchecked_rem(-1, 1) = 0
+unchecked_rem(-1, -1) = 0
+unchecked_rem(-1, 31) = -1
+unchecked_rem(-1, -31) = -1
+unchecked_rem(-1, 2147483647) = -1
+unchecked_rem(-1, -2147483648) = -1
+unchecked_rem(31, 1) = 0
+unchecked_rem(31, -1) = 0
+unchecked_rem(31, 31) = 0
+unchecked_rem(31, -31) = 0
+unchecked_rem(31, 2147483647) = 31
+unchecked_rem(31, -2147483648) = 31
+unchecked_rem(-31, 1) = 0
+unchecked_rem(-31, -1) = 0
+unchecked_rem(-31, 31) = 0
+unchecked_rem(-31, -31) = 0
+unchecked_rem(-31, 2147483647) = -31
+unchecked_rem(-31, -2147483648) = -31
+unchecked_rem(2147483647, 1) = 0
+unchecked_rem(2147483647, -1) = 0
+unchecked_rem(2147483647, 31) = 1
+unchecked_rem(2147483647, -31) = 1
+unchecked_rem(2147483647, 2147483647) = 0
+unchecked_rem(2147483647, -2147483648) = 2147483647
+unchecked_rem(-2147483648, 1) = 0
+unchecked_rem(-2147483648, 31) = -2
+unchecked_rem(-2147483648, -31) = -2
+unchecked_rem(-2147483648, 2147483647) = -1
+unchecked_rem(-2147483648, -2147483648) = 0
+
+left_shift(1, 0) = 1
+left_shift(1, 1) = 2
+left_shift(1, -1) = 0
+left_shift(1, 31) = 2147483648
+left_shift(1, -31) = 0
+left_shift(-1, 0) = -1
+left_shift(-1, 1) = -2
+left_shift(-1, -1) = -1
+left_shift(-1, 31) = -2147483648
+left_shift(-1, -31) = -1
+left_shift(31, 0) = 31
+left_shift(31, 1) = 62
+left_shift(31, -1) = 15
+left_shift(31, 31) = 66571993088
+left_shift(31, -31) = 0
+left_shift(-31, 0) = -31
+left_shift(-31, 1) = -62
+left_shift(-31, -1) = -16
+left_shift(-31, 31) = -66571993088
+left_shift(-31, -31) = -1
+left_shift(2147483647, 0) = 2147483647
+left_shift(2147483647, 1) = 4294967294
+left_shift(2147483647, -1) = 1073741823
+left_shift(2147483647, 31) = 4611686016279904256
+left_shift(2147483647, -31) = 0
+left_shift(-2147483648, 0) = -2147483648
+left_shift(-2147483648, 1) = -4294967296
+left_shift(-2147483648, -1) = -1073741824
+left_shift(-2147483648, 31) = -4611686018427387904
+left_shift(-2147483648, -31) = -1
+
+unchecked_left_shift(1, 0) = 1
+unchecked_left_shift(1, 1) = 2
+unchecked_left_shift(1, 31) = 2147483648
+unchecked_left_shift(-1, 0) = -1
+unchecked_left_shift(-1, 1) = -2
+unchecked_left_shift(-1, 31) = -2147483648
+unchecked_left_shift(31, 0) = 31
+unchecked_left_shift(31, 1) = 62
+unchecked_left_shift(31, 31) = 66571993088
+unchecked_left_shift(-31, 0) = -31
+unchecked_left_shift(-31, 1) = -62
+unchecked_left_shift(-31, 31) = -66571993088
+unchecked_left_shift(2147483647, 0) = 2147483647
+unchecked_left_shift(2147483647, 1) = 4294967294
+unchecked_left_shift(2147483647, 31) = 4611686016279904256
+unchecked_left_shift(-2147483648, 0) = -2147483648
+unchecked_left_shift(-2147483648, 1) = -4294967296
+unchecked_left_shift(-2147483648, 31) = -4611686018427387904
+
+right_shift(1, 0) = 1
+right_shift(1, 1) = 0
+right_shift(1, -1) = 2
+right_shift(1, 31) = 0
+right_shift(1, -31) = 2147483648
+right_shift(-1, 0) = -1
+right_shift(-1, 1) = -1
+right_shift(-1, -1) = -2
+right_shift(-1, 31) = -1
+right_shift(-1, -31) = -2147483648
+right_shift(31, 0) = 31
+right_shift(31, 1) = 15
+right_shift(31, -1) = 62
+right_shift(31, 31) = 0
+right_shift(31, -31) = 66571993088
+right_shift(-31, 0) = -31
+right_shift(-31, 1) = -16
+right_shift(-31, -1) = -62
+right_shift(-31, 31) = -1
+right_shift(-31, -31) = -66571993088
+right_shift(2147483647, 0) = 2147483647
+right_shift(2147483647, 1) = 1073741823
+right_shift(2147483647, -1) = 4294967294
+right_shift(2147483647, 31) = 0
+right_shift(2147483647, -31) = 4611686016279904256
+right_shift(-2147483648, 0) = -2147483648
+right_shift(-2147483648, 1) = -1073741824
+right_shift(-2147483648, -1) = -4294967296
+right_shift(-2147483648, 31) = -1
+right_shift(-2147483648, -31) = -4611686018427387904
+
+unchecked_right_shift(1, 0) = 1
+unchecked_right_shift(1, 1) = 0
+unchecked_right_shift(1, 31) = 0
+unchecked_right_shift(-1, 0) = -1
+unchecked_right_shift(-1, 1) = -1
+unchecked_right_shift(-1, 31) = -1
+unchecked_right_shift(31, 0) = 31
+unchecked_right_shift(31, 1) = 15
+unchecked_right_shift(31, 31) = 0
+unchecked_right_shift(-31, 0) = -31
+unchecked_right_shift(-31, 1) = -16
+unchecked_right_shift(-31, 31) = -1
+unchecked_right_shift(2147483647, 0) = 2147483647
+unchecked_right_shift(2147483647, 1) = 1073741823
+unchecked_right_shift(2147483647, 31) = 0
+unchecked_right_shift(-2147483648, 0) = -2147483648
+unchecked_right_shift(-2147483648, 1) = -1073741824
+unchecked_right_shift(-2147483648, 31) = -1
+
diff --git a/tests/hard_coded/constant_prop_int.m b/tests/hard_coded/constant_prop_int.m
new file mode 100644
index 0000000..7b8c50a
--- /dev/null
+++ b/tests/hard_coded/constant_prop_int.m
@@ -0,0 +1,904 @@
+%---------------------------------------------------------------------------%
+% vim: ts=4 sw=4 et ft=mercury
+%---------------------------------------------------------------------------%
+
+:- module constant_prop_int.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+:- implementation.
+
+:- import_module int.
+
+main(!IO) :-
+    test_plus(!IO),
+    test_minus(!IO),
+    test_times(!IO),
+    test_quotient(!IO),
+    test_unchecked_quotient(!IO),
+    test_mod(!IO),
+    test_rem(!IO),
+    test_unchecked_rem(!IO),
+    test_left_shift(!IO),
+    test_unchecked_left_shift(!IO),
+    test_right_shift(!IO),
+    test_unchecked_right_shift(!IO),
+    true.
+
+:- pred test_plus(io::di, io::uo) is det.
+
+test_plus -->
+    label("plus(1, 0) = "),
+    result(1 + 0),
+    label("plus(1, 1) = "),
+    result(1 + 1),
+    label("plus(1, -1) = "),
+    result(1 + -1),
+    label("plus(1, 31) = "),
+    result(1 + 31),
+    label("plus(1, -31) = "),
+    result(1 + -31),
+    label("plus(1, 2147483647) = "),
+    result(1 + 2147483647),
+    label("plus(1, -2147483648) = "),
+    result(1 + -2147483648),
+    label("plus(-1, 0) = "),
+    result(-1 + 0),
+    label("plus(-1, 1) = "),
+    result(-1 + 1),
+    label("plus(-1, -1) = "),
+    result(-1 + -1),
+    label("plus(-1, 31) = "),
+    result(-1 + 31),
+    label("plus(-1, -31) = "),
+    result(-1 + -31),
+    label("plus(-1, 2147483647) = "),
+    result(-1 + 2147483647),
+    label("plus(-1, -2147483648) = "),
+    result(-1 + -2147483648),
+    label("plus(31, 0) = "),
+    result(31 + 0),
+    label("plus(31, 1) = "),
+    result(31 + 1),
+    label("plus(31, -1) = "),
+    result(31 + -1),
+    label("plus(31, 31) = "),
+    result(31 + 31),
+    label("plus(31, -31) = "),
+    result(31 + -31),
+    label("plus(31, 2147483647) = "),
+    result(31 + 2147483647),
+    label("plus(31, -2147483648) = "),
+    result(31 + -2147483648),
+    label("plus(-31, 0) = "),
+    result(-31 + 0),
+    label("plus(-31, 1) = "),
+    result(-31 + 1),
+    label("plus(-31, -1) = "),
+    result(-31 + -1),
+    label("plus(-31, 31) = "),
+    result(-31 + 31),
+    label("plus(-31, -31) = "),
+    result(-31 + -31),
+    label("plus(-31, 2147483647) = "),
+    result(-31 + 2147483647),
+    label("plus(-31, -2147483648) = "),
+    result(-31 + -2147483648),
+    label("plus(2147483647, 0) = "),
+    result(2147483647 + 0),
+    label("plus(2147483647, 1) = "),
+    result(2147483647 + 1),
+    label("plus(2147483647, -1) = "),
+    result(2147483647 + -1),
+    label("plus(2147483647, 31) = "),
+    result(2147483647 + 31),
+    label("plus(2147483647, -31) = "),
+    result(2147483647 + -31),
+    label("plus(2147483647, 2147483647) = "),
+    result(2147483647 + 2147483647),
+    label("plus(2147483647, -2147483648) = "),
+    result(2147483647 + -2147483648),
+    label("plus(-2147483648, 0) = "),
+    result(-2147483648 + 0),
+    label("plus(-2147483648, 1) = "),
+    result(-2147483648 + 1),
+    label("plus(-2147483648, -1) = "),
+    result(-2147483648 + -1),
+    label("plus(-2147483648, 31) = "),
+    result(-2147483648 + 31),
+    label("plus(-2147483648, -31) = "),
+    result(-2147483648 + -31),
+    label("plus(-2147483648, 2147483647) = "),
+    result(-2147483648 + 2147483647),
+    label("plus(-2147483648, -2147483648) = "),
+    result(-2147483648 + -2147483648),
+    nl.
+
+:- pred test_minus(io::di, io::uo) is det.
+
+test_minus -->
+    label("minus(1, 0) = "),
+    result(1 - 0),
+    label("minus(1, 1) = "),
+    result(1 - 1),
+    label("minus(1, -1) = "),
+    result(1 - -1),
+    label("minus(1, 31) = "),
+    result(1 - 31),
+    label("minus(1, -31) = "),
+    result(1 - -31),
+    label("minus(1, 2147483647) = "),
+    result(1 - 2147483647),
+    label("minus(1, -2147483648) = "),
+    result(1 - -2147483648),
+    label("minus(-1, 0) = "),
+    result(-1 - 0),
+    label("minus(-1, 1) = "),
+    result(-1 - 1),
+    label("minus(-1, -1) = "),
+    result(-1 - -1),
+    label("minus(-1, 31) = "),
+    result(-1 - 31),
+    label("minus(-1, -31) = "),
+    result(-1 - -31),
+    label("minus(-1, 2147483647) = "),
+    result(-1 - 2147483647),
+    label("minus(-1, -2147483648) = "),
+    result(-1 - -2147483648),
+    label("minus(31, 0) = "),
+    result(31 - 0),
+    label("minus(31, 1) = "),
+    result(31 - 1),
+    label("minus(31, -1) = "),
+    result(31 - -1),
+    label("minus(31, 31) = "),
+    result(31 - 31),
+    label("minus(31, -31) = "),
+    result(31 - -31),
+    label("minus(31, 2147483647) = "),
+    result(31 - 2147483647),
+    label("minus(31, -2147483648) = "),
+    result(31 - -2147483648),
+    label("minus(-31, 0) = "),
+    result(-31 - 0),
+    label("minus(-31, 1) = "),
+    result(-31 - 1),
+    label("minus(-31, -1) = "),
+    result(-31 - -1),
+    label("minus(-31, 31) = "),
+    result(-31 - 31),
+    label("minus(-31, -31) = "),
+    result(-31 - -31),
+    label("minus(-31, 2147483647) = "),
+    result(-31 - 2147483647),
+    label("minus(-31, -2147483648) = "),
+    result(-31 - -2147483648),
+    label("minus(2147483647, 0) = "),
+    result(2147483647 - 0),
+    label("minus(2147483647, 1) = "),
+    result(2147483647 - 1),
+    label("minus(2147483647, -1) = "),
+    result(2147483647 - -1),
+    label("minus(2147483647, 31) = "),
+    result(2147483647 - 31),
+    label("minus(2147483647, -31) = "),
+    result(2147483647 - -31),
+    label("minus(2147483647, 2147483647) = "),
+    result(2147483647 - 2147483647),
+    label("minus(2147483647, -2147483648) = "),
+    result(2147483647 - -2147483648),
+    label("minus(-2147483648, 0) = "),
+    result(-2147483648 - 0),
+    label("minus(-2147483648, 1) = "),
+    result(-2147483648 - 1),
+    label("minus(-2147483648, -1) = "),
+    result(-2147483648 - -1),
+    label("minus(-2147483648, 31) = "),
+    result(-2147483648 - 31),
+    label("minus(-2147483648, -31) = "),
+    result(-2147483648 - -31),
+    label("minus(-2147483648, 2147483647) = "),
+    result(-2147483648 - 2147483647),
+    label("minus(-2147483648, -2147483648) = "),
+    result(-2147483648 - -2147483648),
+    nl.
+
+:- pred test_times(io::di, io::uo) is det.
+
+test_times -->
+    label("times(1, 0) = "),
+    result(1 * 0),
+    label("times(1, 1) = "),
+    result(1 * 1),
+    label("times(1, -1) = "),
+    result(1 * -1),
+    label("times(1, 31) = "),
+    result(1 * 31),
+    label("times(1, -31) = "),
+    result(1 * -31),
+    label("times(1, 2147483647) = "),
+    result(1 * 2147483647),
+    label("times(1, -2147483648) = "),
+    result(1 * -2147483648),
+    label("times(-1, 0) = "),
+    result(-1 * 0),
+    label("times(-1, 1) = "),
+    result(-1 * 1),
+    label("times(-1, -1) = "),
+    result(-1 * -1),
+    label("times(-1, 31) = "),
+    result(-1 * 31),
+    label("times(-1, -31) = "),
+    result(-1 * -31),
+    label("times(-1, 2147483647) = "),
+    result(-1 * 2147483647),
+    label("times(-1, -2147483648) = "),
+    result(-1 * -2147483648),
+    label("times(31, 0) = "),
+    result(31 * 0),
+    label("times(31, 1) = "),
+    result(31 * 1),
+    label("times(31, -1) = "),
+    result(31 * -1),
+    label("times(31, 31) = "),
+    result(31 * 31),
+    label("times(31, -31) = "),
+    result(31 * -31),
+    label("times(31, 2147483647) = "),
+    result(31 * 2147483647),
+    label("times(31, -2147483648) = "),
+    result(31 * -2147483648),
+    label("times(-31, 0) = "),
+    result(-31 * 0),
+    label("times(-31, 1) = "),
+    result(-31 * 1),
+    label("times(-31, -1) = "),
+    result(-31 * -1),
+    label("times(-31, 31) = "),
+    result(-31 * 31),
+    label("times(-31, -31) = "),
+    result(-31 * -31),
+    label("times(-31, 2147483647) = "),
+    result(-31 * 2147483647),
+    label("times(-31, -2147483648) = "),
+    result(-31 * -2147483648),
+    label("times(2147483647, 0) = "),
+    result(2147483647 * 0),
+    label("times(2147483647, 1) = "),
+    result(2147483647 * 1),
+    label("times(2147483647, -1) = "),
+    result(2147483647 * -1),
+    label("times(2147483647, 31) = "),
+    result(2147483647 * 31),
+    label("times(2147483647, -31) = "),
+    result(2147483647 * -31),
+    label("times(2147483647, 2147483647) = "),
+    result(2147483647 * 2147483647),
+    label("times(2147483647, -2147483648) = "),
+    result(2147483647 * -2147483648),
+    label("times(-2147483648, 0) = "),
+    result(-2147483648 * 0),
+    label("times(-2147483648, 1) = "),
+    result(-2147483648 * 1),
+    label("times(-2147483648, -1) = "),
+    result(-2147483648 * -1),
+    label("times(-2147483648, 31) = "),
+    result(-2147483648 * 31),
+    label("times(-2147483648, -31) = "),
+    result(-2147483648 * -31),
+    label("times(-2147483648, 2147483647) = "),
+    result(-2147483648 * 2147483647),
+    label("times(-2147483648, -2147483648) = "),
+    result(-2147483648 * -2147483648),
+    nl.
+
+:- pred test_quotient(io::di, io::uo) is det.
+
+test_quotient -->
+    label("quotient(1, 1) = "),
+    result(1 // 1),
+    label("quotient(1, -1) = "),
+    result(1 // -1),
+    label("quotient(1, 31) = "),
+    result(1 // 31),
+    label("quotient(1, -31) = "),
+    result(1 // -31),
+    label("quotient(1, 2147483647) = "),
+    result(1 // 2147483647),
+    label("quotient(1, -2147483648) = "),
+    result(1 // -2147483648),
+    label("quotient(-1, 1) = "),
+    result(-1 // 1),
+    label("quotient(-1, -1) = "),
+    result(-1 // -1),
+    label("quotient(-1, 31) = "),
+    result(-1 // 31),
+    label("quotient(-1, -31) = "),
+    result(-1 // -31),
+    label("quotient(-1, 2147483647) = "),
+    result(-1 // 2147483647),
+    label("quotient(-1, -2147483648) = "),
+    result(-1 // -2147483648),
+    label("quotient(31, 1) = "),
+    result(31 // 1),
+    label("quotient(31, -1) = "),
+    result(31 // -1),
+    label("quotient(31, 31) = "),
+    result(31 // 31),
+    label("quotient(31, -31) = "),
+    result(31 // -31),
+    label("quotient(31, 2147483647) = "),
+    result(31 // 2147483647),
+    label("quotient(31, -2147483648) = "),
+    result(31 // -2147483648),
+    label("quotient(-31, 1) = "),
+    result(-31 // 1),
+    label("quotient(-31, -1) = "),
+    result(-31 // -1),
+    label("quotient(-31, 31) = "),
+    result(-31 // 31),
+    label("quotient(-31, -31) = "),
+    result(-31 // -31),
+    label("quotient(-31, 2147483647) = "),
+    result(-31 // 2147483647),
+    label("quotient(-31, -2147483648) = "),
+    result(-31 // -2147483648),
+    label("quotient(2147483647, 1) = "),
+    result(2147483647 // 1),
+    label("quotient(2147483647, -1) = "),
+    result(2147483647 // -1),
+    label("quotient(2147483647, 31) = "),
+    result(2147483647 // 31),
+    label("quotient(2147483647, -31) = "),
+    result(2147483647 // -31),
+    label("quotient(2147483647, 2147483647) = "),
+    result(2147483647 // 2147483647),
+    label("quotient(2147483647, -2147483648) = "),
+    result(2147483647 // -2147483648),
+    label("quotient(-2147483648, 1) = "),
+    result(-2147483648 // 1),
+    % label("quotient(-2147483648, -1) = "),
+    % result(-2147483648 // -1),
+    label("quotient(-2147483648, 31) = "),
+    result(-2147483648 // 31),
+    label("quotient(-2147483648, -31) = "),
+    result(-2147483648 // -31),
+    label("quotient(-2147483648, 2147483647) = "),
+    result(-2147483648 // 2147483647),
+    label("quotient(-2147483648, -2147483648) = "),
+    result(-2147483648 // -2147483648),
+    nl.
+
+:- pred test_unchecked_quotient(io::di, io::uo) is det.
+
+test_unchecked_quotient -->
+    label("unchecked_quotient(1, 1) = "),
+    result(unchecked_quotient(1, 1)),
+    label("unchecked_quotient(1, -1) = "),
+    result(unchecked_quotient(1, -1)),
+    label("unchecked_quotient(1, 31) = "),
+    result(unchecked_quotient(1, 31)),
+    label("unchecked_quotient(1, -31) = "),
+    result(unchecked_quotient(1, -31)),
+    label("unchecked_quotient(1, 2147483647) = "),
+    result(unchecked_quotient(1, 2147483647)),
+    label("unchecked_quotient(1, -2147483648) = "),
+    result(unchecked_quotient(1, -2147483648)),
+    label("unchecked_quotient(-1, 1) = "),
+    result(unchecked_quotient(-1, 1)),
+    label("unchecked_quotient(-1, -1) = "),
+    result(unchecked_quotient(-1, -1)),
+    label("unchecked_quotient(-1, 31) = "),
+    result(unchecked_quotient(-1, 31)),
+    label("unchecked_quotient(-1, -31) = "),
+    result(unchecked_quotient(-1, -31)),
+    label("unchecked_quotient(-1, 2147483647) = "),
+    result(unchecked_quotient(-1, 2147483647)),
+    label("unchecked_quotient(-1, -2147483648) = "),
+    result(unchecked_quotient(-1, -2147483648)),
+    label("unchecked_quotient(31, 1) = "),
+    result(unchecked_quotient(31, 1)),
+    label("unchecked_quotient(31, -1) = "),
+    result(unchecked_quotient(31, -1)),
+    label("unchecked_quotient(31, 31) = "),
+    result(unchecked_quotient(31, 31)),
+    label("unchecked_quotient(31, -31) = "),
+    result(unchecked_quotient(31, -31)),
+    label("unchecked_quotient(31, 2147483647) = "),
+    result(unchecked_quotient(31, 2147483647)),
+    label("unchecked_quotient(31, -2147483648) = "),
+    result(unchecked_quotient(31, -2147483648)),
+    label("unchecked_quotient(-31, 1) = "),
+    result(unchecked_quotient(-31, 1)),
+    label("unchecked_quotient(-31, -1) = "),
+    result(unchecked_quotient(-31, -1)),
+    label("unchecked_quotient(-31, 31) = "),
+    result(unchecked_quotient(-31, 31)),
+    label("unchecked_quotient(-31, -31) = "),
+    result(unchecked_quotient(-31, -31)),
+    label("unchecked_quotient(-31, 2147483647) = "),
+    result(unchecked_quotient(-31, 2147483647)),
+    label("unchecked_quotient(-31, -2147483648) = "),
+    result(unchecked_quotient(-31, -2147483648)),
+    label("unchecked_quotient(2147483647, 1) = "),
+    result(unchecked_quotient(2147483647, 1)),
+    label("unchecked_quotient(2147483647, -1) = "),
+    result(unchecked_quotient(2147483647, -1)),
+    label("unchecked_quotient(2147483647, 31) = "),
+    result(unchecked_quotient(2147483647, 31)),
+    label("unchecked_quotient(2147483647, -31) = "),
+    result(unchecked_quotient(2147483647, -31)),
+    label("unchecked_quotient(2147483647, 2147483647) = "),
+    result(unchecked_quotient(2147483647, 2147483647)),
+    label("unchecked_quotient(2147483647, -2147483648) = "),
+    result(unchecked_quotient(2147483647, -2147483648)),
+    label("unchecked_quotient(-2147483648, 1) = "),
+    result(unchecked_quotient(-2147483648, 1)),
+    % label("unchecked_quotient(-2147483648, -1) = "),
+    % result(unchecked_quotient(-2147483648, -1)),
+    label("unchecked_quotient(-2147483648, 31) = "),
+    result(unchecked_quotient(-2147483648, 31)),
+    label("unchecked_quotient(-2147483648, -31) = "),
+    result(unchecked_quotient(-2147483648, -31)),
+    label("unchecked_quotient(-2147483648, 2147483647) = "),
+    result(unchecked_quotient(-2147483648, 2147483647)),
+    label("unchecked_quotient(-2147483648, -2147483648) = "),
+    result(unchecked_quotient(-2147483648, -2147483648)),
+    nl.
+
+:- pred test_mod(io::di, io::uo) is det.
+
+test_mod -->
+    label("mod(1, 1) = "),
+    result(mod(1, 1)),
+    label("mod(1, -1) = "),
+    result(mod(1, -1)),
+    label("mod(1, 31) = "),
+    result(mod(1, 31)),
+    label("mod(1, -31) = "),
+    result(mod(1, -31)),
+    label("mod(1, 2147483647) = "),
+    result(mod(1, 2147483647)),
+    label("mod(1, -2147483648) = "),
+    result(mod(1, -2147483648)),
+    label("mod(-1, 1) = "),
+    result(mod(-1, 1)),
+    label("mod(-1, -1) = "),
+    result(mod(-1, -1)),
+    label("mod(-1, 31) = "),
+    result(mod(-1, 31)),
+    label("mod(-1, -31) = "),
+    result(mod(-1, -31)),
+    label("mod(-1, 2147483647) = "),
+    result(mod(-1, 2147483647)),
+    label("mod(-1, -2147483648) = "),
+    result(mod(-1, -2147483648)),
+    label("mod(31, 1) = "),
+    result(mod(31, 1)),
+    label("mod(31, -1) = "),
+    result(mod(31, -1)),
+    label("mod(31, 31) = "),
+    result(mod(31, 31)),
+    label("mod(31, -31) = "),
+    result(mod(31, -31)),
+    label("mod(31, 2147483647) = "),
+    result(mod(31, 2147483647)),
+    label("mod(31, -2147483648) = "),
+    result(mod(31, -2147483648)),
+    label("mod(-31, 1) = "),
+    result(mod(-31, 1)),
+    label("mod(-31, -1) = "),
+    result(mod(-31, -1)),
+    label("mod(-31, 31) = "),
+    result(mod(-31, 31)),
+    label("mod(-31, -31) = "),
+    result(mod(-31, -31)),
+    label("mod(-31, 2147483647) = "),
+    result(mod(-31, 2147483647)),
+    label("mod(-31, -2147483648) = "),
+    result(mod(-31, -2147483648)),
+    label("mod(2147483647, 1) = "),
+    result(mod(2147483647, 1)),
+    label("mod(2147483647, -1) = "),
+    result(mod(2147483647, -1)),
+    label("mod(2147483647, 31) = "),
+    result(mod(2147483647, 31)),
+    label("mod(2147483647, -31) = "),
+    result(mod(2147483647, -31)),
+    label("mod(2147483647, 2147483647) = "),
+    result(mod(2147483647, 2147483647)),
+    label("mod(2147483647, -2147483648) = "),
+    result(mod(2147483647, -2147483648)),
+    label("mod(-2147483648, 1) = "),
+    result(mod(-2147483648, 1)),
+    % label("mod(-2147483648, -1) = "),
+    % result(mod(-2147483648, -1)),
+    label("mod(-2147483648, 31) = "),
+    result(mod(-2147483648, 31)),
+    label("mod(-2147483648, -31) = "),
+    result(mod(-2147483648, -31)),
+    label("mod(-2147483648, 2147483647) = "),
+    result(mod(-2147483648, 2147483647)),
+    label("mod(-2147483648, -2147483648) = "),
+    result(mod(-2147483648, -2147483648)),
+    nl.
+
+:- pred test_rem(io::di, io::uo) is det.
+
+test_rem -->
+    label("rem(1, 1) = "),
+    result(rem(1, 1)),
+    label("rem(1, -1) = "),
+    result(rem(1, -1)),
+    label("rem(1, 31) = "),
+    result(rem(1, 31)),
+    label("rem(1, -31) = "),
+    result(rem(1, -31)),
+    label("rem(1, 2147483647) = "),
+    result(rem(1, 2147483647)),
+    label("rem(1, -2147483648) = "),
+    result(rem(1, -2147483648)),
+    label("rem(-1, 1) = "),
+    result(rem(-1, 1)),
+    label("rem(-1, -1) = "),
+    result(rem(-1, -1)),
+    label("rem(-1, 31) = "),
+    result(rem(-1, 31)),
+    label("rem(-1, -31) = "),
+    result(rem(-1, -31)),
+    label("rem(-1, 2147483647) = "),
+    result(rem(-1, 2147483647)),
+    label("rem(-1, -2147483648) = "),
+    result(rem(-1, -2147483648)),
+    label("rem(31, 1) = "),
+    result(rem(31, 1)),
+    label("rem(31, -1) = "),
+    result(rem(31, -1)),
+    label("rem(31, 31) = "),
+    result(rem(31, 31)),
+    label("rem(31, -31) = "),
+    result(rem(31, -31)),
+    label("rem(31, 2147483647) = "),
+    result(rem(31, 2147483647)),
+    label("rem(31, -2147483648) = "),
+    result(rem(31, -2147483648)),
+    label("rem(-31, 1) = "),
+    result(rem(-31, 1)),
+    label("rem(-31, -1) = "),
+    result(rem(-31, -1)),
+    label("rem(-31, 31) = "),
+    result(rem(-31, 31)),
+    label("rem(-31, -31) = "),
+    result(rem(-31, -31)),
+    label("rem(-31, 2147483647) = "),
+    result(rem(-31, 2147483647)),
+    label("rem(-31, -2147483648) = "),
+    result(rem(-31, -2147483648)),
+    label("rem(2147483647, 1) = "),
+    result(rem(2147483647, 1)),
+    label("rem(2147483647, -1) = "),
+    result(rem(2147483647, -1)),
+    label("rem(2147483647, 31) = "),
+    result(rem(2147483647, 31)),
+    label("rem(2147483647, -31) = "),
+    result(rem(2147483647, -31)),
+    label("rem(2147483647, 2147483647) = "),
+    result(rem(2147483647, 2147483647)),
+    label("rem(2147483647, -2147483648) = "),
+    result(rem(2147483647, -2147483648)),
+    label("rem(-2147483648, 1) = "),
+    result(rem(-2147483648, 1)),
+    % label("rem(-2147483648, -1) = "),
+    % result(rem(-2147483648, -1)),
+    label("rem(-2147483648, 31) = "),
+    result(rem(-2147483648, 31)),
+    label("rem(-2147483648, -31) = "),
+    result(rem(-2147483648, -31)),
+    label("rem(-2147483648, 2147483647) = "),
+    result(rem(-2147483648, 2147483647)),
+    label("rem(-2147483648, -2147483648) = "),
+    result(rem(-2147483648, -2147483648)),
+    nl.
+
+:- pred test_unchecked_rem(io::di, io::uo) is det.
+
+test_unchecked_rem -->
+    label("unchecked_rem(1, 1) = "),
+    result(unchecked_rem(1, 1)),
+    label("unchecked_rem(1, -1) = "),
+    result(unchecked_rem(1, -1)),
+    label("unchecked_rem(1, 31) = "),
+    result(unchecked_rem(1, 31)),
+    label("unchecked_rem(1, -31) = "),
+    result(unchecked_rem(1, -31)),
+    label("unchecked_rem(1, 2147483647) = "),
+    result(unchecked_rem(1, 2147483647)),
+    label("unchecked_rem(1, -2147483648) = "),
+    result(unchecked_rem(1, -2147483648)),
+    label("unchecked_rem(-1, 1) = "),
+    result(unchecked_rem(-1, 1)),
+    label("unchecked_rem(-1, -1) = "),
+    result(unchecked_rem(-1, -1)),
+    label("unchecked_rem(-1, 31) = "),
+    result(unchecked_rem(-1, 31)),
+    label("unchecked_rem(-1, -31) = "),
+    result(unchecked_rem(-1, -31)),
+    label("unchecked_rem(-1, 2147483647) = "),
+    result(unchecked_rem(-1, 2147483647)),
+    label("unchecked_rem(-1, -2147483648) = "),
+    result(unchecked_rem(-1, -2147483648)),
+    label("unchecked_rem(31, 1) = "),
+    result(unchecked_rem(31, 1)),
+    label("unchecked_rem(31, -1) = "),
+    result(unchecked_rem(31, -1)),
+    label("unchecked_rem(31, 31) = "),
+    result(unchecked_rem(31, 31)),
+    label("unchecked_rem(31, -31) = "),
+    result(unchecked_rem(31, -31)),
+    label("unchecked_rem(31, 2147483647) = "),
+    result(unchecked_rem(31, 2147483647)),
+    label("unchecked_rem(31, -2147483648) = "),
+    result(unchecked_rem(31, -2147483648)),
+    label("unchecked_rem(-31, 1) = "),
+    result(unchecked_rem(-31, 1)),
+    label("unchecked_rem(-31, -1) = "),
+    result(unchecked_rem(-31, -1)),
+    label("unchecked_rem(-31, 31) = "),
+    result(unchecked_rem(-31, 31)),
+    label("unchecked_rem(-31, -31) = "),
+    result(unchecked_rem(-31, -31)),
+    label("unchecked_rem(-31, 2147483647) = "),
+    result(unchecked_rem(-31, 2147483647)),
+    label("unchecked_rem(-31, -2147483648) = "),
+    result(unchecked_rem(-31, -2147483648)),
+    label("unchecked_rem(2147483647, 1) = "),
+    result(unchecked_rem(2147483647, 1)),
+    label("unchecked_rem(2147483647, -1) = "),
+    result(unchecked_rem(2147483647, -1)),
+    label("unchecked_rem(2147483647, 31) = "),
+    result(unchecked_rem(2147483647, 31)),
+    label("unchecked_rem(2147483647, -31) = "),
+    result(unchecked_rem(2147483647, -31)),
+    label("unchecked_rem(2147483647, 2147483647) = "),
+    result(unchecked_rem(2147483647, 2147483647)),
+    label("unchecked_rem(2147483647, -2147483648) = "),
+    result(unchecked_rem(2147483647, -2147483648)),
+    label("unchecked_rem(-2147483648, 1) = "),
+    result(unchecked_rem(-2147483648, 1)),
+    % label("unchecked_rem(-2147483648, -1) = "),
+    % result(unchecked_rem(-2147483648, -1)),
+    label("unchecked_rem(-2147483648, 31) = "),
+    result(unchecked_rem(-2147483648, 31)),
+    label("unchecked_rem(-2147483648, -31) = "),
+    result(unchecked_rem(-2147483648, -31)),
+    label("unchecked_rem(-2147483648, 2147483647) = "),
+    result(unchecked_rem(-2147483648, 2147483647)),
+    label("unchecked_rem(-2147483648, -2147483648) = "),
+    result(unchecked_rem(-2147483648, -2147483648)),
+    nl.
+
+:- pred test_left_shift(io::di, io::uo) is det.
+
+test_left_shift -->
+    label("left_shift(1, 0) = "),
+    result(1 << 0),
+    label("left_shift(1, 1) = "),
+    result(1 << 1),
+    label("left_shift(1, -1) = "),
+    result(1 << -1),
+    label("left_shift(1, 31) = "),
+    result(1 << 31),
+    label("left_shift(1, -31) = "),
+    result(1 << -31),
+    label("left_shift(-1, 0) = "),
+    result(-1 << 0),
+    label("left_shift(-1, 1) = "),
+    result(-1 << 1),
+    label("left_shift(-1, -1) = "),
+    result(-1 << -1),
+    label("left_shift(-1, 31) = "),
+    result(-1 << 31),
+    label("left_shift(-1, -31) = "),
+    result(-1 << -31),
+    label("left_shift(31, 0) = "),
+    result(31 << 0),
+    label("left_shift(31, 1) = "),
+    result(31 << 1),
+    label("left_shift(31, -1) = "),
+    result(31 << -1),
+    label("left_shift(31, 31) = "),
+    result(31 << 31),
+    label("left_shift(31, -31) = "),
+    result(31 << -31),
+    label("left_shift(-31, 0) = "),
+    result(-31 << 0),
+    label("left_shift(-31, 1) = "),
+    result(-31 << 1),
+    label("left_shift(-31, -1) = "),
+    result(-31 << -1),
+    label("left_shift(-31, 31) = "),
+    result(-31 << 31),
+    label("left_shift(-31, -31) = "),
+    result(-31 << -31),
+    label("left_shift(2147483647, 0) = "),
+    result(2147483647 << 0),
+    label("left_shift(2147483647, 1) = "),
+    result(2147483647 << 1),
+    label("left_shift(2147483647, -1) = "),
+    result(2147483647 << -1),
+    label("left_shift(2147483647, 31) = "),
+    result(2147483647 << 31),
+    label("left_shift(2147483647, -31) = "),
+    result(2147483647 << -31),
+    label("left_shift(-2147483648, 0) = "),
+    result(-2147483648 << 0),
+    label("left_shift(-2147483648, 1) = "),
+    result(-2147483648 << 1),
+    label("left_shift(-2147483648, -1) = "),
+    result(-2147483648 << -1),
+    label("left_shift(-2147483648, 31) = "),
+    result(-2147483648 << 31),
+    label("left_shift(-2147483648, -31) = "),
+    result(-2147483648 << -31),
+    nl.
+
+:- pred test_unchecked_left_shift(io::di, io::uo) is det.
+
+test_unchecked_left_shift -->
+    label("unchecked_left_shift(1, 0) = "),
+    result(unchecked_left_shift(1, 0)),
+    label("unchecked_left_shift(1, 1) = "),
+    result(unchecked_left_shift(1, 1)),
+    label("unchecked_left_shift(1, 31) = "),
+    result(unchecked_left_shift(1, 31)),
+    label("unchecked_left_shift(-1, 0) = "),
+    result(unchecked_left_shift(-1, 0)),
+    label("unchecked_left_shift(-1, 1) = "),
+    result(unchecked_left_shift(-1, 1)),
+    label("unchecked_left_shift(-1, 31) = "),
+    result(unchecked_left_shift(-1, 31)),
+    label("unchecked_left_shift(31, 0) = "),
+    result(unchecked_left_shift(31, 0)),
+    label("unchecked_left_shift(31, 1) = "),
+    result(unchecked_left_shift(31, 1)),
+    label("unchecked_left_shift(31, 31) = "),
+    result(unchecked_left_shift(31, 31)),
+    label("unchecked_left_shift(-31, 0) = "),
+    result(unchecked_left_shift(-31, 0)),
+    label("unchecked_left_shift(-31, 1) = "),
+    result(unchecked_left_shift(-31, 1)),
+    label("unchecked_left_shift(-31, 31) = "),
+    result(unchecked_left_shift(-31, 31)),
+    label("unchecked_left_shift(2147483647, 0) = "),
+    result(unchecked_left_shift(2147483647, 0)),
+    label("unchecked_left_shift(2147483647, 1) = "),
+    result(unchecked_left_shift(2147483647, 1)),
+    label("unchecked_left_shift(2147483647, 31) = "),
+    result(unchecked_left_shift(2147483647, 31)),
+    label("unchecked_left_shift(-2147483648, 0) = "),
+    result(unchecked_left_shift(-2147483648, 0)),
+    label("unchecked_left_shift(-2147483648, 1) = "),
+    result(unchecked_left_shift(-2147483648, 1)),
+    label("unchecked_left_shift(-2147483648, 31) = "),
+    result(unchecked_left_shift(-2147483648, 31)),
+    nl.
+
+:- pred test_right_shift(io::di, io::uo) is det.
+
+test_right_shift -->
+    label("right_shift(1, 0) = "),
+    result(1 >> 0),
+    label("right_shift(1, 1) = "),
+    result(1 >> 1),
+    label("right_shift(1, -1) = "),
+    result(1 >> -1),
+    label("right_shift(1, 31) = "),
+    result(1 >> 31),
+    label("right_shift(1, -31) = "),
+    result(1 >> -31),
+    label("right_shift(-1, 0) = "),
+    result(-1 >> 0),
+    label("right_shift(-1, 1) = "),
+    result(-1 >> 1),
+    label("right_shift(-1, -1) = "),
+    result(-1 >> -1),
+    label("right_shift(-1, 31) = "),
+    result(-1 >> 31),
+    label("right_shift(-1, -31) = "),
+    result(-1 >> -31),
+    label("right_shift(31, 0) = "),
+    result(31 >> 0),
+    label("right_shift(31, 1) = "),
+    result(31 >> 1),
+    label("right_shift(31, -1) = "),
+    result(31 >> -1),
+    label("right_shift(31, 31) = "),
+    result(31 >> 31),
+    label("right_shift(31, -31) = "),
+    result(31 >> -31),
+    label("right_shift(-31, 0) = "),
+    result(-31 >> 0),
+    label("right_shift(-31, 1) = "),
+    result(-31 >> 1),
+    label("right_shift(-31, -1) = "),
+    result(-31 >> -1),
+    label("right_shift(-31, 31) = "),
+    result(-31 >> 31),
+    label("right_shift(-31, -31) = "),
+    result(-31 >> -31),
+    label("right_shift(2147483647, 0) = "),
+    result(2147483647 >> 0),
+    label("right_shift(2147483647, 1) = "),
+    result(2147483647 >> 1),
+    label("right_shift(2147483647, -1) = "),
+    result(2147483647 >> -1),
+    label("right_shift(2147483647, 31) = "),
+    result(2147483647 >> 31),
+    label("right_shift(2147483647, -31) = "),
+    result(2147483647 >> -31),
+    label("right_shift(-2147483648, 0) = "),
+    result(-2147483648 >> 0),
+    label("right_shift(-2147483648, 1) = "),
+    result(-2147483648 >> 1),
+    label("right_shift(-2147483648, -1) = "),
+    result(-2147483648 >> -1),
+    label("right_shift(-2147483648, 31) = "),
+    result(-2147483648 >> 31),
+    label("right_shift(-2147483648, -31) = "),
+    result(-2147483648 >> -31),
+    nl.
+
+:- pred test_unchecked_right_shift(io::di, io::uo) is det.
+
+test_unchecked_right_shift -->
+    label("unchecked_right_shift(1, 0) = "),
+    result(unchecked_right_shift(1, 0)),
+    label("unchecked_right_shift(1, 1) = "),
+    result(unchecked_right_shift(1, 1)),
+    label("unchecked_right_shift(1, 31) = "),
+    result(unchecked_right_shift(1, 31)),
+    label("unchecked_right_shift(-1, 0) = "),
+    result(unchecked_right_shift(-1, 0)),
+    label("unchecked_right_shift(-1, 1) = "),
+    result(unchecked_right_shift(-1, 1)),
+    label("unchecked_right_shift(-1, 31) = "),
+    result(unchecked_right_shift(-1, 31)),
+    label("unchecked_right_shift(31, 0) = "),
+    result(unchecked_right_shift(31, 0)),
+    label("unchecked_right_shift(31, 1) = "),
+    result(unchecked_right_shift(31, 1)),
+    label("unchecked_right_shift(31, 31) = "),
+    result(unchecked_right_shift(31, 31)),
+    label("unchecked_right_shift(-31, 0) = "),
+    result(unchecked_right_shift(-31, 0)),
+    label("unchecked_right_shift(-31, 1) = "),
+    result(unchecked_right_shift(-31, 1)),
+    label("unchecked_right_shift(-31, 31) = "),
+    result(unchecked_right_shift(-31, 31)),
+    label("unchecked_right_shift(2147483647, 0) = "),
+    result(unchecked_right_shift(2147483647, 0)),
+    label("unchecked_right_shift(2147483647, 1) = "),
+    result(unchecked_right_shift(2147483647, 1)),
+    label("unchecked_right_shift(2147483647, 31) = "),
+    result(unchecked_right_shift(2147483647, 31)),
+    label("unchecked_right_shift(-2147483648, 0) = "),
+    result(unchecked_right_shift(-2147483648, 0)),
+    label("unchecked_right_shift(-2147483648, 1) = "),
+    result(unchecked_right_shift(-2147483648, 1)),
+    label("unchecked_right_shift(-2147483648, 31) = "),
+    result(unchecked_right_shift(-2147483648, 31)),
+    nl.
+
+:- pred label(string::in, io::di, io::uo) is det.
+
+label(X, !IO) :-
+    io.write_string(X, !IO).
+
+:- pred result(int::in, io::di, io::uo) is det.
+
+result(X, !IO) :-
+    io.write_int(X, !IO),
+    io.nl(!IO).
-- 
2.1.2




More information about the reviews mailing list