RFR: 8288467: C2: assert(cisc->memory_operand() == nullptr) failed: no memory operand, only stack
Emanuel Peter
epeter at openjdk.org
Fri Jun 17 09:48:53 UTC 2022
In [JDK-8282555](https://bugs.openjdk.org/browse/JDK-8282555) I added this assert, because on x64 this seems to always hold. But it turns out there are instructions on x86 (32bit) that violate this assumption.
**Why it holds on x64**
It seems we only ever do one read or one write per instruction. Instructions with multiple memory operands are extremely rare.
1. we spill from register to memory: we land in the if case, where the cisc node has an additional input slot for the memory edge.
2. we spill from register to stackSlot: no additional input slot is reserved, we land in else case and add an additional precedence edge.
**Why it is violated on x86 (32bit)**
We have additional cases that land in the else case. For example spilling `src1` from `addFPR24_reg_mem` to `addFPR24_mem_cisc`.
https://urldefense.com/v3/__https://github.com/openjdk/jdk19/blob/53bf1bfdabb79b37afedd09051d057f9eea620f2/src/hotspot/cpu/x86/x86_32.ad*L10325-L10327__;Iw!!ACWV5N9M2RV99hQ!OECebibs9mV50VnvBHuYVR53yehF_LYezwUObWXbuXoUlSCzPdEdTefOaDzLFYjc5g6Ern-O97qbm8DA5kYd3M1QUkKdvQ$ https://urldefense.com/v3/__https://github.com/openjdk/jdk19/blob/53bf1bfdabb79b37afedd09051d057f9eea620f2/src/hotspot/cpu/x86/x86_32.ad*L10368-L10370__;Iw!!ACWV5N9M2RV99hQ!OECebibs9mV50VnvBHuYVR53yehF_LYezwUObWXbuXoUlSCzPdEdTefOaDzLFYjc5g6Ern-O97qbm8DA5kYd3M2yf79Lyw$
We land in the else case, because both have 2 inputs, thus `oper_input_base() == 2`.
And both have memory operands, so the assert must fail.
**Solutions**
1. Remove the Assert, as it is incorrect.
2. Extend the assert to be correct.
- case 1: reg to mem spill, where we have a reserved input slot in cisc for memory edge
- case 2: reg to stackSlot spill, where both mach and cisc have no memory operand.
- other cases, with various register, stackSlot and memory inputs and outputs. We would have to find a general rule, and test it properly, which is not trivial because getting registers to spill is not easy to precisely provoke.
3. Have platform dependent asserts. But also this makes testing harder.
For now I went with 1. as it is simple and as far as I can see correct.
Running tests on x64 (should not fail). **I need someone to help me with testing x86 (32bit)**. I only verified the reported test failure with a 32bit build.
-------------
Commit messages:
- 8288467: C2: assert(cisc->memory_operand() == nullptr) failed: no memory operand, only stack
Changes: https://git.openjdk.org/jdk19/pull/33/files
Webrev: https://webrevs.openjdk.org/?repo=jdk19&pr=33&range=00
Issue: https://bugs.openjdk.org/browse/JDK-8288467
Stats: 7 lines in 1 file changed: 5 ins; 0 del; 2 mod
Patch: https://git.openjdk.org/jdk19/pull/33.diff
Fetch: git fetch https://git.openjdk.org/jdk19 pull/33/head:pull/33
PR: https://git.openjdk.org/jdk19/pull/33
More information about the hotspot-compiler-dev
mailing list