Skip to content

Commit 40528b8

Browse files
committed
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 parent 370662c commit 40528b8

File tree

1 file changed

+22
-2
lines changed

1 file changed

+22
-2
lines changed

src/codegen/llvm.zig

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10333,8 +10333,20 @@ pub const FuncGen = struct {
1033310333
const o = fg.dg.object;
1033410334
const mod = o.module;
1033510335
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+
1033610348
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))
1033810350
else
1033910351
payload_llvm_ty;
1034010352
const loaded = try fg.wip.load(access_kind, load_llvm_ty, payload_ptr, payload_alignment, "");
@@ -10345,7 +10357,15 @@ pub const FuncGen = struct {
1034510357
), "")
1034610358
else
1034710359
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, "");
1034910369
}
1035010370

1035110371
/// Load a by-ref type by constructing a new alloca and performing a memcpy.

0 commit comments

Comments
 (0)