int48_t multiplication and division not working
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;
}
@jacobly0 Did you add support for int48_t without telling me? What functions are missing?
I believe it's been in there almost since the start?
Anyway I'm 90% sure it's related to this issue: https://github.com/jacobly0/llvm-project/issues/12
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.
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?
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.