No truncation warning issued for 32-bit output of 64-bit atomics
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
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.