Commit Graph
172 Commits
Author SHA1 Message Date
Alyssa Rosenzweig ff37177f4d IR: Remove AND(N)Z conditions
Unused since TestNZ+NZCVSelect accomplishes the same and good riddance. Might
bring them back later for tbz/tbnz, but certainly not in this Selectful form.

(I added them when I thought we were going to RA the flags. With the more
effective static approach, we don't need this for that.)

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
2023-11-12 17:32:24 -04:00
Alyssa Rosenzweig 157f95b08f IR: Extend TestNZ to two sources
Unlock the power of AND.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
2023-11-12 17:32:24 -04:00
Alyssa Rosenzweig 6bf7ab0778 IR: Remove complex branches
Performance footgun and now unused. Don't bring it back.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
2023-11-12 17:32:24 -04:00
Alyssa Rosenzweig 0de958be2a IR: Remove Abs
Now unused. If we bring it back, it should be brought back as CSSC only. On
non-CSSC platforms, an explicit cmp + predicated neg can be better.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
2023-11-12 17:32:24 -04:00
Alyssa Rosenzweig 5eea68d6c6 IR: Support predicated Neg
i.e. cneg. will be used for x87 hell op

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
2023-11-12 17:32:24 -04:00
Alyssa Rosenzweig 099c683a5a IR: Add FromNZCV mode to CondJump
In this mode, rather than the branch comparing its arguments and then jumping
based on the result, the branch simply jumps by the native comparison based on
the NZCV value. This allows us to map x86 branches to arm64 branches 1:1.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
2023-11-12 17:32:24 -04:00
Alyssa Rosenzweig 228c7d142e IR: Allow inline 0 on NZCVSelect
via the 0 reg. We really need a more generalized approach to taking advantage of
wzr, but this optimizes the special case I care about for seta (saving a move to
make the impl optimal).

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
2023-11-10 09:42:26 -04:00
Alyssa Rosenzweig 041199644c IR: Add NZCVSelect op
This will replace Select soon, as it lets us take advantage of
NZCV-generating instructions and it doesn't clobber NZCV.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
2023-11-10 09:04:42 -04:00
Alyssa Rosenzweig b5c83f0628 JIT: Optimize 8/16-bit TestNZ
This is cursed. I blame the darling.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
2023-11-09 14:50:36 -04:00
Alyssa Rosenzweig 1281145982 OpcodeDispatcher: Optimize popf
mostly for easier debugging tbh

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
2023-11-09 09:40:51 -04:00
Alyssa Rosenzweig 5336129b58 IR: Optimize sub/sbb
Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
2023-11-09 09:40:51 -04:00
Alyssa Rosenzweig 72fc2b522d IR: Optimize add/adc
Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
2023-11-09 09:40:51 -04:00
Alyssa Rosenzweig b6f6c84790 IR: Optimize tests
Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
2023-11-09 09:40:51 -04:00
Alyssa Rosenzweig afdb8753ba IR: Remove some implicit flag clobbers
Do it explicitly for sve-256 and punt on optimizing, so we avoid regressing code
gen otherwise.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
2023-11-09 09:40:51 -04:00
Alyssa Rosenzweig d6569d510d Arm64: Keep host flags resident in NZCV
Rather than the context. Effectively a static register allocation scheme for
flags. This will let us optimize out a LOT of flag handling code, keeping things
in NZCV rather than needing to copy between NZCV and memory all the time.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
2023-11-09 09:40:51 -04:00
Alyssa Rosenzweig 8f7e393ffb Arm64: Don't clobber NZCV in CondJump
Again we need to handle this one specially because the dispatcher can't insert
restore code after the branch. It should be optimized in the near future, don't
worry.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
2023-11-09 09:40:51 -04:00
Alyssa Rosenzweig b3055523b4 IR: Switch to dedicated NZCV load/store
Semantics differ markedly from the non-NZCV flags, splitting this out makes it a
lot easier to do things correctly imho. Gets the dest/src size correct
(important for spilling), as well as makes our existing opt passes skip this
which is needed for correctness at the moment anyway.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
2023-11-09 09:40:51 -04:00
Ryan Houdek 829384e488 JITArm64: Fixes double munmap issue that was causing crashes
While tracking issues in #3162, I had encountered a random crash that I
started hunting. It was very quickly apparent that this crash was
unrelated to that PR. I just happened to be running a unittest that was
creating and tearing down a bunch of threads that exacerbated the
problem.

See as follows with the strace output:
```
[pid 269497] munmap(0x7fffde1ff000, 16777216) = 0
[pid 269497] munmap(0x7fffde1ff000, 16777216 <unfinished ...>
[pid 268982] mmap(NULL, 16777216, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fffde1ff000
[pid 269497] <... munmap resumed>)      = 0
```

One thread is freeing some memory with munmap, another one then does a mmap and gets the same address back.
Nothing too crazy at initial glance, but taking a closelier look, we can
see that there are two strange oddities:
1) We are double unmapping the same address range through munmap
2) The second munmap is interrupted and returns AFTER the mmap.

This has the unfortunate side-effect that the mmap that just returned
the same address has actually just been unmapped! This was resulting in
spurious crashes around thread creation that was SUPER hard to nail
down.

The problem comes down to how code buffer objects are managed, in
particular how the Arm64Emitter and Dispatcher handled its buffers.

Arm64Emitter is inherited by two classes; Dispatcher, and Arm64JITCore.
On class destruction the emitter would free its internal tracking
buffer. Additionally on destruction, the Arm64JITCore would walk through
all of its CodeBuffers and free them. The problem ends up being that in
the Arm64JITCore, it would free its code buffers which also ended up
being the current active buffer bound to the Arm64Emitter. Thus causing
the Arm64Emitter to come back around and try to free the same buffer
again.

This is a double-free problem! and was only visible on thread exiting!
Can't track double frees with mmap and munmap with current tooling!

This problem typically didn't occur because of how fast the destruction
usually takes and jemalloc inbetween also typically means the problem
doesn't occur. Initially thinking this was a threaded pool allocator bug
because typically the new allocation would end up in there once a new
thread was spinning up.

Now we change behaviour, Arm64Emitter doesn't do any buffer management
itself, instead just passing an initial buffer on to its internal buffer
tracking if given one up front.

This leaves the Dispatcher and the Arm64JITCore to do their buffer
management and ensuring there is no double free.

The day is saved!
2023-11-05 19:18:40 -08:00
Ryan Houdek 5103f2d92b Merge pull request #3247 from alyssarosenzweig/refactor/nzcv-prereq
Preparatory patches for nzcv
2023-11-01 14:07:14 -07:00
Alyssa Rosenzweig d4a6b031ea Merge pull request #3245 from Sonicadvance1/remove_gdbpausecheck
FEXCore: Removes gdb pause check handler
2023-11-01 15:46:40 -04:00
Alyssa Rosenzweig 319cf4bf3d Arm64: Preserve flags in ExitFunction
Mostly harmless (except for fusion on cortexes), prepares us for nzcv work.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
2023-11-01 15:44:36 -04:00
Ryan Houdek e4d9c264d8 IR: Adds support for tbx 2023-10-31 20:06:45 -07:00
Mai 77d92872bc Merge pull request #3212 from Sonicadvance1/dpp_opt
OpcodeDispatcher: Optimize 128-bit DPPS and DPPD
2023-11-01 04:01:05 +01:00
Ryan Houdek 460f13be71 FEXCore: Removes gdb pause check handler
gdbserver is currently entirely broken so this doesn't change behaviour.
The gdb pause check that we originally had an excessive amount of
overhead.
Instead use the pending interrupt fault check that was wired
up for wine.
This makes the check very lightweight and makes it more reasonable to
implement a way to have gdbserver support attaching to a process.
2023-10-31 18:40:00 -07:00
Alyssa Rosenzweig 5b70209728 Merge pull request #3233 from Sonicadvance1/print_vixl
JIT: Implements Print support for vixl sim
2023-10-29 07:32:32 -04:00
Alyssa Rosenzweig 8181e53727 Merge pull request #3234 from Sonicadvance1/minor_bfxil
Arm64: Minor optimization to bfxil and bfi
2023-10-27 08:00:28 -04:00
Ryan Houdek 61f22911c7 Arm64: Minor optimization to bfxil and bfi
When the destination doesn't alias the source, we can remove a final mov
from both of these operations.

Does some minor code improvement.
2023-10-26 20:25:44 -07:00
Ryan Houdek fe8778bb96 JIT: Implements Print support for vixl sim
Everytime I want to quickly output a value for testing I tend to use
Print which didn't work under the simulator.
Give this a quick fix to wire up the jump to the vixl sim.
2023-10-26 18:34:47 -07:00
Ryan Houdek 14e5ea1e22 Merge pull request #3230 from Sonicadvance1/optimize_atomic_fetch
IR: Optimize unused result atomic fetch mop to just atomic mop
2023-10-26 15:57:20 -07:00
Ryan Houdek 8f0461cac8 IR: Adds support for non-fetch Atomci CLR and NEG 2023-10-25 21:00:04 -07:00
Ryan Houdek 20a54913bd IR: Support shifted imms in VectorImm
We will want to use this in some cases.
2023-10-25 19:27:00 -07:00
Ryan Houdek 99465faf63 IR: Implements support for subtract with shifted register
Will be used soon.
2023-10-23 09:27:41 -07:00
Alyssa Rosenzweig 42259974c4 Arm64: Preserve NZCV in VInsertElement
So we don't need to mark VInsertElement as implicit clobber in the common case.
Only afects sve256 which doesn't exist yet.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
2023-10-23 10:21:34 -04:00
Ryan Houdek d5beba9423 JITArm64: Fixes bug in rpres scalar operations
Noticed this during code investigation, these two operations were
swapped.

Would have caused issues if anything supported RPRES today.
2023-10-21 15:24:43 -07:00
Ryan Houdek 165d3d3d4d Arm64JIT: Fixes VDupElement so it respects 64-bit vector duping
In some cases when we want the upper bits to be zero, this is the
desired behaviour
2023-10-20 18:15:43 +02:00
Ryan Houdek 2c0bc0654d IR: Adds new VFAddV operation
SVE added this instruction natively, we can take advantage of it on
SVE-128bit systems which is quite nice.

Will be used soon.
2023-10-19 16:38:11 +02:00
Lioncache d84577c36c VectorOps: Handle SVE VExtr a little better
If the source registers don't alias the destination, then we can
safely move the lower bits over to it without using a temporary.
2023-10-19 15:11:23 +02:00
Lioncache 24f2796141 VectorOps: Handle SVE VFCADD a little better
If no registers alias, then we can move the first source directly into the
destination and then perform the FCADD operation as opposed to using a
temporary.
2023-10-19 14:48:46 +02:00
Lioncache 1f6c6345d9 VectorOps: Handle SVE VURAvg a little better
We can perform less moves by checking for scenarios where aliasing
occurs. Since addition is commutative (usually, general-case anyway),
order of inputs doesn't strictly matter here.
2023-10-19 12:14:12 +02:00
Lioncache 3d23cd5765 VectorOps: Handle SVE VFDiv a little better
In the event no source vectors alias the destination,
we can just move the first source vector into it and
then perform the divide without needing to move afterword.
2023-10-19 11:45:35 +02:00
Lioncache 39e658f02a VectorOps: Handle more VUMin SVE cases better
We can avoid needing to use movprfx here by moving
directly into the destination when possible and just
doing the UMIN directly
2023-10-18 18:48:13 +02:00
Lioncache e89dd27f2a VectorOps: Handle more VSMin SVE cases better
We can avoid needing to use movprfx here by moving
directly into the destination when possible and just
doing the SMIN directly.
2023-10-18 18:48:13 +02:00
Lioncache f85fae0041 VectorOps: Handle more VUMax SVE cases better
We can avoid needing to use movprfx here by moving
directly into the destination when possible and just
doing the UMAX directly.

Also expands the unsigned max tests to test values with
the sign bit set to ensure all behavior is caught.
2023-10-18 18:48:12 +02:00
Lioncache 65eec673fc VectorOps: Handle more VSMax SVE cases better
Since SMAX performs a comparison and returns the max value regardless
of how the operands are provided, we can check for when the second
input aliases the destination.
2023-10-18 18:48:03 +02:00
Lioncache 47a0f14537 OpcodeDispatcher: Remove unnecessary 128-bit truncating moves from StoreResult
Removes the truncating move that we perform inside the StoreResult
function and instead delegates the responsibility to the instruction
implementations themselves.

This removes a lot of redundant moves that occur on 128-bit variants
of AVX instructions.

Also fixes a weird case where we were handling 128-bit SVE
in VBroadcastFromMem when we already have AdvSIMD instructions
that will perfom the zero-extension behavior for us.
2023-10-17 11:07:04 +02:00
Ryan Houdek 2671246fef IR: Adds scalar vector insert operations
These IR operations are required to support AFP's NEP mode which does
vector insert in to the destination register. Additionally it gives us
tracking information to allow optimizing out redundant inserts on
devices that don't support AFP natively.

In order to match x86 semantics we need to support binary and unary
scalar operations that do a final insert in to a vector. With optional
zeroing of the top 128-bits for AVX variants.

A tricky thing is that in binary operations this means that the
destination and first source have an intrinsically linked property
depending on if it is SSE or AVX.

SSE example:
- addss xmm0, xmm1
   - xmm0 is both the destination and the first source.
   - This means xmm0[31:0] = xmm0[31:0] + xmm1[31:0]
   - Bits [127:32] are UNMODIFIED.

FEX's JIT jumps through some hoops so that if the destination register
equals the first source register, then it hits the optimal path the
AFP.NEP will insert in to the result. AVX throws a small wrench in to
this due to changed behaviour

AVX example:
- vaddss xmm0, xmm1, xmm2
  - xmm0 is ONLY the destination, xmm1 and xmm2 are the sources
  - This operation copies the bits above the scalar result from the
    first source (xmm1).
  - Additionally this will zero bits above the original 128-bit xmm
    register.
  - xmm0[31:0] = xmm1[31:0] + xmm2[31:0]
  - xmm0[127:32] = xmm1[127:32]
  - ymm0[255:127] = 0

This causes these instructions to support a fairly large table depending
on if the instruction is an SSE or AVX instruction, plus if the host CPU
supports AFP or not.

So while fairly complex, it's handling all the edge cases and gives us
optimization opportunities as we move forward. Currently on non-AFP
supporting devices this has a minor benefit that these IR operations
remove one temporary register, lowering the Register Allocation
overhead.

In the coming weeks I am likely to introduce an optimization pass that
removes redundant inserts because FEX currently does /really/ badly with
scalar code loops.

Needs #3184 merged first.
2023-10-10 03:17:19 -07:00
Ryan Houdek 252d7712ea Arm64: Save if the host supports AFP 2023-10-10 03:17:18 -07:00
Ryan Houdek a1a479e69f FEXCore: Removes a warning about assume discarding side-effects 2023-10-09 16:04:57 -07:00
Ryan Houdek 22590dde77 FEXCore: Implements support for RPRES
This allows us to use reciprocal instructions which matches precision of
what x86 expects rather than converting everything to float divides.

Currently no hardware supports this, and even the upcoming X4/A720/A520
won't support it, but it was trivial to implement so wire it up.
2023-10-07 23:13:47 -07:00
Ryan Houdek 4cff3e5f1f FEXCore/IR: Changes over to automated IR dispatch generation
Suggested by Alyssa. Adding an IR operation can be a little tedious
since you need to add the definition to JIT.cpp for the dispatch switch,
JITClass.h for the function declared, and then actually defining the
implementation in the correct file.

Instead support the common case where an IR operation just gets
dispatched through to the regular handler. This lets the developer just
put the function definition in to the json and the relevent cpp file and
it just gets picked up.

Some minor things:
- Needs to support dynamic dispatch for {Load,Store}Register and
  {Load,Store}Mem
   - This is just a bool in the json
- It needs to not output JIT dispatch for some IR operations
   - SSE4.2 string instructions and x87 operations
   - These go down the "Unhandled" path
- Needs to support a Dispatcher function override
   - This is just for handling NoOp IR operations that get used for
     other reasons.
- Finally removes VSMul and VUMul, consolidating to VMul
   - Unlike V{U,S}Mull, signed or unsigned doesn't change behaviour here
- Fixed a couple random handler names not matching the IR operation
  name.
2023-10-07 15:01:47 -07:00