Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Always use typeEquivAux EraseMeasures (for integral range optimizations) #17048

Merged
merged 5 commits into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/release-notes/.FSharp.Compiler.Service/8.0.400.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
### Fixed

* Disallow calling abstract methods directly on interfaces. ([Issue #14012](https://github.com/dotnet/fsharp/issues/14012), [Issue #16299](https://github.com/dotnet/fsharp/issues/16299), [PR #17021](https://github.com/dotnet/fsharp/pull/17021))
* Various parenthesization API fixes. ([PR #16977](https://github.com/dotnet/fsharp/pull/16977))
* Fix bug in optimization of for-loops over integral ranges with steps and units of measure. ([Issue #17025](https://github.com/dotnet/fsharp/issues/17025), [PR #17040](https://github.com/dotnet/fsharp/pull/17040))
* Various parenthesization API fixes. ([PR #16977](https://github.com/dotnet/fsharp/pull/16977))
* Fix bug in optimization of for-loops over integral ranges with steps and units of measure. ([Issue #17025](https://github.com/dotnet/fsharp/issues/17025), [PR #17040](https://github.com/dotnet/fsharp/pull/17040), [PR #17048](https://github.com/dotnet/fsharp/pull/17048))
* Fix calling an overridden virtual static method via the interface ([PR #17013](https://github.com/dotnet/fsharp/pull/17013))
10 changes: 5 additions & 5 deletions src/Compiler/Optimize/LowerComputedCollections.fs
Original file line number Diff line number Diff line change
Expand Up @@ -314,21 +314,21 @@ module Array =
let arrayTy = mkArrayType g overallElemTy

let convToNativeInt ovf expr =
let ty = stripMeasuresFromTy g (tyOfExpr g expr)
let ty = tyOfExpr g expr

let conv =
match ovf with
| NoCheckOvf -> AI_conv DT_I
| CheckOvf when isSignedIntegerTy g ty -> AI_conv_ovf DT_I
| CheckOvf -> AI_conv_ovf_un DT_I

if typeEquiv g ty g.int64_ty then
if typeEquivAux EraseMeasures g ty g.int64_ty then
mkAsmExpr ([conv], [], [expr], [g.nativeint_ty], m)
elif typeEquiv g ty g.nativeint_ty then
elif typeEquivAux EraseMeasures g ty g.nativeint_ty then
mkAsmExpr ([conv], [], [mkAsmExpr ([AI_conv DT_I8], [], [expr], [g.int64_ty], m)], [g.nativeint_ty], m)
elif typeEquiv g ty g.uint64_ty then
elif typeEquivAux EraseMeasures g ty g.uint64_ty then
mkAsmExpr ([conv], [], [expr], [g.nativeint_ty], m)
elif typeEquiv g ty g.unativeint_ty then
elif typeEquivAux EraseMeasures g ty g.unativeint_ty then
mkAsmExpr ([conv], [], [mkAsmExpr ([AI_conv DT_U8], [], [expr], [g.uint64_ty], m)], [g.nativeint_ty], m)
else
expr
Expand Down
46 changes: 19 additions & 27 deletions src/Compiler/TypedTree/TypedTreeOps.fs
Original file line number Diff line number Diff line change
Expand Up @@ -10434,41 +10434,37 @@ let mkRangeCount g m rangeTy rangeExpr start step finish =
mkAsmExpr ([AI_clt_un], [], [e1; e2], [g.bool_ty], m)

let unsignedEquivalent ty =
if typeEquiv g ty g.int64_ty then g.uint64_ty
elif typeEquiv g ty g.int32_ty then g.uint32_ty
elif typeEquiv g ty g.int16_ty then g.uint16_ty
elif typeEquiv g ty g.sbyte_ty then g.byte_ty
if typeEquivAux EraseMeasures g ty g.int64_ty then g.uint64_ty
elif typeEquivAux EraseMeasures g ty g.int32_ty then g.uint32_ty
elif typeEquivAux EraseMeasures g ty g.int16_ty then g.uint16_ty
elif typeEquivAux EraseMeasures g ty g.sbyte_ty then g.byte_ty
else ty

/// Find the unsigned type with twice the width of the given type, if available.
let nextWidestUnsignedTy ty =
let ty = stripMeasuresFromTy g ty

if typeEquiv g ty g.int64_ty || typeEquiv g ty g.int32_ty || typeEquiv g ty g.uint32_ty then
if typeEquivAux EraseMeasures g ty g.int64_ty || typeEquivAux EraseMeasures g ty g.int32_ty || typeEquivAux EraseMeasures g ty g.uint32_ty then
g.uint64_ty
elif typeEquiv g ty g.int16_ty || typeEquiv g ty g.uint16_ty || typeEquiv g ty g.char_ty then
elif typeEquivAux EraseMeasures g ty g.int16_ty || typeEquivAux EraseMeasures g ty g.uint16_ty || typeEquivAux EraseMeasures g ty g.char_ty then
g.uint32_ty
elif typeEquiv g ty g.sbyte_ty || typeEquiv g ty g.byte_ty then
elif typeEquivAux EraseMeasures g ty g.sbyte_ty || typeEquivAux EraseMeasures g ty g.byte_ty then
g.uint16_ty
else
ty

/// Convert the value to the next-widest unsigned type.
/// We do this so that adding one won't result in overflow.
let mkWiden e =
let ty = stripMeasuresFromTy g rangeTy

if typeEquiv g ty g.int32_ty then
if typeEquivAux EraseMeasures g rangeTy g.int32_ty then
mkAsmExpr ([AI_conv DT_I8], [], [e], [g.uint64_ty], m)
elif typeEquiv g ty g.uint32_ty then
elif typeEquivAux EraseMeasures g rangeTy g.uint32_ty then
mkAsmExpr ([AI_conv DT_U8], [], [e], [g.uint64_ty], m)
elif typeEquiv g ty g.int16_ty then
elif typeEquivAux EraseMeasures g rangeTy g.int16_ty then
mkAsmExpr ([AI_conv DT_I4], [], [e], [g.uint32_ty], m)
elif typeEquiv g ty g.uint16_ty || typeEquiv g ty g.char_ty then
elif typeEquivAux EraseMeasures g rangeTy g.uint16_ty || typeEquivAux EraseMeasures g rangeTy g.char_ty then
mkAsmExpr ([AI_conv DT_U4], [], [e], [g.uint32_ty], m)
elif typeEquiv g ty g.sbyte_ty then
elif typeEquivAux EraseMeasures g rangeTy g.sbyte_ty then
mkAsmExpr ([AI_conv DT_I2], [], [e], [g.uint16_ty], m)
elif typeEquiv g ty g.byte_ty then
elif typeEquivAux EraseMeasures g rangeTy g.byte_ty then
mkAsmExpr ([AI_conv DT_U2], [], [e], [g.uint16_ty], m)
else
e
Expand All @@ -10481,12 +10477,10 @@ let mkRangeCount g m rangeTy rangeExpr start step finish =

/// Whether the total count might not fit in 64 bits.
let couldBeTooBig ty =
let underlying = stripMeasuresFromTy g ty

typeEquiv g underlying g.int64_ty
|| typeEquiv g underlying g.uint64_ty
|| typeEquiv g underlying g.nativeint_ty
|| typeEquiv g underlying g.unativeint_ty
typeEquivAux EraseMeasures g ty g.int64_ty
|| typeEquivAux EraseMeasures g ty g.uint64_ty
|| typeEquivAux EraseMeasures g ty g.nativeint_ty
|| typeEquivAux EraseMeasures g ty g.unativeint_ty

/// pseudoCount + 1
let mkAddOne pseudoCount =
Expand All @@ -10499,16 +10493,14 @@ let mkRangeCount g m rangeTy rangeExpr start step finish =
mkAsmExpr ([AI_add], [], [pseudoCount; mkTypedOne g m ty], [ty], m)

let mkRuntimeCalc mkThrowIfStepIsZero pseudoCount count =
let underlying = stripMeasuresFromTy g rangeTy

if typeEquiv g underlying g.int64_ty || typeEquiv g underlying g.uint64_ty then
if typeEquivAux EraseMeasures g rangeTy g.int64_ty || typeEquivAux EraseMeasures g rangeTy g.uint64_ty then
RangeCount.PossiblyOversize (fun mkLoopExpr ->
mkThrowIfStepIsZero
(mkCompGenLetIn m (nameof pseudoCount) (tyOfExpr g pseudoCount) pseudoCount (fun (_, pseudoCount) ->
let wouldOvf = mkILAsmCeq g m pseudoCount (Expr.Const (Const.UInt64 UInt64.MaxValue, m, g.uint64_ty))
mkCompGenLetIn m (nameof wouldOvf) g.bool_ty wouldOvf (fun (_, wouldOvf) ->
mkLoopExpr count wouldOvf))))
elif typeEquiv g underlying g.nativeint_ty || typeEquiv g underlying g.unativeint_ty then // We have a nativeint ty whose size we won't know till runtime.
elif typeEquivAux EraseMeasures g rangeTy g.nativeint_ty || typeEquivAux EraseMeasures g rangeTy g.unativeint_ty then // We have a nativeint ty whose size we won't know till runtime.
RangeCount.PossiblyOversize (fun mkLoopExpr ->
mkThrowIfStepIsZero
(mkCompGenLetIn m (nameof pseudoCount) (tyOfExpr g pseudoCount) pseudoCount (fun (_, pseudoCount) ->
Expand Down
Loading
Loading