Fixes#141840
This PR implements support for the `memcpy` intrinsic in the DXIL
CBuffer Access pass with the following restrictions:
- The CBuffer Access must be the `src` operand of `memcpy` and must be
direct (i.e., not a GEP)
- The type of the CBuffer Access must be of an Array Type
These restrictions greatly simplify the implementation of `memcpy` yet
still covers the known uses in DML shaders.
Furthermore, to prevent errors like #141840 from occurring silently
again, this PR adds error reporting for unsupported users of globals in
the DXIL CBuffer Access pass.
Implements static samplers parsing from root signature metadata
representation. This is required to support Root Signatures in HLSL.
Closes: #[126641](https://github.com/llvm/llvm-project/issues/126641)
---------
Co-authored-by: joaosaffran <joao.saffran@microsoft.com>
fixes#140321
Specifically it fixes ` error: Cannot create BufferLoad operation:
Invalid overload type`
https://hlsl.godbolt.org/z/dTq4q7o58
but no new DML shaders are building. This change now exposes #144747.
The change does two things it adds i64 support for intrinsic expansion
for the `dx_resource_load_typedbuffer`, and
`dx_resource_store_typedbuffer` intrinsics.
It also lets loaded typedbuffers crash more gracefully because of ` auto
*EVI = cast<ExtractValueInst>(U);` is now a `dyn_cast` and
`llvm_unreachable`.
fixes#145782
This change modifies `isArrayOfVectors` into `isVectorOrArrayOfVectors`.
The previous implementation did not support vector to array
transformations. Further it was too simplistic and didn't assume allocas
would create multidimensional arrays.
fixes#145408
Before we see the GEP we already have transformed Allocas that get
passed the `isArrayOfVectors`.
The bug is because we are trying to transform a gep for struct of arrays
when we should only be transforming arrays.
The problem with our `visitGetElementPtrInst` is that it was doing
transformations for all allocas when it should be limiting it to the
alloca of array cases. Technically we would have liked to make sure it
was an array of vectors cases but by the time we see the GEP the type
has been changed by replace all uses. There should not be a problem with
looking at all Arrays since DXILDataScalarization does not change any
indicies.
The `dx.rootsignatures` metadata is not recognized in DXIL, so failure
to remove this will cause validation errors.
This metadata is parsed (within `RootSignatureAnalysisWrapper`) into its
binary format. As such, once it has been used to construct the binary
form, it can be safely discarded without loss of information.
This pr ensures that the dxil prepare pass will depend and preserve on
the root signature analysis so that it runs before the metadata is
removed.
- Update `DXILPrepare.cpp` to preserve and depend on
`RootSignatureAnalysisWrapper`
- Update test to demonstrate order is correct
- Provide test-case to demonstrate the metadata is removed
Resolves https://github.com/llvm/llvm-project/issues/145437.
----------
Co-authored-by: Justin Bogner <mail@justinbogner.com>
Running the `vector-combine` pass on this test now produces a single
shuffle on a loaded `<1 x float>` instead of an insert into a `<2 x
float>` followed by a shuffle.
This test change matches changes in other tests in PR #144690, which
introduced the optimization.
In #144957 the backend was updated to expect a version in the metadata,
but since the frontend wasn't updated this breaks compilation. This is a
somewhat temporary fix to that until #144813 lands.
fixes#144608
- there is a getPointerOperandIndex function so we don't need to iterate
the operands trying to find the pointer. This resulted in a small
cleanup to visitStoreInst and visitLoadInst.
- The meat of this change was in visitGetElementPtrInst to account for
allocas and not bail when we don't find a global.
Implements descriptor table parsing from root signature metadata. This
is required to support root signatures in hlsl.
Closes: #[126640](https://github.com/llvm/llvm-project/issues/126640)
---------
Co-authored-by: joaosaffran <joao.saffran@microsoft.com>
Fixes#141136
- Implement `visitExtractElementInst` and `visitInsertElementInst` in
`DXILDataScalarizerVisitor` to scalarize `extractelement` and
`insertelement` instructions whose index operand is not a `ConstantInt`
by converting the vector to an array and then loading from the array
- Rename the `replaceVectorWithArray` helper function to
`equivalentArrayTypeFromVector`, relocate the function toward the top of
the file, and remove the unused `Ctx` parameter
Updates the Root Signature metadata parser to extract version
information. This requirement was added after the initial parser
implementation.
---------
Co-authored-by: joaosaffran <joao.saffran@microsoft.com>
Implements
https://github.com/llvm/wg-hlsl/blob/main/proposals/0026-symbol-visibility.md.
The change is to stop using the `hlsl.export` attribute. Instead,
symbols with "program linkage" in HLSL will have export linkage with
default visibility, and symbols with "external linkage" in HLSL will
have export linkage with hidden visibility.
fixes#142836
We added a function called `collectIndicesAndDimsFromGEP` which builds
the Indicies and Dims up for the recursive case and the base case.
really to solve #142836 we didn't need to add it to the recursive case.
The recursive cases exists for gep chains which are ussually two
indicies per gep ie ptr index and array index. adding
collectIndicesAndDimsFromGEP to the recursive cases means we can now do
some mixed mode indexing say we get a case where its not the ussual 2
indicies but instead 3 we can now treat those last two indicies as part
of the computation for the flat array index.
This change relands https://github.com/llvm/llvm-project/pull/142853
It fixes the circular reference issue we were seeing in GEPs
ex `%.flat = getelementptr inbounds [16 x i32], ptr %.flat, i32 0, i32
15`
This PR addresses a specific edge case when deciding whether or not to
produce a bitcast instruction.
Specifically, when the given instruction is a global array, the element
type of the array wasn't correctly compared to the return type. In this
specific case, if the types are equal, a bitcast shouldn't be created,
but it was.
This PR checks to see if the element type of the array is the same as
the return type, and if it is, it doesn't create a bitcast instruction.
Fixes https://github.com/llvm/llvm-project/issues/139013
partially fixes#142836
- Update DXILFlattenArrays.cpp GEPs to use two indicies since they are
array GEPs
- Update flatten test cases
- This change reduces dxv bitcast validation errors by 364 (Total now is
1070x)
- This change reduces dxv out of bounds validation errors by 124 (Total
is now 24)
- We are also able to successfully compile 4 more shaders
fixes#140415
The i8 legalization code in DXILLegalizePass's `fixI8UseChain` needs to
be updated to check for i8 geps.
It seems like there are i8 GEPs being left around after we remove all
the other i8 instructions and this is causing problem on validation.
Since this is cleaning up a missed GEP The approach is to assume the
getPointerOperand is to an alloca we further will check if this is an
array alloca then do some byte offset arithmetic to figure out the
memory index to use. Finally we will emit the new gep and cleanup the
old one.
Finally needed to update upcastI8AllocasAndUses to account for loads off
of GEPs instead of just loads from the alloca.
- adds parsing from metadata into dxcontainer binary
- adds validations as described in the spec
- adds testing scenarios
closes: [#126638](https://github.com/llvm/llvm-project/issues/126638)
---------
Co-authored-by: joaosaffran <joao.saffran@microsoft.com>
Adds reporting of overlapping binding errors to `DXILPostOptimizationValidation` pass. Only runs when `DXILResourceBindingAnalysis` detects that there is a resource binding that overlaps while it is building up a map of available register spaces.
Fixes#110723
Since the `DXILResourceImplicitBinding` pass has been moved after `DXILForwardHandleAccesses` pass the forward-handle pass needs to handle `llvm.dx.resource.handlefromimplicitbinding` calls as well.
typedBufferLoad of double/double2 is expanded to a typedBufferLoad of a
<2 x i32>/<4 x i32> and asdouble
typedBufferStore of a double/double2 is expanded to a splitdouble and a
typedBufferStore of a <2 x i32>/<4 x i32>
Add tests showing result of intrinsic expansion for typedBufferLoad and
typedBufferStore
Add tests showing dxil op lowering can handle typedBufferLoad and
typedBufferStore where the target type doesn't match the typedBufferLoad
and typedBufferStore type
Closes#104423
Update resource type names for globals variables that we generate in `DXILTranslateMetadata` pass to include element type. This change prevents duplicate types for identical resources and brings the DXIL metadata names it closer to what DXC generates.
Moving `DXILResourceImplicitBinding` pass and the associated `DXILResourceBindingAnalysis` lower in the llc pipeline to just before the DXIL Resource Analysis, which is where its results are first needed, and adjusting the set of analyses it preserves.
The reason for this change is that I will soon be adding `DXILResourceBindingAnalysis` dependency to `DXILPostOptimizationValidation` pass and bringing this closer to where it is needed avoid unnecessary churn to preserved analysis setting in preceding passes.
Adds resource name argument to `llvm.dx.handlefrombinding` and `llvm.dx.handlefromimplicitbinding` intrinsics.
SPIR-V currently does not seem to need the resource names so this change only affects DirectX binding intrinsics.
Part 2/4 of https://github.com/llvm/llvm-project/issues/105059
- DXILDataScalarization should not just be limited to global data
- Add a scalarization for alloca
- Add ReversePostOrderTraversal of functions and iterate over basic
blocks and run DataScalarizerVisitor.
- fixes#140143
Adds checks for resource globals that were created for DXIL metadata.
The names of the globals and the names of the types will be changing
soon. Adding these to the baseline will make it easier to see what is
changing.
Fixes#137188
This PR legalizes memcpy for DXIL in cases where:
- the src and dst arguments are from Alloca or a GlobalVariable,
- the src and dst are pointers to an ArrayType,
- the array element types of src and dst must be equivalent, and
- the len param is a ConstantInt
These assumptions simplify the legalization and, with the addition of
#138991, covers the currently-known cases of memcpy that appear when
compiling DML shaders.
This PR may be unnecessary if #138788 determines that memset and memcpy
can be eliminated entirely.
---------
Co-authored-by: Finn Plummer <canadienfinn@gmail.com>
Co-authored-by: Greg Roth <grroth@microsoft.com>
There were some issues with these ops:
- The overload wasn't being specified (`dx.op.dot4AddPacked` vs
`dx.op.dot4AddPacked.i32`)
- The versioning wasn't correct (These ops were added in SM 6.4)
- The argument order was off - while the HLSL function has the
accumulator as the last argument, the DXIL op lists it first.
This fixes the DXIL.td definition and adjusts the LLVM DX and SPIRV
intrinsics to match the argument order in DXIL rather than the argument
order in HLSL.
Fixes#139018
Fixes#139024 and #139954
- Refactor DXILShaderFlags to compute the flags that apply to a whole
module before computing flags that apply individually to each function
- Make DXILResourceMap const, since it is not modified in
DXILShaderFlags
- Per-function shader flag analysis now initially starts with the set of
flags that apply to the whole module instead of starting from no flags.
This change fixes the above linked issues
- Fix shader flag tests affected by the above change
Fixes#138997 and does refactoring for low-precision-related flags.
The shader feature flags MinimumPrecision and NativeLowPrecision were
not being set, leading to validation errors.
This PR sets these shader feature flags [as in
DXC](377c4ca6d8/lib/DXIL/DxilShaderFlags.cpp (L58-L63))
and adds tests for them.
This PR also performs some refactoring of low-precision-related flags to
make it less confusing.
- The `UseNativeLowPrecision` DXIL module flag has been renamed to
`NativeLowPrecisionMode` to imply that it is setting some execution
state which the module should be interpreted with
- The LLVM module flag `dx.nativelowprec` is now read only once and sets
a bool to be used by `updateFunctionFlags()` and for setting the DXIL
module flag `NativeLowPrecisionMode`
- The `MinimumPrecision`, `NativeLowPrecision`, and
`LowPrecisionPresent` shader feature flags are all set together under
`updateFunctionFlags()`
- Moved the logic for setting DXIL module flags `NativeLowPrecisionMode`
and `ResMayNotAlias` out of the per-function loop and placed it
alongside the logic for setting other DXIL module flags
(`DisableOptimizations`, `Max64UAVs`, and `UAVsAtEveryStage` flags)
---------
Co-authored-by: Justin Bogner <mail@justinbogner.com>
Move dxil resource access legacy pass before intrinsic expansion legacy
pass so TypedBuffer Loads and Stores will be created before intrinsic
expansion.
This is to facilitate #104423
The `DXILResourceImplicitBinding` pass uses the results of
`DXILResourceBindingAnalysis` to assigns register slots to resources
that do not have explicit binding. It replaces all
`llvm.dx.resource.handlefromimplicitbinding` calls with
`llvm.dx.resource.handlefrombinding` using the newly assigned binding.
If a binding cannot be found for a resource, the pass will raise a
diagnostic error. Currently this diagnostic message does not include the
resource name, which will be addressed in a separate task (#137868).
Part 2/2 of #136786Closes#136786
Fixes#137209
This PR:
- Adds a case to `expandIntrinsic()` in `DXILIntrinsicExpansion.cpp` to
expand the `Intrinsic::is_fpclass` in the case of
`FPClassTest::fcNegZero`
- Defines the `IsNaN`, `IsFinite`, `IsNormal` DXIL ops in `DXIL.td`
- Adds a case to `lowerIntrinsics()` in `DXILOpLowering.cpp` to handle
the lowering of `Intrinsic::is_fpclass` to the DXIL ops `IsNaN`,
`IsInf`, `IsFinite`, `IsNormal` when the FPClassTest is `fcNan`,
`fcInf`, `fcFinite`, and `fcNormal` respectively
- Creates a test `llvm/test/CodeGen/DirectX/is_fpclass.ll` to exercise
the intrinsic expansion and DXIL op lowering of `Intrinsic::is_fpclass`
~~A separate PR will be made to remove the now-redundant `dx_isinf`
intrinsic to address #87777.~~
A proper implementation for the lowering of the `llvm.is.fpclass`
intrinsic to handle all possible combinations of FPClassTest can be
implemented in a separate PR. This PR's implementation focuses primarily
on addressing the current use-cases for DirectML and HLSL intrinsics.
This moves the responsibility for cleaning up dead intrinsics from
DXILFinalizeLinkage to DXILOpLowering, and moves DXILFinalizeLinkage
back to it's pre-#136244 place in the pipeline. Doing this avoids issues
with DXIL passes running on obviously dead code, and makes it more clear
what DXILFinalizeLinkage is really doing.
This also helps with the story for #134260, as cleaning up dead
intrinsics doesn't make sense if this becomes a more generic pass.
Note that test/CodeGen/DirectX/remove-dead-intriniscs.ll already covers
most of the testing here. It'd be nice to have something that catches
the regression from changing the pass ordering but I couldn't come up
with anything that wouldn't be incredibly fragile.
Fixes#138180.
fixes#136243
This change converts memset into a series of geps and stores It is
intentionally limited to memsets of fixed size It also converts the byte
stores to type stores.
DXIL does not support i8 plus this reduces the total number of gep and
store instructions.
This change also moves DXILFinalizeLinkage to run after Legalization to
clean up any dead intrinsic definitions.
fixes#137202
investingating i8 allocas I came to find some missing instructions from
out i8 legalization around load, store, and select.
Added those three.
To do i8 allocas right though we needed to walk the uses and find the
casts.
After finding the casts I chose to pick the smallest cast as the cast to
transform to. That would then let me preserve the larger casts that come
later
Fixes#112272
In addition to the implementation of the UAVsAtEveryStage shader flag
analysis, several unrelated tests have had the `dx.valver` module
metadata defined to avoid setting the UAVsAtEveryStage shader flag in
them.
Example:
```
!dx.valver = !{!0}
!0 = !{i32 1, i32 8}
```
---------
Co-authored-by: Justin Bogner <mail@justinbogner.com>
This PR revises the descriptions of DXIL module flags.
Descriptions such as `D3D11_1_SB_GLOBAL_FLAG_SKIP_OPTIMIZATION` are
referring to Global Flags in DXBC.
DXBC is not a supported backend target, so references to DXBC should not
be present.
There is also confusion with regards to the description of the
`LowPrecisionPresent` DXIL module flag, which currently reads
`D3D11_1_SB_GLOBAL_FLAG_ENABLE_MINIMUM_PRECISION` and implies the use of
minimum-precision to handle 16-bit types.
However this is not true, because both the flags `LowPrecisionPresent`
and `UseNativeLowPrecision` can simultaneously be set in the same DXIL
module, and minimum precision mode is mutually exclusive with native low
precision.
This PR revises the description of the `LowPrecisionPresent` flag to
accurately describe what it represents.
This PR introduces a Metadata Node Kind allowlist. The purpose is to
prevent newer Metadata Node Kinds to be used and inserted into the
outputted DXIL module. Only the metadata kinds that are accepted in the
DXIL Validator are on the allowlist. The Github DXC validator doesn't
support these newer Metadata Node Kinds, so we need to filter them out.
We introduce this restrictive allowlist into LLVM and strip all metadata
that isn't found in the list.
The accompanying test would add the `llvm.loop.mustprogress` metadata
node kind, but thanks to the allowlist, filters it out, and so the
whitelist is proven to work.
The test also has two separate metadata kinds that are on the allowlist,
and remain after the DXIL Prepare pass.