Hi, I am trying to complete the hardware multiplier option for MSP430 backend. As the hardware multiplier in most of the MSP430 devices is for i8 and i16 operands, with i16 and i32 result, I am lowering MUL_i8 and MUL_I16. However, the front-end promotes the i8 argument to i32, executes 32-bit multiplier and truncates to 16-bit, so I never lower MUL_I8 nor MUL_I16 but MUL_I32, wchich is lowered to an external libcall (__mulsi3) that I don´t have. What should I do in order to prevent the front-end from promote to 32-bit multiplier? If that is not possible, how can I detect when lowering that it is actually a MUL_I8 or MUL_I16 in order to do the correct lowering? Thanks in advance, Pedro P.S: I add C code and corresponding LLVM code. C code: void (const u_int16_t in_data, u_int16_t* out) { u_int8_t kk = in_data&0xFF; u_int16_t kk16 = kk * kk; *out = kk16; } LLVM: %1 = load i8* %kk, align 1 %conv2 = zext i8 %1 to i32 %2 = load i8* %kk, align 1 %conv3 = zext i8 %2 to i32 %mul = mul nsw i32 %conv2, %conv3 %conv4 = trunc i32 %mul to i16 store i16 %conv4, i16* %kk16, align 2 -- Pedro Malagón - Profesor ayudante 91 549 57 00 - ext. 4220 Departamento de Ingeniería Electrónica Escuela Técnica Superior de Ingenieros de Telecomunicación Universidad Politécnica de Madrid
Hi Pedro, what is the "front-end" you refer to? Clang? Ciao, Duncan.> I am trying to complete the hardware multiplier option for MSP430 backend. > > As the hardware multiplier in most of the MSP430 devices is for i8 and > i16 operands, with i16 and i32 result, I am lowering MUL_i8 and MUL_I16. > However, the front-end promotes the i8 argument to i32, executes 32-bit > multiplier and truncates to 16-bit, so I never lower MUL_I8 nor MUL_I16 > but MUL_I32, wchich is lowered to an external libcall (__mulsi3) that I > don´t have. > > What should I do in order to prevent the front-end from promote to > 32-bit multiplier? > If that is not possible, how can I detect when lowering that it is > actually a MUL_I8 or MUL_I16 in order to do the correct lowering? > > Thanks in advance, > Pedro > > P.S: I add C code and corresponding LLVM code. > > C code: > void > (const u_int16_t in_data, u_int16_t* out) > { > u_int8_t kk = in_data&0xFF; > u_int16_t kk16 = kk * kk; > *out = kk16; > } > > > LLVM: > %1 = load i8* %kk, align 1 > %conv2 = zext i8 %1 to i32 > %2 = load i8* %kk, align 1 > %conv3 = zext i8 %2 to i32 > %mul = mul nsw i32 %conv2, %conv3 > %conv4 = trunc i32 %mul to i16 > store i16 %conv4, i16* %kk16, align 2 >
On Mon, Oct 8, 2012 at 2:44 AM, Pedro Malagón <malagon at die.upm.es> wrote:> Hi, > > I am trying to complete the hardware multiplier option for MSP430 backend. > > As the hardware multiplier in most of the MSP430 devices is for i8 and > i16 operands, with i16 and i32 result, I am lowering MUL_i8 and MUL_I16. > However, the front-end promotes the i8 argument to i32, executes 32-bit > multiplier and truncates to 16-bit, so I never lower MUL_I8 nor MUL_I16 > but MUL_I32, wchich is lowered to an external libcall (__mulsi3) that I > don´t have. > > What should I do in order to prevent the front-end from promote to > 32-bit multiplier?(I'm assuming you're getting C code from clang.) You can't, assuming your platform defines "int" to be 32 bits; clang is just following the C standard. This may seem a little silly in this case, but clang generally tries to generate math operations as written.> If that is not possible, how can I detect when lowering that it is > actually a MUL_I8 or MUL_I16 in order to do the correct lowering?At -O0, you don't. __mulsi3 is the obvious lowering, and you're doing something wrong if your tools don't provide it. There are probably some interesting issues with the current optimizers at -O2, but it's hard to discuss that without specific examples. -Eli
> At -O0, you don't. __mulsi3 is the obvious lowering, and you're doing > something wrong if your tools don't provide it.MSP430 is 16 bit target, so mulsi is a bit expensive there, mulhi / mulqi can be implemented via hardware multiplier. There are several problems wrt 16 bit support inside LLVM in general and msp430 in particular: 1. In some places LLVM expectes 32 bit or 64 bit target (e.g. i32 arguments length argument of memcpy, etc.) 2. On MSP430 the multiplier is an external device, so you either need to be sure that there are no muls, etc. inside interrupts, or disable interrupts while accessing the multiplier. I'm attaching some old proof-of-concept code for compiler-rt which implementes "hi" and "qi" operations. Most probably it needs to be modified to be fit into current compiler-rt codebase. -- With best regards, Anton Korobeynikov Faculty of Mathematics and Mechanics, Saint Petersburg State University -------------- next part -------------- A non-text attachment was scrubbed... Name: mulhi3hw_noint.S Type: application/octet-stream Size: 509 bytes Desc: not available URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20121008/34bf46a4/attachment.obj> -------------- next part -------------- A non-text attachment was scrubbed... Name: mulhi3hw.S Type: application/octet-stream Size: 541 bytes Desc: not available URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20121008/34bf46a4/attachment-0001.obj> -------------- next part -------------- A non-text attachment was scrubbed... Name: mulqi3hw_noint.S Type: application/octet-stream Size: 510 bytes Desc: not available URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20121008/34bf46a4/attachment-0002.obj> -------------- next part -------------- A non-text attachment was scrubbed... Name: mulqi3hw.S Type: application/octet-stream Size: 541 bytes Desc: not available URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20121008/34bf46a4/attachment-0003.obj> -------------- next part -------------- A non-text attachment was scrubbed... Name: umulhi3hw_noint.S Type: application/octet-stream Size: 511 bytes Desc: not available URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20121008/34bf46a4/attachment-0004.obj> -------------- next part -------------- A non-text attachment was scrubbed... Name: umulhi3hw.S Type: application/octet-stream Size: 542 bytes Desc: not available URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20121008/34bf46a4/attachment-0005.obj> -------------- next part -------------- A non-text attachment was scrubbed... Name: umulqi3hw_noint.S Type: application/octet-stream Size: 511 bytes Desc: not available URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20121008/34bf46a4/attachment-0006.obj> -------------- next part -------------- A non-text attachment was scrubbed... Name: umulqi3hw.S Type: application/octet-stream Size: 542 bytes Desc: not available URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20121008/34bf46a4/attachment-0007.obj>
Maybe Matching Threads
- [LLVMdev] Multiply i8 operands promotes to i32
- [LLVMdev] Multiply i8 operands promotes to i32
- Bug 20871 -- is there a fix or work around?
- [LLVMdev] Unnecessary moves after sign-extension in 2-address target
- [LLVMdev] llvm-gcc promotes i32 mul to i64 inside __muldi3