microsoft / microsoft/DirectXShaderCompiler

Long vector tests fail on x86 for 64-bit left/right shift operations

Open
#8,178 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
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: includes 32
  • int64_t/uint64_t: includes 64

This causes two problems:

  1. C++ undefined behavior: Per the C++ standard (expr.shift), shifting by an amount greater than or equal to the bit width is undefined behavior.

  2. Platform-dependent results: MSVC x86 64-bit shift implementation returns 0 for value << 64, while HLSL/DXIL (and GPU hardware) masks the shift amount to the low 6 bits, computing value << (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/shr instructions use only the low 6 bits of the shift count. So shl rax, 64 executes as shl rax, 0 (since 64 & 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, 3229, 30, 31
  • int64_t/uint64_t: 62, 63, 6461, 62, 63

This matches the existing 16-bit pattern which correctly ends at 15.

Affected Files
  • tools/clang/unittests/HLSLExec/LongVectorTestData.h - BitShiftRhs input sets
Affected Tests
  • LeftShift_int64_t
  • RightShift_int64_t
  • LeftShift_uint64_t
  • RightShift_uint64_t

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.