89 Commits

Author SHA1 Message Date
Steven Perron
d8295e2eec
[SPIRV][HLSL] Handle arrays of resources (#111564)
This commit adds the ability to get a particular resource from an array
of resources using the handle_fromBinding intrinsic.

The main changes are:

1. Create an array when generating the type.
2. Add capabilities from

[SPV_EXT_descriptor_indexing](https://htmlpreview.github.io/?https://github.com/KhronosGroup/SPIRV-Registry/blob/main/extensions/EXT/SPV_EXT_descriptor_indexing.html).

We are still missing the ability to declare a runtime array. That will
be done in a follow up PR.
2024-10-30 15:01:02 -04:00
Adam Yang
3a1228a543
[SPIRV] Add GroupMemoryBarrierWithGroupSync intrinsic (#111888)
partially fixes #70103

### Changes
* Added int_spv_group_memory_barrier_with_group_sync intrinsic in
IntrinsicsSPIRV.td
* Added lowering for int_spv_group_memory_barrier_with_group_sync in
SPIRVInstructionSelector.cpp
* Added SPIRV backend test case

### Related PRs
* [[clang][HLSL] Add GroupMemoryBarrierWithGroupSync intrinsic
#111883](https://github.com/llvm/llvm-project/pull/111883)
* [[DXIL] Add GroupMemoryBarrierWithGroupSync intrinsic
#111884](https://github.com/llvm/llvm-project/pull/111884)
2024-10-29 12:40:01 -07:00
Finn Plummer
6d13cc9411
[HLSL] Implement WaveReadLaneAt intrinsic (#111010)
- create a clang built-in in Builtins.td
    - add semantic checking in SemaHLSL.cpp
    - link the WaveReadLaneAt api in hlsl_intrinsics.h
    - add lowering to spirv backend op GroupNonUniformShuffle
      with Scope = 2 (Group) in SPIRVInstructionSelector.cpp
    - add WaveReadLaneAt intrinsic to IntrinsicsDirectX.td and mapping
      to DXIL.td

    - add tests for HLSL intrinsic lowering to spirv intrinsic in
      WaveReadLaneAt.hlsl
    - add tests for sema checks in WaveReadLaneAt-errors.hlsl
    - add spir-v backend tests in WaveReadLaneAt.ll
    - add test to show scalar dxil lowering functionality

    - note that this doesn't include support for the scalarizer to
      handle WaveReadLaneAt will be added in a future pr

This is the first part #70104
2024-10-15 18:49:40 -07:00
Finn Plummer
2647505027
[HLSL] Implement the degrees intrinsic (#111209)
- add degrees builtin
    - link degrees api in hlsl_intrinsics.h
    - add degrees intrinsic to IntrinsicsDirectX.td
    - add degrees intrinsic to IntrinsicsSPIRV.td
- add lowering from clang builtin to dx/spv intrinsics in CGBuiltin.cpp
    - add semantic checks to SemaHLSL.cpp
- add expansion of directx intrinsic to llvm fmul for DirectX in
DXILIntrinsicExpansion.cpp
    - add mapping to spir-v intrinsic in SPIRVInstructionSelector.cpp

    - add test coverage:
- degrees.hlsl -> check hlsl lowering to dx/spv degrees intrinsics
- degrees-errors.hlsl/half-float-only-errors -> check semantic warnings
- hlsl-intrinsics/degrees.ll -> check lowering of spir-v degrees
intrinsic to SPIR-V backend
- DirectX/degrees.ll -> check expansion and scalarization of directx
degrees intrinsic to fmul
      
Resolves #99104
2024-10-10 16:34:26 -07:00
Steven Perron
5af7ae501a
[SPIRV] Implement handle_fromBinding intrinsic. (#111052)
Implement the intrinsic `llvm.spv.handle.fromBinding`, which returns the
handle for a global resource. This involves creating a global variable
that matches the return-type, set, and binding in the call, and
returning the handle to that resource.

This commit implements the scalar version. It does not handle arrays of
resources yet. It also does not handle storage buffers yet. We do not
have the type for the storage buffers designed yet.

Part of #81036
2024-10-08 12:31:23 -04:00
Justin Bogner
b2c615fc79 Reapply "[SPIRV] Add radians intrinsic"
I had too many tabs open and reverted #110800 by mistake, it was
supposed to be #110616.

This reverts commit dec6fe3de0f6475ea83391e5b0b4036cf56db35b.
2024-10-07 09:24:34 -07:00
Justin Bogner
dec6fe3de0
Revert "[SPIRV] Add radians intrinsic" (#111398)
Reverts llvm/llvm-project#110800

`llvm\test\CodeGen\DirectX\radians.ll` is failing after this change.
@adam-yang please send a new PR with the issue resolved once you've had
time to investigate.
2024-10-07 09:23:38 -07:00
Adam Yang
c0f8889774
[SPIRV] Add radians intrinsic (#110800)
partially fixes #99151

### Changes
* Added int_spv_radians intrinsic in IntrinsicsSPIRV.td
* Added lowering for int_spv_radians in SPIRVInstructionSelector.cpp
* Added DXIL backend test case

### Related PRs
* [[clang][HLSL] Add radians intrinsic
#110802](https://github.com/llvm/llvm-project/pull/110802)
* [[DXIL] Add radians intrinsic
#110616](https://github.com/llvm/llvm-project/pull/110616)
2024-10-04 14:09:50 -04:00
Joshua Batista
c098435eaa
Add cross builtins and cross HLSL function to DirectX and SPIR-V backend (#109180)
This PR adds the step intrinsic and an HLSL function that uses it.
The SPIRV backend is also implemented.

Used https://github.com/llvm/llvm-project/pull/106471 as a reference.
Fixes https://github.com/llvm/llvm-project/issues/99095
2024-10-03 10:24:09 -07:00
Farzon Lotfi
add6b2f35f
[NFC][SPIRV] Fix for selectExtInst to be able to process intrinsics (#110864)
`selectExtInst` tries to add the intrinsic to the SPIRV GL extension
instruction.
`MO_IntrinsicID` is always the first operand when we come from
`selectIntrinsic`.
For all those cases `selectExtInst` needs to know to start at index 2.
2024-10-02 15:34:04 -04:00
Vyacheslav Levytskyy
0e3476605f
[SPIR-V] Implement support of the SPV_EXT_arithmetic_fence SPIRV extension (#110500)
This PR implements support of the SPV_EXT_arithmetic_fence SPIRV
extension:
https://htmlpreview.github.io/?https://github.com/KhronosGroup/SPIRV-Registry/blob/main/extensions/EXT/SPV_EXT_arithmetic_fence.html.
2024-10-01 10:48:25 +02:00
Vyacheslav Levytskyy
c538d5c8b2
[SPIR-V] Discard some llvm intrinsics which we do not expect to actually represent code after lowering (#110233)
There are llvm intrinsics which we do not expect to actually represent
code after lowering or which are not implemented yet but can be found in
a customer's LLVM IR input. We do not want translation to crash when
these llvm intrinsics are found, and this PR fixes the issue with
translation crash for some known cases, aligned with Khronos Translator.
2024-10-01 10:48:10 +02:00
Vyacheslav Levytskyy
3e79c7fec0
[SPIR-V] Implement OpSpecConstantOp with ptr-cast operation (#109979)
This PR reworks implementation of OpSpecConstantOp with ptr-cast
operation (PtrCastToGeneric, GenericCastToPtr). Previous implementation
didn't take into account a lot of use cases, including multiple
inclusion of pointers, reference to a pointer from OpName, etc. A
reproducer is attached as a new test case.

This PR also fixes wrong type inference for IR patterns which generate
new virtual registers without SPIRV type. Previous implementation
assumed always that result has the same address space as a source that
is not the fact, and, for example, led to impossibility to emit a
ptr-cast operation in the reproducer, because wrong type inference
rendered source and destination with the same address space, eliminating
translation of G_ADDRSPACE_CAST.
2024-10-01 10:47:15 +02:00
Tex Riddell
139688a699
[SPIRV] Add atan2 function lowering (p2) (#110037)
This change is part of this proposal:
https://discourse.llvm.org/t/rfc-all-the-math-intrinsics/78294

- Add generic opcode for atan2
- Add SPIRV lowering for atan2

Part 2 for Implement the atan2 HLSL Function #70096.
2024-09-26 15:00:59 -07:00
Vyacheslav Levytskyy
a059b29930
[SPIR-V] Allow intrinsics with aggregate return type to reach GlobalISel (#108893)
Two main goals of this PR are:
* to support "Arithmetic with Overflow" intrinsics, including the
special case when those intrinsics are being generated by the
CodeGenPrepare pass during translations with optimization;
* to redirect intrinsics with aggregate return type to be lowered via
GlobalISel operations instead of SPIRV-specific unfolding/lowering (see
https://github.com/llvm/llvm-project/pull/95012).

There is a new test case
`llvm/test/CodeGen/SPIRV/passes/translate-aggregate-uaddo.ll` that
describes and checks the general logics of the translation.

This PR continues a series of PRs aimed to identify and fix flaws in
code emission, to improve pass rates for the mode with expensive checks
set on (see https://github.com/llvm/llvm-project/pull/101732,
https://github.com/llvm/llvm-project/pull/104104,
https://github.com/llvm/llvm-project/pull/106966), having in mind the
ultimate goal of proceeding towards the non-experimental status of
SPIR-V Backend.

The reproducers are:

1) consider `llc -O3 -mtriple=spirv64-unknown-unknown ...` with:

```
define spir_func i32 @foo(i32 %a, ptr addrspace(4) %p) {
entry:
  br label %l1

l1:
  %e = phi i32 [ %a, %entry ], [ %i, %body ]
  %i = add nsw i32 %e, 1
  %fl = icmp eq i32 %i, 0
  br i1 %fl, label %exit, label %body

body:
  store i8 42, ptr addrspace(4) %p
  br label %l1

exit:
  ret i32 %i
}
```

2) consider `llc -O0 -mtriple=spirv64-unknown-unknown ...` with:

```
define spir_func i32 @foo(i32 %a, ptr addrspace(4) %p) {
entry:
  br label %l1

l1:                                               ; preds = %body, %entry
  %e = phi i32 [ %a, %entry ], [ %math, %body ]
  %0 = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %e, i32 1)
  %math = extractvalue { i32, i1 } %0, 0
  %ov = extractvalue { i32, i1 } %0, 1
  br i1 %ov, label %exit, label %body

body:                                             ; preds = %l1
  store i8 42, ptr addrspace(4) %p, align 1
  br label %l1

exit:                                             ; preds = %l1
  ret i32 %math
}
```
2024-09-26 10:57:02 +02:00
Alex Voicu
3cfd0c0d36
[SPIRV][RFC] Rework / extend support for memory scopes (#106429)
This change adds support for correctly lowering the `__scoped` Clang
builtins, and corresponding scoped LLVM instructions. These were
previously unconditionally lowered to Device scope, which is possibly incorrect. 
Furthermore, the default / implicit scope is changed from Device (an 
OpenCL assumption) to AllSvmDevices (aka System), since the SPIR-V BE is not 
OpenCL specific / can ingest IR coming from other language front-ends. OpenCL 
defaulting to Device scope is now reflected in the front-end handling of atomic 
ops, which seems preferable.
2024-09-25 00:44:57 +01:00
Nathan Gauër
1ed65febd9
[SPIR-V] Add SPIR-V structurizer (#107408)
This commit adds an initial SPIR-V structurizer.
It leverages the previously merged passes, and the convergence region
analysis to determine the correct merge and continue blocks for SPIR-V.

The first part does a branch cleanup (simplifying switches, and
legalizing them), then merge instructions are added to cycles,
convergent and later divergent blocks.
Then comes the important part: splitting critical edges, and making sure
the divergent construct boundaries don't cross.

- we split blocks with multiple headers into 2 blocks.
- we split blocks that are a merge blocks for 2 or more constructs:
SPIR-V spec disallow a merge block to be shared by 2
loop/switch/condition construct.
- we split merge & continue blocks: SPIR-V spec disallow a basic block
to be both a continue block, and a merge block.
- we remove superfluous headers: when a header doesn't bring more info
than the parent on the divergence state, it must be removed.

This PR leverages the merged SPIR-V simulator for testing, as long as
spirv-val. For now, most DXC structurization tests are passing. The
unsupported ones are either caused by unsupported features like switches
on boolean types, or switches in region exits, because the MergeExit
pass doesn't support those yet (there is a FIXME).

This PR is quite large, and the addition not trivial, so I tried to keep
it simple. E.G: as soon as the CFG changes, I recompute the dominator
trees and other structures instead of updating them.

---------

Signed-off-by: Nathan Gauër <brioche@google.com>
2024-09-20 11:36:43 +02:00
Joshua Batista
2d47a0baba
Add step builtins and step HLSL function to DirectX and SPIR-V backend (#106471)
This PR adds the step intrinsic and an HLSL function that uses it.
The SPIRV backend is also implemented.

Used https://github.com/llvm/llvm-project/pull/102683 as a reference.
Fixes https://github.com/llvm/llvm-project/issues/99157
2024-09-12 10:26:38 -07:00
Vyacheslav Levytskyy
ed22029eea
[SPIR-V] Address the case when optimization uses GEP operator and GenCode creates G_PTR_ADD to convey the semantics (#107880)
When running SPIR-V Backend with optimization levels higher than 0, we
observe GEP Operator's as a new factor, massively used to convey the
semantics of the original LLVM IR. Previously, an issue related to GEP
Operator was mentioned and fixed on the consumer side of toolchains
(see, for example, Khronos Trandslator Issue
https://github.com/KhronosGroup/SPIRV-LLVM-Translator/issues/2486 and PR
https://github.com/KhronosGroup/SPIRV-LLVM-Translator/pull/2487).
However, there is a case when GenCode creates G_PTR_ADD to convey the
original semantics under optimization levels higher than 0 where it's
SPIR-V Backend that fails to translate source LLVM IR correctly.

Consider the following reproducer:

```
%struct = type { i32, [257 x i8], [257 x i8], [129 x i8], i32, i64, i64, i64, i64, i64, i64 }
@Mem = linkonce_odr dso_local addrspace(1) global %struct zeroinitializer, align 8

define weak dso_local spir_func void @__devicelib_assert_fail(ptr addrspace(4) noundef %expr, i32 noundef %line, i1 %fl) {
entry:
  %cmp = icmp eq i32 %line, 0
  br i1 %cmp, label %lbl, label %exit

lbl:
  store i32 %line, ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) @Mem, i64 648), align 8
  br i1 %fl, label %lbl, label %exit

exit:
  ret void
}
```

converted to the following machine instructions by SPIR-V Backend:

```
  %4:type(s64) = OpTypeInt 32, 0
  %22:type(s64) = OpTypePointer 5, %4:type(s64)
  %2:type(s64) = OpTypeInt 8, 0
  %28:type(s64) = OpTypePointer 5, %2:type(s64)

  %10:pid(p1) = G_GLOBAL_VALUE @Mem

  %36:type(s64) = OpTypeStruct %4:type(s64), %32:type(s64), %32:type(s64), %34:type(s64), %4:type(s64), %35:type(s64), %35:type(s64), %35:type(s64), %35:type(s64), %35:type(s64), %35:type(s64)
  %37:iid(s32) = G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.spv.const.composite)

  %8:iid(s32) = ASSIGN_TYPE %37:iid(s32), %36:type(s64)
  G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.spv.init.global), %10:pid(p1), %8:iid(s32)

  %29:pid(p1) = nuw G_PTR_ADD %10:pid, %16:iid(s64)
  %15:pid(p1) = nuw ASSIGN_TYPE %29:pid(p1), %28:type(s64)

  %27:pid(p2) = G_BITCAST %15:pid(p1)
  %17:pid(p2) = ASSIGN_TYPE %27:pid(p2), %22:type(s64)
  G_STORE %1:iid(s32), %17:pid(p2) :: (store (s32) into %ir.3, align 8, addrspace 1)
```

On the next stage of instruction selection this `G_PTR_ADD`-related
pattern would be interpreted as an initialization of a global variable
and converted to an invalid constant GEP pattern that, in its turn,
would fail to be verified by LLVM during back translation from SPIR-V to
LLVM IR.

This PR introduces a fix for the problem by adding one more case of
`G_PTR_ADD` translation, when we use a non-const GEP to convey the
meaning. The reproducer is attached as a new test case.
2024-09-11 14:18:14 +02:00
Tim Gymnich
a9a5a18a0e
[SPIRV] Add sign intrinsic part 1 (#101987)
partially fixes #70078

### Changes
- Added `int_spv_sign` intrinsic in `IntrinsicsSPIRV.td`
- Added lowering and map to `int_spv_sign in
`SPIRVInstructionSelector.cpp`
- Added SPIR-V backend test case in
`llvm/test/CodeGen/SPIRV/hlsl-intrinsics/sign.ll`

### Related PRs
- https://github.com/llvm/llvm-project/pull/101988
- https://github.com/llvm/llvm-project/pull/101989
2024-09-09 17:27:27 -04:00
Nathan Gauër
afb6dafc6b
[clang][HLSL] Add WaveIsFirstLane() intrinsic (#103299)
This commits add the WaveIsFirstLane() hlsl intrinsinc. This intrinsic
uses the convergence intrinsincs for the SPIR-V backend. On the DXIL
side, I'm not sure what the strategy is for convergence, so I
implemented that like in DXC: a normal builtin function.

Signed-off-by: Nathan Gauër <brioche@google.com>
2024-09-04 11:27:03 +02:00
Greg Roth
319c7a42ba
[HLSL][SPIRV]Add SPIRV generation for HLSL dot (#104656)
This adds the SPIRV fdot, sdot, and udot intrinsics and allows them to
be created at codegen depending on the target architecture. This
required moving some of the DXIL-specific choices to DXIL instruction
expansion out of codegen and providing it with at a more generic fdot
intrinsic as well.

Removed some stale comments that gave the obsolete impression that type
conversions should be expected to match overloads.

The SPIRV intrinsic handling involves generating multiply and add
operations for integers and the existing OpDot operation for floating
point.

New tests for generating SPIRV float and integer dot intrinsics are
added as well as expanding HLSL tests to include SPIRV generation

Used new dot product intrinsic generation to implement normalize() in SPIRV

Incidentally changed existing dot intrinsic definitions to use
DefaultAttrsIntrinsic to match the newly added inrinsics

Fixes #88056
2024-08-22 11:13:52 -07:00
Vyacheslav Levytskyy
67d3ef74b3
[SPIR-V] Rework usage of virtual registers' types and classes (#104104)
This PR continues https://github.com/llvm/llvm-project/pull/101732
changes in virtual register processing aimed to improve correctness of
emitted MIR between passes from the perspective of MachineVerifier.
Namely, the following changes are introduced:
* register classes (lib/Target/SPIRV/SPIRVRegisterInfo.td) and
instruction patterns (lib/Target/SPIRV/SPIRVInstrInfo.td) are corrected
and simplified (by removing unnecessary sophisticated options) -- e.g.,
this PR gets rid of duplicating 32/64 bits patterns, removes ANYID
register class and simplifies definition of the rest of register
classes,
* hardcoded LLT scalar types in passes before instruction selection are
corrected -- the goal is to have correct bit width before instruction
selection, and use 64 bits registers for pattern matching in the
instruction selection pass; 32-bit registers remain where they are
described in such terms by SPIR-V specification (like, for example,
creation of virtual registers for scope/mem semantics operands),
* rework virtual register type/class assignment for calls/builtins
lowering,
* a series of minor changes to fix validity of emitted code between
passes:
  - ensure that that bitcast changes the type,
  - fix the pattern for instruction selection for OpExtInst,
  - simplify inline asm operands usage,
  - account for arbitrary integer sizes / update legalizer rules;
* add '-verify-machineinstrs' to existed test cases.

See also https://github.com/llvm/llvm-project/issues/88129 that this PR
may resolve.

This PR fixes a great number of issues reported by MachineVerifier and,
as a result, reduces a number of failed test cases for the mode with
expensive checks set on from ~200 to ~57.
2024-08-22 09:40:27 +02:00
S. Bharadwaj Yadavalli
6a38e19c92
[HLSL] Implement support for HLSL intrinsic - saturate (#104619)
Implement support for HLSL intrinsic saturate.
Implement DXIL codegen for the intrinsic saturate by lowering it to DXIL
Op dx.saturate.
Implement SPIRV codegen by transforming saturate(x) to clamp(x, 0.0f,
1.0f).

Add tests for DXIL and SPIRV CodeGen.
2024-08-20 12:46:33 -04:00
Vyacheslav Levytskyy
2fc7a72733
[SPIR-V] Add implementation of the non-const G_BUILD_VECTOR and fix emission of the OpGroupBroadcast instruction (#103050)
This PR addresses a TODO in
lib/Target/SPIRV/SPIRVInstructionSelector.cpp by adding implementation
of the non-const G_BUILD_VECTOR, and fix emission of the
OpGroupBroadcast instruction for the case when the `..._group_broadcast`
builtin has more than one `local_id` argument and `OpGroupBroadcast`
requires a newly constructed vector with 2 or 3 components instead of
originally passed series of `local_id` arguments.

This PR may resolve https://github.com/llvm/llvm-project/issues/97310 if
the reason for the reported fail is an incorrectly generated
OpGroupBroadcast instruction that was definitely a case.

Existing test is hardened and a new test is added to cover this special
case of the OpGroupBroadcast instruction emission.
2024-08-14 11:42:48 +02:00
Joshua Batista
1b2d11de93
Add normalize builtins and normalize HLSL function to DirectX and SPIR-V backend (#102683)
This PR adds the normalize intrinsic and an HLSL function that uses it.
The SPIRV backend is also implemented.

Used https://github.com/llvm/llvm-project/pull/101256 as a reference,
along with https://github.com/llvm/llvm-project/pull/102243
Fixes https://github.com/llvm/llvm-project/issues/99139
2024-08-13 15:15:19 -07:00
Joshua Batista
e4e938f3cd
[HLSL] Lower Length to SPIR-V backend (#102243)
This PR finishes #99134 by lowering the length function to the SPIR-V
backend. A test was added to verify that the generated SPIR-V is
correct.
Fixes #99134
2024-08-12 10:59:07 -07:00
Vyacheslav Levytskyy
f9c98068c8
[SPIR-V] Rework usage of virtual registers' types and classes (#101732)
This PR contains changes in virtual register processing aimed to improve
correctness of emitted MIR between passes from the perspective of
MachineVerifier. This potentially helps to detect previously missed
flaws in code emission and harden the test suite. As a measure of
correctness and usefulness of this PR we may use a mode with expensive
checks set on, and MachineVerifier reports problems in the test suite.

In order to satisfy Machine Verifier requirements to MIR correctness not
only a rework of usage of virtual registers' types and classes is
required, but also corrections into pre-legalizer and instruction
selection logics. Namely, the following changes are introduced:
* scalar virtual registers have proper bit width,
* detect register class by SPIR-V type,
* add a superclass for id virtual register classes,
* fix Tablegen rules used for instruction selection,
* fixes of minor existed issues (missed flag for proper representation
of a null constant for OpenCL vs. HLSL, wrong usage of integer virtual
registers as a synonym of any non-type virtual register).
2024-08-12 15:49:43 +02:00
Vyacheslav Levytskyy
281f59fdf9
[SPIR-V] Emit valid Lifestart/Lifestop instructions (#98475)
This PR fixes emission of valid OpLifestart/OpLifestop instructions.
According to
https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#OpLifetimeStart:
"Size must be 0 if Pointer is a pointer to a non-void type or the
Addresses
[capability](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#Capability)
is not declared.". The `Size` argument is set the corresponding
intrinsics arguments, so Size is not zero we must ensure that Pointer
has the required type by inserting a bitcast if needed.
2024-08-12 15:49:17 +02:00
Justin Bogner
bb4aeb66ab
[SPIRV] Don't specialize MachineModuleInfo to access the LLVMContext. NFC (#101085)
The MachineModuleInfo reference was removed from the MachineFunction in
#100357, which broke this code. Instead of finding another way to get at
the MMI, just avoid using it - we can get at the LLVMContext from the
MachineFunction itself.
2024-07-29 14:51:04 -07:00
Andrii Levytskyi
c92d9b06d4
[SPIRV][HLSL] Add lowering of frac to SPIR-V (#97111)
Implements frac lowering to SPIR-V.

Closes #88059
2024-07-23 14:03:39 -04:00
Vyacheslav Levytskyy
dbd00a5968
[SPIRV] Improve type inference of operand presented by opaque pointers and aggregate types (#98035)
This PR improves type inference of operand presented by opaque pointers
and aggregate types:
* tries to restore original function return type for aggregate types so
that it's possible to deduce a correct type during emit-intrinsics step
(see llvm/test/CodeGen/SPIRV/SpecConstants/restore-spec-type.ll for the
reproducer of the previously existed issue when spirv-val found a
mismatch between object and ptr types in OpStore due to the incorrect
aggregate types tracing),
* explores untyped pointer operands of store to deduce correct pointee
types,
* creates an extension type to track pointee types from emit-intrinsics
step and further instead of direct and naive usage of TypePointerType
that led previously to crashes due to ban of creation of Value of
TypePointerType type,
* tracks instructions with uncomplete type information and tries to
improve their type info after pass calculated types for all machine
functions (it doesn't traverse a code but rather checks only those
instructions which were tracked as uncompleted),
* address more cases of removing unnecessary bitcasts (see, for example,
changes in test/CodeGen/SPIRV/transcoding/OpGenericCastToPtr.ll where
`CHECK-SPIRV-NEXT` in LIT checks show absence of unneeded bitcasts and
unmangled/mangled versions have proper typing now with equivalent type
info),
* address more cases of well known types or relations between types
within instructions (see, for example, atomic*.ll test cases and
Event-related test cases for improved SPIR-V code generated by the
Backend),
* fix the issue of removing unneeded ptrcast instructions in
pre-legalizer pass that led to creation of new assign-type instructions
with the same argument as source in ptrcast and caused errors in type
inference (the reproducer `complex.ll` test case is added to the PR).
2024-07-11 07:16:29 +02:00
Vyacheslav Levytskyy
0d9172ecac
[SPIR-V] Improve pattern matching and tracking of constant integers (#96615)
This PR fixes the issue
https://github.com/llvm/llvm-project/issues/96614 by improve pattern
matching and tracking of constant integers. The attached test is
successful if it doesn't crash and generate valid SPIR-V code for both
32 and 64 bits targets.
2024-06-26 19:38:51 +02:00
Vyacheslav Levytskyy
f6aa508734
[SPIR-V]: Fix creation of constants of array types in SPIRV Backend (#96514)
This PR fixes https://github.com/llvm/llvm-project/issues/96513.

The way of creation of array type constant was incorrect: instead of
creating [1, 1, 1] or [1, 1, 1, 1, 1, ....] constants, the same [1]
constant was always created, substituting original composite constants.
This in its turn led to a situation when only one of constants might
exist in the code without emitting invalid code, the second constant
would be eventually rewritten to the first constant, because a key to
address both was an array of a single element (like [1]).

This PR fixes the issue and purges from the code unneeded copy/pasted
clone of the function that creates an array constant.
2024-06-25 10:56:56 +02:00
Vyacheslav Levytskyy
b0efde6db0
[SPIR-V]: Improve pattern matching to recognize a composite constant to be a constant (#96286)
This PR is to fix https://github.com/llvm/llvm-project/issues/96285 by:
* improve pattern matching to recognize an aggregate constant to be a
constant
* do not emit Bitcast for an aggregate type
2024-06-24 17:19:08 +02:00
Vyacheslav Levytskyy
57f79371a5
[SPIR-V]: Add SPIR-V extension: SPV_KHR_cooperative_matrix (#96091)
This PR adds SPIR-V extension SPV_KHR_cooperative_matrix that "adds a
new set of types known as "cooperative matrix" types, where the storage
for and computations performed on the matrix are spread across a set of
invocations such as a subgroup" (see
https://github.com/KhronosGroup/SPIRV-Registry/blob/main/extensions/KHR/SPV_KHR_cooperative_matrix.asciidoc).

This PR also fixes https://github.com/llvm/llvm-project/issues/96170, a
new test cases is attached
(llvm/test/CodeGen/SPIRV/transcoding/OpPtrCastToGeneric.ll).
2024-06-24 09:57:27 +02:00
Farzon Lotfi
2ae6889d3f
[SPIRV] Add trig function lowering (#95973)
This change is part of this proposal:
https://discourse.llvm.org/t/rfc-all-the-math-intrinsics/78294

This is part 2 of 4 PRs. It sets the ground work for adding the
intrinsics.

Add SPIRV  Lower for `acos`, `asin`, `atan`, `cosh`, `sinh`, and `tanh`
https://github.com/llvm/llvm-project/issues/70079
https://github.com/llvm/llvm-project/issues/70080
https://github.com/llvm/llvm-project/issues/70081
https://github.com/llvm/llvm-project/issues/70083
https://github.com/llvm/llvm-project/issues/70084
https://github.com/llvm/llvm-project/issues/95966


There isn't any aarch64 change in this pr, but when you add a target
opcode it is visible in there validaiton tests.
2024-06-20 10:34:23 -04:00
Helena Kotas
35a2b60973
[SPIRV][HLSL] Add lowering of rsqrt to SPIRV (#95849)
Add lowering of `rsqrt` to SPIRV.

Fixes #88949
2024-06-18 10:35:38 -07:00
Vyacheslav Levytskyy
9a737109a0
[SPIR-V] Improve type inference, addrspacecast and dependencies between SPIR-V entities and required capability/extensions (#94626)
This PR continues https://github.com/llvm/llvm-project/pull/94467 and
contains fixes in emission of type intrinsics, constant recording and
corresponding test cases:
* type-deduce-global-dup.ll -- fix of integer constant emission on
32-bit platforms and correct type deduction for globals
* type-deduce-simple-for.ll -- fix of GEP translation (there was an
issue previously that led to incorrect translation/broken logic of
for-range implementation)

This PR also:
* fixes a cast between identical storage classes and updates the test
case to include validation run by spirv-val,
* ensures that Bitcast for pointers satisfies the requirement that the
address spaces must match and adds the corresponding test case,
* improve encode in Tablegen and decode in code of dependencies between
SPIR-V entities and required capability/extensions,
* prevent emission of identical OpTypePointer instructions.
2024-06-07 21:12:33 +02:00
Vyacheslav Levytskyy
cf9a5a162b
[SPIR-V] Support saturation arithmetic intrinsics in SPIR-V Backend (#91722)
This PR is to support saturation arithmetic intrinsics in SPIR-V
Backend.
2024-05-14 09:22:37 +02:00
Farzon Lotfi
3e82442ff7
[SPIRV] Add tan intrinsic part 3 (#90278)
This change is an implementation of #87367's investigation on supporting
IEEE math operations as intrinsics.
Which was discussed in this RFC:
https://discourse.llvm.org/t/rfc-all-the-math-intrinsics/78294

If you want an overarching view of how this will all connect see:
https://github.com/llvm/llvm-project/pull/90088
Changes:
- `llvm/docs/GlobalISel/GenericOpcode.rst` - Document the `G_FTAN`
opcode
-  `llvm/include/llvm/IR/Intrinsics.td` - Create the tan intrinsic
- `llvm/include/llvm/Support/TargetOpcodes.def` - Create a `G_FTAN`
Opcode handler
- `llvm/include/llvm/Target/GenericOpcodes.td` - Define the `G_FTAN`
Opcode
- `llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp` Map the tan intrinsic
to `G_FTAN` Opcode
- `llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp` - Map the
`G_FTAN` opcode to the GLSL 4.5 and openCL tan instructions.
- `llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp` - Define `G_FTAN` as a
legal spirv target opcode.
2024-05-08 00:57:39 -04:00
Vyacheslav Levytskyy
486ea1ec6e
[SPIR-V] Fix pre-legalizer pass in SPIR-V Backend to support more gMIR opcode inserted by IRTranslator (#89890)
Translating global values, IRTranslator pass can sometimes generates
code patterns that require additional efforts during pre-legalization.
This PR addresses this problem to support G_PTRTOINT instruction used in
initialization of GV.
2024-04-24 11:28:29 +02:00
Vyacheslav Levytskyy
89d125564a
Bit width of input/result types in OpSConvert/OpUConvert must not be the same (#89737)
This PR fixes the issue
https://github.com/llvm/llvm-project/issues/88908
Attached test case is updated to check that OpSConvert/OpUConvert is not
generated when input and result types are identical.
2024-04-24 11:28:17 +02:00
Farzon Lotfi
c4c54af569
[SPIRV][HLSL] map lerp to Fmix (#88976)
- `clang/lib/CodeGen/CGBuiltin.cpp` - switch to using
`getLerpIntrinsic()` to abstract backend intrinsic
- `clang/lib/CodeGen/CGHLSLRuntime.h` - add `getLerpIntrinsic()` 
- `llvm/include/llvm/IR/IntrinsicsSPIRV.td` - add SPIRV intrinsic for
lerp
- `llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp` - add mapping of
HLSL's lerp to GLSL's Fmix.

resolves #88940
2024-04-22 12:40:21 -04:00
Vyacheslav Levytskyy
b512df660e
[SPIR-V] Improve Tablegen instruction selection and account for a pointer size of the target (#88725)
This PR resolves the issue that SPIR-V Backend uses the notion of a
pointer size of the target, most notably, in legalizer code, but
Tablegen instruction selection in SPIR-V Backend doesn't account for a
pointer size of the target. See
https://github.com/llvm/llvm-project/issues/88723 for a detailed
description. There are 3 test cases attached to the PR that reproduced
the issue, when dealing with spirv32-spirv64 differences, and are
working correctly now with this PR.
2024-04-17 11:50:37 +02:00
Farzon Lotfi
105dcc882c
[HLSL][SPIRV] Add any intrinsic lowering (#88325)
- `CGBuiltin.cpp` - Switch to using
`CGM.getHLSLRuntime().get##NAME##Intrinsic()`
- `CGHLSLRuntime.h` - Add any to backend intrinsic abstraction
-  `IntrinsicsSPIRV.td` - Add any intrinsic to SPIR-V.
- `SPIRVInstructionSelector.cpp` - Add means of selecting any intrinsic.
Any and All share the same behavior up to the opCode. They are only
different in vector cases.

Completes #88045
2024-04-15 09:52:47 -04:00
Farzon Lotfi
05093e2438
[Spirv][HLSL] Add OpAll lowering and float vec support (#87952)
The main point of this change was to add support for HLSL's all
intrinsic.
In the process of doing that I found a few issues around creating an
`OpConstantComposite` via `buildZerosVal`.

First the current code didn't support floats so the process of adding
`buildZerosValF` meant I needed a
float version of `getOrCreateIntConstVector`. After doing so I renamed
both versions to `getOrCreateConstVector`. That meant I needed to create
a float type version of `getOrCreateIntCompositeOrNull`. Luckily the
type information was low for this function so was able to split it out
into a helpwe and rename `getOrCreateIntCompositeOrNull` to
`getOrCreateCompositeOrNull` With the exception of type handling
differences of the code and Null vs 0 Constant Op codes these functions
should be identical.

To handle scalar floats I could not use `buildConstantFP` like this PR
did:
https://github.com/llvm/llvm-project/commit/0a2aaab5aba46#diff-733a189c5a8c3211f3a04fd6e719952a3fa231eadd8a7f11e6ecf1e584d57411R1603
because that would create too many superfluous registers (that causes
problems in the validator), I had to create a float version of
`getOrCreateConstInt` which I called `getOrCreateConstFP`.
similar problems with doing it like this:
https://github.com/llvm/llvm-project/blob/main/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp#L1540.

`buildZerosValF` also has a use of a function `getZeroFP`. This is
because half, float, and double scalar values of 0 would collide in
`SPIRVDuplicatesTracker<Constant> CT` if you use `APFloat(0.0f)`.

`getORCreateConstFP` needed its own version of `getOrCreateConstIntReg`
which I called `getOrCreateConstFloatReg` The one difference in this
function is `getOrCreateConstFloatReg` returns a bit width so we don't
have to call `getScalarOrVectorBitWidth` twice ie when it is used again
in `getOrCreateConstFP` for `OpConstantF` `addNumImm`.

`getOrCreateConstFloatReg` needed an `assignFloatTypeToVReg` helper
which called a `getOrCreateSPIRVFloatType` helper. There was no
equivalent IntegerType::get for floats so I handled this with a switch
statement on bit widths to get the right LLVM float type.

Finally, there is the use of `bool ZeroAsNull = STI.isOpenCLEnv();` This
is partly a cosmetic change. When Zeros are treated as nulls, we don't
create `OpConstantComposite` vectors which is something we do in the
DXCs SPIRV backend. The DXC SPIRV backend also does not use
`OpConstantNull`. Finally, I needed a means to test the behavior of the
OpConstantNull and `OpConstantComposite` changes and this was one way I
could do that via the same tests.
2024-04-10 16:27:44 -04:00
Natalie Chouinard
1e44d9ac5e
[SPIR-V] Map llvm.{min,max}num to GL::N{Min,Max} (#88009)
SPIR-V intsruction selection was mapping the LLVM float min/max
intrinsics to FMin and FMax respectively for GL/Vulkan environments,
which does not match the intrinsics' documented treatment of NaN
operands. This patch switches the mapping to the correctly matched NMin
and NMax operations.

Fixes #87072
2024-04-09 09:41:47 -04:00
Vyacheslav Levytskyy
47e996d89d
[SPIR-V] Fix OpVariable instructions place in a function (#87554)
This PR:
* fixes OpVariable instructions place in a function (see
https://github.com/llvm/llvm-project/issues/66261),
* improves type inference,
* helps avoiding unneeded bitcasts when validating function call's

This allows to improve existing and add new test cases with more strict
checks. OpVariable fix refers to "All OpVariable instructions in a
function must be the first instructions in the first block" requirement
from SPIR-V spec.
2024-04-04 10:50:35 +02:00
Vyacheslav Levytskyy
b7ac8fddb5
[SPIR-V] Improve type inference: deduce types of composite data structures (#86782)
This PR improves type inference in general and deduces types of
composite data structures in particular. Also added a way to insert a
bitcast to make a fun call valid in case of arguments types mismatch due
to opaque pointers type inference.

The attached test `pointers/nested-struct-opaque-pointers.ll`
demonstrates new capabilities: the SPIRV code emitted for this test is
now (1) valid in a sense of data field types and (2) accepted by
`spirv-val`.

More strict LIT checks, support of more composite data structures and
improvement of fun calls from the perspective of type correctness are
main todo's at the moment.
2024-03-28 08:08:06 +01:00