zig icon indicating copy to clipboard operation
zig copied to clipboard

Modulo operation fails on integers of bitwidth greater than 128 bits

Open kristate opened this issue 7 years ago • 7 comments

test "mod129" {
    const base = 10;
    var a: @IntType(false, 129) = 0;
    const digit = a % base;
}

results in compiler error:

LLVM ERROR: Unsupported library call operation!

#1533 is related.

kristate avatar Sep 17 '18 07:09 kristate

backtrace:

(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.3
  * frame #0: 0x0000000102474cba zig`llvm::report_fatal_error(char const*, bool)
    frame #1: 0x0000000101bb5f95 zig`llvm::TargetLowering::makeLibCall(llvm::SelectionDAG&, llvm::RTLIB::Libcall, llvm::EVT, llvm::ArrayRef<llvm::SDValue>, bool, llvm::SDLoc const&, bool, bool) const + 1445
    frame #2: 0x0000000101afba28 zig`llvm::DAGTypeLegalizer::ExpandIntRes_UREM(llvm::SDNode*, llvm::SDValue&, llvm::SDValue&) + 400
    frame #3: 0x0000000101af6dd8 zig`llvm::DAGTypeLegalizer::ExpandIntegerResult(llvm::SDNode*, unsigned int) + 1524
    frame #4: 0x0000000101b072e5 zig`llvm::DAGTypeLegalizer::run() + 963
    frame #5: 0x0000000101b0a853 zig`llvm::SelectionDAG::LegalizeTypes() + 55
    frame #6: 0x0000000101ba6140 zig`llvm::SelectionDAGISel::CodeGenAndEmitDAG() + 354
    frame #7: 0x0000000101ba53e2 zig`llvm::SelectionDAGISel::SelectAllBasicBlocks(llvm::Function const&) + 5390
    frame #8: 0x0000000101ba364e zig`llvm::SelectionDAGISel::runOnMachineFunction(llvm::MachineFunction&) + 1512
    frame #9: 0x000000010193e6f8 zig`(anonymous namespace)::X86DAGToDAGISel::runOnMachineFunction(llvm::MachineFunction&) + 20
    frame #10: 0x0000000101d0ad8f zig`llvm::MachineFunctionPass::runOnFunction(llvm::Function&) + 113
    frame #11: 0x00000001023f71a4 zig`llvm::FPPassManager::runOnFunction(llvm::Function&) + 276
    frame #12: 0x00000001023f7369 zig`llvm::FPPassManager::runOnModule(llvm::Module&) + 49
    frame #13: 0x00000001023f7695 zig`llvm::legacy::PassManagerImpl::run(llvm::Module&) + 579
    frame #14: 0x00000001001059c5 zig`::ZigLLVMTargetMachineEmitToFile(targ_machine_ref=0x0000000105418c70, module_ref=0x00000001054173e0, filename="zig-cache/test.o", output_type=ZigLLVM_EmitBinary, error_message=0x00007ffeefbfefd0, is_debug=true, is_small=false, time_report=false) at zig_llvm.cpp:181
    frame #15: 0x000000010003a608 zig`zig_llvm_emit_output(g=0x000000010580c600) at codegen.cpp:6408
    frame #16: 0x0000000100037cb3 zig`codegen_build_and_link(g=0x000000010580c600) at codegen.cpp:8231
    frame #17: 0x00000001000cf2d1 zig`main(argc=3, argv=0x00007ffeefbff8d8) at main.cpp:978
    frame #18: 0x00007fff5b6e1015 libdyld.dylib`start + 1
    frame #19: 0x00007fff5b6e1015 libdyld.dylib`start + 1

kristate avatar Sep 17 '18 07:09 kristate

Hmm, llvm does not support urem and friends on integers with bitwidth > 128:

urem_test.ll:

define i256 @urem_test(i256 %a) {
  %1 = urem i256 %a, %a
  ret i256 %1
}

llc urem_test.ll -march=x86-64 -o urem_test-x86-64.s returns:

LLVM ERROR: Unsupported library call operation!

kristate avatar Sep 17 '18 08:09 kristate

very similar to https://github.com/ziglang/zig/issues/1485

ghost avatar Sep 17 '18 09:09 ghost

The short answer to this and #1485 is that we need to send a patch to LLVM to make it emit library calls for this even though the scope of those library calls is outside of the standardized compiler-rt.

andrewrk avatar Sep 17 '18 13:09 andrewrk

I also ran into this when trying to compare two i256s for equality - got the LLVM ERROR: Unsupported library call operation! but saw an actual segfault when trying to do multiplication.

To reproduce:

const std = @import("std");

fn square(num: i128) i128 {
    return @intCast(i128, @intCast(i256, num) * @intCast(i256, num));
}

test "square" {
    std.testing.expectEqual(square(5), 25);
}

produces this output, when run with zig test:

LLVM Emit Output... [1]    14190 segmentation fault  zig test repro.zig

rtfeldman avatar May 15 '21 18:05 rtfeldman

LLVM15 lowers division, remainder and modulus to __udivei4, __umodei4, __divei4 and __modei4.

https://discourse.llvm.org/t/rfc-add-support-for-division-of-large-bitint-builtins-selectiondag-globalisel-clang/60329

Vexu avatar Oct 24 '22 18:10 Vexu

https://github.com/ziglang/zig/commit/929cb68fdb088008d9a886fe71d1aff72c2fd52a implements __udivei4 and __umodei4, allowing > 128 bit integers to be formatted.

But looks like another direction is being taken by LLVM.

jedisct1 avatar Nov 02 '22 00:11 jedisct1