Closed agnat closed 8 years ago
Ah, and it does no longer use the 16 bit pseudos, of course ;)
This looks really, really nice. If we get this passing, it will clean up and simplify the backend immensely.
I'm gonna have a look and see if I can diagnose the calling convention problem.
I asked about non-legal pointer types on LLVMdev.
I also found this PIC16 backend. It was removed in LLVM 2.9. It works around the issue by using custom ISD nodes, external symbols and... premature lowering. So, that's just for reference...
If you remove addRegisterClass(MVT::i16, &AVR::DREGSRegClass);
, are you still able to perform instruction selection on 16-bit values? From your comments, it looks like you can. Although I am a bit confused as to why LLVM generates three MUL
instructions for a single multiplication.
If you remove addRegisterClass(MVT::i16, &AVR::DREGSRegClass);, are you still able to perform instruction selection on 16-bit values?
Nope. There are no i16 values in the graph after type legalization. So there is nothing to match with. Which comment gave you that impression?
Although I am a bit confused as to why LLVM generates three MUL instructions for a single multiplication.
Hehe... yes, that's a bit confusing. However, it is an arithmetic property of multiplication and has nothing to do with computer science. Let me try to explain.
Let's forget about bits and bytes for a second. Subdividing operations on large binary numbers into operations on bytes is exactly equivalent to digit-wise arithmetic on paper like back in school. The only difference is that the former has radix 255 and the later has radix 10. It's easy to see with addition:
23
+ 42
-----
65
That is one add and one add with carry. Still with me? Now lets look at the ascii-art for a digit-wise multiplication:
23
⨉ 42
-----
46
+ 92
-----
966
That is actually four digit-wise multiplications. However, since we are going to truncate the result to two digits we can skip the fourth (4 * 2 + 1
) and get away with three.
... the former has radix 255 ...
256! But you get the idea... ;)
Looking a bit deeper into the whole SelectionDAG business I believe this is the root of all evil:
It makes LLVM believe i16 is a native type. So I ripped it out.
The part that immediately collapsed is the calling convention. I kind of kludged the kludge and it works for now (as in: it compiles). But it certainly has bugs. The whole calling convention could use some love...
The other issue is probably a little more involved. LLVM does not provide any help when the targets pointer type is larger than the targets native registers. I'll look into that.
Demo? Sure thing:
16 Bit Multiplication
No more crazy shifting.
64 Bit And
Everything fits in registers and is done in place.