Add and substract were the main culprits here.
We are trying to more towards a state where:
* Every IR op can expect it isn't given extra bits
on it's input
* Every IR op never sets more bits than it's size
* All unnessicary BFEs are never emitted
* ARM doesn't have to implement special 8 and 16bit versions of IR ops
All masking required to implement 8/16bit math on
arm should be explictly generated from Opcode decoder
The IR mostly worked this way already.
The one change I needed to make was in DCSE.
DCSE needs to add an explict truncate whenever an eliminated store was
doing an implict trunctate.
We are rebranding an x86-64 illegal instruction near VIA's old ALTINST
instruction as an instruction to handle returning from guest signals
cleanly.
If this ever collides with a new x86-64 (unlikely) then we will need to
change the instruction.
This ends up looking similar to what we will do for thunk callbacks
32bit apps are setting GS register that I saw.
64Bit applications can also technically use these instructions but it
has some major limitation that causes applications to never use them
This implements support for 130 of the 132 x87 ops as interpreter
fallbacks.
The two missing ops are the BCD load and BCD store instructions and can
be implemented another time.
This allows us to no longer have to rely on a libstdc++ modification to
handle their usage of long double. This instead works entirely through
using `long double` directly in the interpreter. Which will either use
real x87 on an x86 host. Or in the case of ARM devices, fall down
glibc's long double soft float path.
This doesn't necessarily need to be quick right now. It's more important
to have the compatibility improvement from this.
As we run more threaded applications it is becoming apparent that this
needs to be fixed now.
This duplicates the FrontendDecoder and Passmanager per thread so they
no longer block each other while compiling.
Increases a bit of memory usage but completely worth it.
Codeblock array was constantly being reallocated.
Changes the remap array over to a allocate in multiples of the alignment
size.
Was hitting a pedantic case where the compaction would hit slightly
increasing function sizes so large numbers of reallocations occured
quickly.
We already have an unmodified classification struct. Just memcpy it to
reset the state. Reduces a bunch of temporary allocations.
Also disables the CFG calculation since we aren't using it currently
The IRHeader itself contains a flag for if a block should fallback to
the interpreter.
This is necessary for the case that an IR is loaded and the Frontend
object no longer has the data necessary to know if it should do an
interpreter fallback.
This is super useful for bisecting JIT versus Intepreter failures, and
also cases where falling back to intepreter for compatibility is a lot
more simple than wiring things through the JIT (ala x87)
This isn't currently utilized, but will be once x87 work lands
Spilling is a mess in this version of the RA and there was a significant
bug that effectively made spilling either infinite loop or crash.
This adds a bunch of new comments about the logic of the spilling and
ipmroves it so it shouldn't break as easily.
There are still some edge cases that can be hit that break spilling but
a lot of this code is going to be scrapped for the new RA coming up
anyway.
This is temporary until the new RA merges in.
The Passmanager passes need very little or zero x86 knowledge to do
their work. They don't need the x86 OpDispatcher handling code at all.
Convert this entirely over to using the IREmitter class so it can
actually optimize IR code from the IRLoader frontend
This class does IR emitting and some basic handling of IR specific
tasks.
This is going to be used to split the x86 OpDispatcher from the IR
emission so the IR emitter can be passed around without caring about x86
dependencies.
Adds some additional validation that an IR op is generating RA for ops
that set a destination.
Ensuring correct register class and that there is a physical register
assigned
Sadly this is a fairly substantial change that can't be broken in to
something smaller.
The gist of the problem is that most of the vector ops declared their
own uint8_t RegisterSize and ElementSize variables in their structs.
This was initially done because there were assumptions elsewhere in the
source that sometimes mixed up the IROp member `Size` and `Elements` as
sometimes meaning `Size` elements and `Elements` number of elements.
Other times there was an assumption that `Size` was the full register
size and `Elements` was the number of elements inside that size.
ex: `Size`: 16, `Elements` 8 would sometimes be interpreted as i8v16 OR i128v8
These assumptions are now removed and we also save on average 16bits per
vector operation. This is a necessary evil first step for upcoming IR
considerations.
This should have zero change on runtime behaviour and unit tests confirm
that.
Changes the IR register class definition to exist in the JSON file.
Removes a couple of IR ops that were unused and weren't necessary.
Changes the CPUID IR op to the new paired op which improves perf ever so
slightly.
Changes RA class handling in the RA pass to pull directly from the new
generated helper routine until it hits a complex op
Still need RA constraints to remove extraneous moves that would crop up
Consolidates usage of register class to the one that is defined in the
IR Json file.
Every magic number is replaced with InvalidClass and instead uses the
enums directly
Another bug fix is that the GetHostFlags IR ops was being declared as
using the flags register class, which isn't a real thing yet.
This would most likely have ended up with host flag usage being
scheduled to a GPR that was already scheduled and overwrite it.
Once this IR op ends up in host flags this will be changed as well