authorgravatar for xavierb@gmail.comXavier Bouchoux <xavierb@gmail.com> 2023-10-08 11:35:33+02:00
committergravatar for xavierb@gmail.comXavier Bouchoux <xavierb@gmail.com> 2023-10-08 11:37:49+02:00
log40528b8a9348fc615cc36a85eebd8cc6ee184333
tree23d07b8f001f6c545b957d195f31e5f410e7cc75
parent370662c565ba541157e3c69d12625c28787d642e

codegen/llvm: add workarounds to loadTruncate() for llvm codegen bugs

for wasm, as a heuritic, only enable truncation for values smaller than 32bits. -> the bug is no longer triggered in most use cases (or at least the test suite...) as for powerpc, adding a redundant `and mask` produces working code.

1 files changed, 22 insertions(+), 2 deletions(-)

src/codegen/llvm.zig+22-2
...@@ -10333,8 +10333,20 @@ pub const FuncGen = struct {...@@ -10333,8 +10333,20 @@ pub const FuncGen = struct {
10333 const o = fg.dg.object;10333 const o = fg.dg.object;
10334 const mod = o.module;10334 const mod = o.module;
10335 const payload_llvm_ty = try o.lowerType(payload_ty);10335 const payload_llvm_ty = try o.lowerType(payload_ty);
10336 const abi_size = payload_ty.abiSize(mod);
10337
10338 // llvm bug workarounds:
10339 const workaround_explicit_mask = o.target.cpu.arch == .powerpc and abi_size >= 4;
10340 const workaround_disable_truncate = o.target.cpu.arch == .wasm32 and abi_size >= 4;
10341
10342 if (workaround_disable_truncate) {
10343 // see https://github.com/llvm/llvm-project/issues/64222
10344 // disable the truncation codepath for larger that 32bits value - with this heuristic, the backend passes the test suite.
10345 return try fg.wip.load(access_kind, payload_llvm_ty, payload_ptr, payload_alignment, "");
10346 }
10347
10336 const load_llvm_ty = if (payload_ty.isAbiInt(mod))10348 const load_llvm_ty = if (payload_ty.isAbiInt(mod))
10337 try o.builder.intType(@intCast(payload_ty.abiSize(mod) * 8))10349 try o.builder.intType(@intCast(abi_size * 8))
10338 else10350 else
10339 payload_llvm_ty;10351 payload_llvm_ty;
10340 const loaded = try fg.wip.load(access_kind, load_llvm_ty, payload_ptr, payload_alignment, "");10352 const loaded = try fg.wip.load(access_kind, load_llvm_ty, payload_ptr, payload_alignment, "");
...@@ -10345,7 +10357,15 @@ pub const FuncGen = struct {...@@ -10345,7 +10357,15 @@ pub const FuncGen = struct {
10345 ), "")10357 ), "")
10346 else10358 else
10347 loaded;10359 loaded;
10348 return fg.wip.conv(.unneeded, shifted, payload_llvm_ty, "");10360
10361 const anded = if (workaround_explicit_mask and payload_llvm_ty != load_llvm_ty) blk: {
10362 // this is rendundant with llvm.trunc. But without it, llvm17 emits invalid code for powerpc.
10363 var mask_val = try o.builder.intConst(payload_llvm_ty, -1);
10364 mask_val = try o.builder.castConst(.zext, mask_val, load_llvm_ty);
10365 break :blk try fg.wip.bin(.@"and", shifted, mask_val.toValue(), "");
10366 } else shifted;
10367
10368 return fg.wip.conv(.unneeded, anded, payload_llvm_ty, "");
10349 }10369 }
1035010370
10351 /// Load a by-ref type by constructing a new alloca and performing a memcpy.10371 /// Load a by-ref type by constructing a new alloca and performing a memcpy.