## Summary
The SPIR-V backend maps OpenCL `atomic_fetch_add`/`sub`/`or`/`xor`/`and`
(and their `_explicit` variants) to SPIR-V atomic opcodes, but was
missing support for `atomic_fetch_min`/`atomic_fetch_max`, their
`_explicit` variants, and the legacy `atom_min`/`atom_max` builtins.
This caused OpenCL programs using these atomics to emit unresolved
function calls instead of the correct
`OpAtomicSMin`/`OpAtomicSMax`/`OpAtomicUMin`/`OpAtomicUMax`
instructions.
### Approach
Unlike add/sub/or/xor/and (which are sign-agnostic), min/max require
distinct signed vs unsigned SPIR-V opcodes. Rather than inspecting the
`OpTypeInt` signedness bit at runtime (which is always 0 in this
backend), this patch uses the existing prefix-based builtin lookup
mechanism in `lookupBuiltin`: the itanium demangler exposes the argument
type (`int` vs `unsigned int`), and the lookup adds an `s_` or `u_`
prefix accordingly, matching the correct `.td` entry.
### Changes
- **`SPIRVBuiltins.td`**: Add 12 prefixed `DemangledNativeBuiltin`
entries (`s_`/`u_` variants for `atomic_fetch_min`, `atomic_fetch_max`,
`atomic_fetch_min_explicit`, `atomic_fetch_max_explicit`, `atom_min`,
`atom_max`)
- **`SPIRVBuiltins.cpp`**: Add
`OpAtomicSMin`/`OpAtomicSMax`/`OpAtomicUMin`/`OpAtomicUMax` cases to the
`generateAtomicInst` switch to route these opcodes to
`buildAtomicRMWInst` (also fixes the pre-existing
`__spirv_Atomic{S,U}{Min,Max}` builtins that were defined in `.td` but
not handled in the switch)
- **New test**: `atomic_fetch_min_max.ll` covering all 6 builtins for
both signed and unsigned `i32` types