microsoft / microsoft/DirectXShaderCompiler
Long vector tests fail on x86 for 64-bit left/right shift operations
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 3.7k
- Forks
- 900
- Avg merge
- 2d 11h
- Merged PRs (30d)
- 44
Description
Issue description assisted by gh copilot.
Description
The x86 build of long vector tests fails for 64-bit left shift and right shift operations (LeftShift_int64_t, LeftShift_uint64_t, RightShift_int64_t, RightShift_uint64_t).
Root Cause
The BitShiftRhs test input sets include shift amounts equal to the bit width of the type:
int32_t/uint32_t: includes32int64_t/uint64_t: includes64
This causes two problems:
-
C++ undefined behavior: Per the C++ standard (expr.shift), shifting by an amount greater than or equal to the bit width is undefined behavior.
-
Platform-dependent results: MSVC x86 64-bit shift implementation returns
0forvalue << 64, while HLSL/DXIL (and GPU hardware) masks the shift amount to the low 6 bits, computingvalue << (64 & 63)=value << 0=value.
Expected HLSL Behavior
DXBC (and by extension DXIL) explicitly masks shift amounts:
- 32-bit shifts: mask with
0x1F(5 bits) - 64-bit shifts: mask with
0x3F(6 bits)
Reference: DxbcConverter.cpp line 5570
Why results vary by platform
Since shifting by >= bit width is undefined behavior in C++, results depend on compiler and platform:
-
x86 (32-bit build): MSVC generates a call to a helper routine for 64-bit shifts. That helper explicitly checks for shifts >= 64 and returns
0, which does not match GPU behavior. -
x64 (64-bit build): Native
shl/shrinstructions use only the low 6 bits of the shift count. Soshl rax, 64executes asshl rax, 0(since64 & 63 = 0), returning the original value—which happens to match HLSL's defined behavior.
Either platform may pass or fail depending on compiler or future compiler changes. The observed failure was on x86, but this is ultimately undefined behavior and should not be relied upon.
Proposed Fix
Change the BitShiftRhs input sets to not include shift amounts >= bit width:
int32_t/uint32_t:30, 31, 32→29, 30, 31int64_t/uint64_t:62, 63, 64→61, 62, 63
This matches the existing 16-bit pattern which correctly ends at 15.
Affected Files
tools/clang/unittests/HLSLExec/LongVectorTestData.h-BitShiftRhsinput sets
Affected Tests
LeftShift_int64_tRightShift_int64_tLeftShift_uint64_tRightShift_uint64_t
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Open tools/clang/unittests/HLSLExec/LongVectorTestData.h and inspect the BitShiftRhs input sets, then run the affected long-vector shift tests: LeftShift_int64_t, RightShift_int64_t, LeftShift_uint64_t, and RightShift_uint64_t. Done means the test inputs avoid shifts at or above each type's width and all four tests pass on x86.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- compilers, testing-qa
- Issue type
- Bug
- Difficulty
- 1/5
- Estimated time
- Under an hour
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 58/100