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

Simplify conversion sequences and overload scoring #261

Merged

Conversation

llvm-beanz
Copy link
Collaborator

@llvm-beanz llvm-beanz commented Jun 12, 2024

This change is a shift in how conversion sequences and overload scoring
is handled to disambiguate a few cases that DXC handles today through
simpler rules.

The main cases relate to scoring conversion sequences with dimension
adjustment conversions. With this change an implicit conversion sequence
is now defined as:

  • Value conversion (lvalue to rvalue or array decay)
  • Data conversion (int/float/bool/struct promotion or conversion)
  • Dimension conversion (splat or truncate)
  • CV qualifier conversion (add const)

Conversion sequences are still assigned the rank of their "highest"
conversion following the same chart as before where the ranks are:

  • Exact match
  • Scalar extension without promotion or conversion
  • Promotion
  • Scalar extension with promotion
  • Conversion
  • Scalar extension with conversion
  • Truncation without promotion or conversion
  • Truncation with promotion
  • Truncation with conversion

Given these rules:

ICS(float -> double) > ICS(float -> double3)
ICS(float -> double3) > ICS(float -> half)
ICS(float -> double2) == ICS(float -> dobule3)
ICS(float -> half) > ICS(float -> half3)
ICS(float4 -> double3) > ICS(float4 -> half3)
ICS(float4 -> double4) > ICS(float4 -> float2)
ICS(float4 -> half4) > ICS(float4 -> float2)

ICS(float -> double) > ICS(float -> float3)
ICS(float -> float3) > ICS(float -> double3)
ICS(float -> double4) > ICS(float -> half4)
ICS(float -> double4) != ICS(float -> double3)
ICS(double -> float4) != ICS(double -> float3)
ICS(double -> float4) != ICS(double -> half3)

ICS(float4 -> float3) > ICS(float4 -> double3)
ICS(float4 -> float3) > ICS(float4 -> half3)
ICS(float4 -> double3) > ICS(float4 -> half3)
ICS(double4 -> float3) != ICS(double4 ->half3)
ICS(half4 -> float3) != ICS(half4 ->double3)

This change is a shift in how conversion sequences and overload scoring
is handled to disambiguate a few cases that DXC handles today through
simpler rules.

The main cases relate to scoring conversion sequences with dimension
adjustment conversions. With this change an implicit conversion sequence
is now defined as:

* Value conversion (lvalue to rvalue or array decay)
* Data conversion (int/float/bool/struct promotion or conversion)
* Dimension conversion (splat or truncate)
* CV qualifier conversion (add const)

Conversion sequences are still assigned the rank of their "highest"
conversion following the same chart as before where the ranks are:

* Exact Match
* Extension
* Promotion
* Conversion
* Truncation

There is an added rule that if two conversion sequences are both of rank
*Promotion* or "Conversion" and one contains an *Extension* but the
other does not, the conversion without the *Extension* is the better
conversion sequence.

Given these rules:

ICS(float -> double) > ICS(float -> double3)
ICS(float -> double3) > ICS(float -> half)
ICS(float -> double2) == ICS(float -> dobule3)
ICS(float -> half) > ICS(float -> half3)
ICS(float4 -> double3) > ICS(float4 -> half3)
ICS(float4 -> double4) > ICS(float4 -> float2)
ICS(float4 -> half4) > ICS(float4 -> float2)
This updates the ordering of conversion ranks and disambiguation rule to handle a few more cases:

ICS(float -> double) > ICS(float -> float3)
ICS(float -> float3) > ICS(float -> double3)
ICS(float -> double4) > ICS(float -> half4)
ICS(float -> double4) != ICS(float -> double3)
ICS(double -> float4) != ICS(double -> float3)
ICS(double -> float4) != ICS(double -> half3)

ICS(float4 -> float3) > ICS(float4 -> double3)
ICS(float4 -> float3) > ICS(float4 -> half3)
ICS(float4 -> double3) > ICS(float4 -> half3)
ICS(double4 -> float3) != ICS(double4 ->half3)
ICS(half4 -> float3) != ICS(half4 ->double3)
It is no longer relevant
@llvm-beanz llvm-beanz merged commit 735cce6 into microsoft:main Jun 25, 2024
3 checks passed
llvm-beanz added a commit to llvm/llvm-project that referenced this pull request Jul 13, 2024
This PR reworks HLSL's implicit conversion sequences. Initially I was
seeking to match DXC's behavior more closely, but that was leading to a
pile of special case rules to tie-break ambiguous cases that should
really be left as ambiguous. We've decided that we're going to break
compatibility with DXC here, and we may port this new behavior over to
DXC instead.

This change is a bit closer to C++'s overload resolution rules, but it
does have a bit of nuance around how dimension adjustment conversions
are ranked. Conversion sequence ranks for HLSL are:

* Exact match
* Scalar Widening (i.e. splat)
* Promotion
* Scalar Widening with Promotion
* Conversion
* Scalar Widening with Conversion
* Dimension Reduction (i.e. truncation)
* Dimension Reduction with Promotion
* Dimension Reduction with Conversion

In this implementation I've folded the disambiguation into the
conversion sequence ranks which does add some complexity as compared to
C++, however this avoids needing to add special casing in
`CompareStandardConversionSequences`. I believe the added conversion
rank values provide a simpler approach, but feedback is appreciated.

The HLSL language spec updates are in the PR here:
microsoft/hlsl-specs#261
aaryanshukla pushed a commit to aaryanshukla/llvm-project that referenced this pull request Jul 14, 2024
This PR reworks HLSL's implicit conversion sequences. Initially I was
seeking to match DXC's behavior more closely, but that was leading to a
pile of special case rules to tie-break ambiguous cases that should
really be left as ambiguous. We've decided that we're going to break
compatibility with DXC here, and we may port this new behavior over to
DXC instead.

This change is a bit closer to C++'s overload resolution rules, but it
does have a bit of nuance around how dimension adjustment conversions
are ranked. Conversion sequence ranks for HLSL are:

* Exact match
* Scalar Widening (i.e. splat)
* Promotion
* Scalar Widening with Promotion
* Conversion
* Scalar Widening with Conversion
* Dimension Reduction (i.e. truncation)
* Dimension Reduction with Promotion
* Dimension Reduction with Conversion

In this implementation I've folded the disambiguation into the
conversion sequence ranks which does add some complexity as compared to
C++, however this avoids needing to add special casing in
`CompareStandardConversionSequences`. I believe the added conversion
rank values provide a simpler approach, but feedback is appreciated.

The HLSL language spec updates are in the PR here:
microsoft/hlsl-specs#261
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants