Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

int48_t multiplication and division not working #440

Open
fundudeone opened this issue Jul 15, 2023 · 5 comments
Open

int48_t multiplication and division not working #440

fundudeone opened this issue Jul 15, 2023 · 5 comments

Comments

@fundudeone
Copy link

fundudeone commented Jul 15, 2023

I'm getting llvm fatal errors when multiplying and dividing int48_t's in functions. This is on CEdev version 11.1.

Reproduction:

#include <stdlib.h>
#include <stdint.h>
#include <debug.h>

int48_t test1(){
    return ((int48_t)2)/((int48_t)3); //works
}

int48_t test2(int48_t a, int48_t b){
    return a+b; //works
}

int48_t test3(int48_t a, int48_t b){
    return a*b; //llvm fatal error
}

int48_t test4(int48_t a, int48_t b){
    return a/b; //llvm fatal error
}

/* Main function, called first */
int main(void){
    dbg_printf("Test1 = %d\n", (int)test1());
    int48_t a = 500;
    int48_t b = 5;
    dbg_printf("Not in function 500/5 = %i\n", (int)(a/b)); //works
    dbg_printf("Test2(500, 5) = %d\n", (int)test2(a, b));
    dbg_printf("Test3(500, 5) = %d\n", (int)test3(a, b));
    dbg_printf("Test4(500, 5) = %d\n", (int)test4(a, b));


    return 0;
}
@runer112
Copy link
Member

@jacobly0 Did you add support for int48_t without telling me? What functions are missing?

@mateoconlechuga
Copy link
Member

I believe it's been in there almost since the start?

Anyway I'm 90% sure it's related to this issue: jacobly0/llvm-project#12

@fundudeone
Copy link
Author

I tried compiling with the fix/12 branch of ez80-clang. It doesn't compile with LTO on and clang hangs with all optimization off.

@fundudeone
Copy link
Author

I changed some things in ez80-clang (fix12 branch) and code is now compiling but produces incorrect output (for reasons that will be apparent later). The tweaks I made are probably incredibly naïve as this is my first time working on llvm stuff but here's what I did:

llvm/lib/Target/Z80/GISel:
Changed line 84 to: auto LegalLibcallScalars24 = {s8, s16, s24, s32, s48, s64};

llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp:
Added macro RTLIBCASE_MULDIV_ALL (Backslashes omitted):

#define RTLIBCASE_MULDIV_ALL(LibcallPrefix)
  do {
    switch(Size){
    case 8:
      return RTLIB::LibcallPrefix##8;
    case 16:
      return RTLIB::LibcallPrefix##16;
    case 24:
      return RTLIB::LibcallPrefix##24;
    case 32:
      return RTLIB::LibcallPrefix##32;
    case 48:
      return RTLIB::LibcallPrefix##48;
    case 64:
      return RTLIB::LibcallPrefix##64;
    case 128:
      return RTLIB::LibcallPrefix##128;
    }
  } while(0)

Replaced line 548 to: RTLIBCASE_MULDIV_ALL(MUL_I);
Replaced line 550 to: RTLIBCASE_MULDIV_ALL(SDIV_I);

llvm/include/llvm/IR/RuntimeLibcalls.def:
Added lines:

HANDLE_LIBCALL(MUL_I48, "_llmulu")
HANDLE_LIBCALL(SDIV_I48, "_lldivu")

Compiling the reproduction gives the following output:

Test1 = 0
Not in function 500/5 = 0
Test2(500, 5) = 505
Test3(500, 5) = 0
Test4(500, 5) = 0

The incorrect output for Test3 and Test4 makes sense as I provided the long long multiplication and division assembly routines and not int48_t ones. Are int48_t operation routines available anywhere?

@mateoconlechuga
Copy link
Member

mateoconlechuga commented Aug 23, 2023

Are int48_t operation routines available anywhere?

int48_t is not implemented nor officially supported by the toolchain. I'm not sure what you are doing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

3 participants