Original bug ID: 7442
Reporter: markghayden
Status: acknowledged (set by @xavierleroy on 2017-01-14T15:25:26Z)
Resolution: open
Priority: normal
Severity: feature
Platform: AMD64
OS: MacOS
OS Version: 10.12.2
Version: 4.04.0
Target version: later
Category: middle end (typedtree to clambda)
Has duplicate: #7440 #7441
Monitored by: @dbuenzli
Bug description
When you create an array of a abstract but concrete type, array operations on the type are never specialized. For instance see AbsInt2 below;
module AbsInt2 :
sig
type t val zero : t
val add_int : int -> t -> int
val array_length : t array -> int
val array_get : t array -> int -> t
end = struct
type t = int
let zero = 0
let add_int = (+)
let array_length a = Array.length (a:t array)
let array_get a i = Array.unsafe_get (a:t array) i
end
If you use Array.get to access an array of type AbsInt.t then the compiled code will check for whether the array is a float array (even though the type t is internally "int") and will compile code to allocate the boxed float if the array is a float array. On the other hand, using AbsInt2.array_get will be specialized as operations on an int array, avoiding the need to check for a float array. This is even though the operations are in the same compilation unit and the compiler has knowledge of the exact type. Using information hiding in the type system should not prevent optimizations by the compiler.
Note that the need to check for float array in the compiled code presumably has follow-on effects in the compiler, since the resulting code is larger I'd guess that this becomes less likely to be inlined -- even though much of it is "dead code".
Steps to reproduce
Compile the attached file with -O3 -unbox-closures with 4.05.0 compiler and review the compiled assembly code. In includes variations on the AbsInt module above. You can expose the internal type as int ("type t =int" in the signature. Or make use of specialized "array_length" functions to avoid the "float array" checks.
File attachments
Original bug ID: 7442
Reporter: markghayden
Status: acknowledged (set by @xavierleroy on 2017-01-14T15:25:26Z)
Resolution: open
Priority: normal
Severity: feature
Platform: AMD64
OS: MacOS
OS Version: 10.12.2
Version: 4.04.0
Target version: later
Category: middle end (typedtree to clambda)
Has duplicate: #7440 #7441
Monitored by: @dbuenzli
Bug description
When you create an array of a abstract but concrete type, array operations on the type are never specialized. For instance see AbsInt2 below;
module AbsInt2 :
sig
type t val zero : t
val add_int : int -> t -> int
val array_length : t array -> int
val array_get : t array -> int -> t
end = struct
type t = int
let zero = 0
let add_int = (+)
let array_length a = Array.length (a:t array)
let array_get a i = Array.unsafe_get (a:t array) i
end
If you use Array.get to access an array of type AbsInt.t then the compiled code will check for whether the array is a float array (even though the type t is internally "int") and will compile code to allocate the boxed float if the array is a float array. On the other hand, using AbsInt2.array_get will be specialized as operations on an int array, avoiding the need to check for a float array. This is even though the operations are in the same compilation unit and the compiler has knowledge of the exact type. Using information hiding in the type system should not prevent optimizations by the compiler.
Note that the need to check for float array in the compiled code presumably has follow-on effects in the compiler, since the resulting code is larger I'd guess that this becomes less likely to be inlined -- even though much of it is "dead code".
Steps to reproduce
Compile the attached file with -O3 -unbox-closures with 4.05.0 compiler and review the compiled assembly code. In includes variations on the AbsInt module above. You can expose the internal type as int ("type t =int" in the signature. Or make use of specialized "array_length" functions to avoid the "float array" checks.
File attachments