For raw interactions with GPUs, you generally use a rather vendor specific dialect of a programming language to write "shaders". This can be CUDA for Nvidia, MSL for Apple Silicon, HIP for AMD, etc. But why is there no one language that compiles down to different GPU ISAs using something like LLVM?
CPU ISAs comprise mostly of general purpose instructions that are heavily portable over different vendors - e.g. Intel and AMD both have CPUs that support x86_64 (there are vendor specific instructions, but not a lot).
In the case of GPUs, the ISA is a lot closer to the hardware implementation for optimization purposes. This causes modern GPU ISAs to be extremely complicated - and in some cases the vendors dont even release them for each GPU cycle.
This forces the backend of any optimizing compiler to be written by the vendor itself. Moreover, due to a lack of standardization, the vendors end up taking the task of implementing a frontend themselves as well, hence the vendor-specific language dialects. However even these dialects can have differing implementations based on the hardware provider! It ends up being a big mess of transpilers and compilers.
SPIR stands for Standard Portable Intermediate Representation (The V is for Vulkan, but that's not important).
To ease the propagation of bugs and inconsistencies, this unified IR (Intermediate Representation) was created. Its job is to offload the frontend optimizations to something like LLVM, while the backend optimizations can still be done by the vendor, in an API that takes SPIR-V as input. Its adoption is still not very widespread, but that is a blog-post for another day.