aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/IR/Module.cpp
diff options
context:
space:
mode:
authorT0b1-iOS <T0b1-iOS@users.noreply.github.com>2025-07-17 18:57:32 +0200
committerGitHub <noreply@github.com>2025-07-17 09:57:32 -0700
commitd35931c49e5b37243ace2b79bec87463772b6c94 (patch)
tree4cedd1129164a17dc17e91f62748202c15f20d2d /llvm/lib/IR/Module.cpp
parente4a3541ff88af03c01007a94b6b5f5cea95ecf33 (diff)
downloadllvm-d35931c49e5b37243ace2b79bec87463772b6c94.zip
llvm-d35931c49e5b37243ace2b79bec87463772b6c94.tar.gz
llvm-d35931c49e5b37243ace2b79bec87463772b6c94.tar.bz2
[Clang][CodeGen][X86] don't coerce int128 into `{i64,i64}` for SysV-like ABIs (#135230)
Currently, clang coerces (u)int128_t to two i64 IR parameters when they are passed in registers. This leads to broken debug info for them after applying SROA+InstCombine. SROA generates IR like this ([godbolt](https://godbolt.org/z/YrTa4chfc)): ```llvm define dso_local { i64, i64 } @add(i64 noundef %a.coerce0, i64 noundef %a.coerce1) { entry: %a.sroa.2.0.insert.ext = zext i64 %a.coerce1 to i128 %a.sroa.2.0.insert.shift = shl nuw i128 %a.sroa.2.0.insert.ext, 64 %a.sroa.0.0.insert.ext = zext i64 %a.coerce0 to i128 %a.sroa.0.0.insert.insert = or i128 %a.sroa.2.0.insert.shift, %a.sroa.0.0.insert.ext #dbg_value(i128 %a.sroa.0.0.insert.insert, !17, !DIExpression(), !18) // ... !17 = !DILocalVariable(name: "a", arg: 1, scope: !10, file: !11, line: 1, type: !14) // ... ``` and InstCombine then removes the `or`, moving it into the `DIExpression`, and the `shl` at which point the debug info salvaging in `Transforms/Local` replaces the arguments with `poison` as it does not allow constants larger than 64 bit in `DIExpression`s. I'm working under the assumption that there is interest in fixing this. If not, please tell me. By not coercing `int128_t`s into `{i64, i64}` but keeping them as `i128`, the debug info stays intact and SelectionDAG then generates two `DW_OP_LLVM_fragment` expressions for the two corresponding argument registers. Given that the ABI code for x64 seems to not coerce the argument when it is passed on the stack, it should not lead to any problems keeping it as an `i128` when it is passed in registers. Alternatively, this could be fixed by checking if a constant value fits in 64 bits in the debug info salvaging code and then extending the value on the expression stack to the necessary width. This fixes InstCombine breaking the debug info but then SelectionDAG removes the expression and that seems significantly more complex to debug. Another fix may be to generate `DW_OP_LLVM_fragment` expressions when removing the `or` as it gets marked as disjoint by InstCombine. However, I don't know if the KnownBits information is still available at the time the `or` gets removed and it would probably require refactoring of the debug info salvaging code as that currently only seems to replace single expressions and is not designed to support generating new debug records. Converting `(u)int128_t` arguments to `i128` in the IR seems like the simpler solution, if it doesn't cause any ABI issues.
Diffstat (limited to 'llvm/lib/IR/Module.cpp')
0 files changed, 0 insertions, 0 deletions