DirectXShaderCompiler icon indicating copy to clipboard operation
DirectXShaderCompiler copied to clipboard

No truncation warning issued for 32-bit output of 64-bit atomics

Open dmpots opened this issue 2 years ago • 1 comments

Description When using InterlockedAdd with a 32-bit output varaible I would expect the compiler to issue a truncation warning, but no warning is given even though the resulting dxil has a truncation in the output.

Steps to Reproduce https://godbolt.org/z/fbK7hWevT

RWStructuredBuffer<uint64_t> buf;

[RootSignature("DescriptorTable(UAV(u0))")]
uint main() : A {
   //return vk::ReadClock(vk::SubgroupScope);
   uint old;
   InterlockedAdd(buf[0], 1, old);
   return old;
}

Actual Behavior The shader compiles without a warning even though the output variable is truncated from 64 to 32 bits.

  %AtomicAdd = call i64 @dx.op.atomicBinOp.i64(i32 78, %dx.types.Handle %1, i32 0, i32 0, i32 0, i32 undef, i64 1)
  %2 = trunc i64 %AtomicAdd to i32, !dbg !46
  call void @dx.op.storeOutput.i32(i32 5, i32 0, i32 0, i8 0, i32 %2)

Environment

  • dxcompiler.dll: 1.8 - 1.7.0.4383 (ad3958c2d); dxil.dll: 1.6(101.6.2104.33)
  • Windows11

dmpots avatar Jan 25 '24 17:01 dmpots

A lot of the implicit out parameter conversions are completely silent because we don't capture them in the AST. The current AST captures casting the uint->int64 on the pass in (which wouldn't warn), but we don't capture the convert back in the AST at all:

  | |-CallExpr 0x56287cb3a690 <line:6:4, col:33> 'void'
  | | |-ImplicitCastExpr 0x56287cb3a678 <col:4> 'void (*)(unsigned long long &, unsigned long long, long long &)' <FunctionToPointerDecay>
  | | | `-DeclRefExpr 0x56287cb3a610 <col:4> 'void (unsigned long long &, unsigned long long, long long &)' lvalue Function 0x56287cb3a368 'InterlockedAdd' 'void (unsigned long long &, unsigned long long, long long &)'
  | | |-CXXOperatorCallExpr 0x56287cb3a1c0 <col:19, col:24> 'unsigned long long' lvalue
  | | | |-ImplicitCastExpr 0x56287cb3a1a8 <col:22, col:24> 'unsigned long long &(*)(unsigned int) const' <FunctionToPointerDecay>
  | | | | `-DeclRefExpr 0x56287cb3a140 <col:22, col:24> 'unsigned long long &(unsigned int) const' lvalue CXXMethod 0x56287cb39f80 'operator[]' 'unsigned long long &(unsigned int) const'
  | | | |-ImplicitCastExpr 0x56287cb3a110 <col:19> 'const RWStructuredBuffer<unsigned long long>' lvalue <NoOp>
  | | | | `-DeclRefExpr 0x56287cb39e10 <col:19> 'RWStructuredBuffer<uint64_t>':'RWStructuredBuffer<unsigned long long>' lvalue Var 0x56287cb2cd08 'buf' 'RWStructuredBuffer<uint64_t>':'RWStructuredBuffer<unsigned long long>'
  | | | `-ImplicitCastExpr 0x56287cb3a128 <col:23> 'unsigned int' <IntegralCast>
  | | |   `-IntegerLiteral 0x56287cb39e38 <col:23> 'literal int' 0
  | | |-ImplicitCastExpr 0x56287cb3a6d0 <col:27> 'unsigned long long' <IntegralCast>
  | | | `-IntegerLiteral 0x56287cb3a208 <col:27> 'literal int' 1
  | | `-DeclRefExpr 0x56287cb3a228 <col:30> 'uint':'unsigned int' lvalue Var 0x56287cb386a8 'old' 'uint':'unsigned int'

This is fixed by #5249, but I don't know that we'll ever land that PR in DXC.

llvm-beanz avatar Jan 25 '24 20:01 llvm-beanz