mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-16 17:14:41 +02:00
8291000: C2: Purge LoadPLocked and Store*Conditional nodes
Reviewed-by: eosterlund, kvn
This commit is contained in:
parent
07f0612c9a
commit
dd69a68d09
17 changed files with 4 additions and 556 deletions
|
@ -9230,103 +9230,6 @@ instruct castVVMask(pRegGov dst)
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Atomic operation instructions
|
// Atomic operation instructions
|
||||||
//
|
//
|
||||||
// Intel and SPARC both implement Ideal Node LoadPLocked and
|
|
||||||
// Store{PIL}Conditional instructions using a normal load for the
|
|
||||||
// LoadPLocked and a CAS for the Store{PIL}Conditional.
|
|
||||||
//
|
|
||||||
// The ideal code appears only to use LoadPLocked/StorePLocked as a
|
|
||||||
// pair to lock object allocations from Eden space when not using
|
|
||||||
// TLABs.
|
|
||||||
//
|
|
||||||
// There does not appear to be a Load{IL}Locked Ideal Node and the
|
|
||||||
// Ideal code appears to use Store{IL}Conditional as an alias for CAS
|
|
||||||
// and to use StoreIConditional only for 32-bit and StoreLConditional
|
|
||||||
// only for 64-bit.
|
|
||||||
//
|
|
||||||
// We implement LoadPLocked and StorePLocked instructions using,
|
|
||||||
// respectively the AArch64 hw load-exclusive and store-conditional
|
|
||||||
// instructions. Whereas we must implement each of
|
|
||||||
// Store{IL}Conditional using a CAS which employs a pair of
|
|
||||||
// instructions comprising a load-exclusive followed by a
|
|
||||||
// store-conditional.
|
|
||||||
|
|
||||||
|
|
||||||
// Locked-load (linked load) of the current heap-top
|
|
||||||
// used when updating the eden heap top
|
|
||||||
// implemented using ldaxr on AArch64
|
|
||||||
|
|
||||||
instruct loadPLocked(iRegPNoSp dst, indirect mem)
|
|
||||||
%{
|
|
||||||
match(Set dst (LoadPLocked mem));
|
|
||||||
|
|
||||||
ins_cost(VOLATILE_REF_COST);
|
|
||||||
|
|
||||||
format %{ "ldaxr $dst, $mem\t# ptr linked acquire" %}
|
|
||||||
|
|
||||||
ins_encode(aarch64_enc_ldaxr(dst, mem));
|
|
||||||
|
|
||||||
ins_pipe(pipe_serial);
|
|
||||||
%}
|
|
||||||
|
|
||||||
// Conditional-store of the updated heap-top.
|
|
||||||
// Used during allocation of the shared heap.
|
|
||||||
// Sets flag (EQ) on success.
|
|
||||||
// implemented using stlxr on AArch64.
|
|
||||||
|
|
||||||
instruct storePConditional(memory8 heap_top_ptr, iRegP oldval, iRegP newval, rFlagsReg cr)
|
|
||||||
%{
|
|
||||||
match(Set cr (StorePConditional heap_top_ptr (Binary oldval newval)));
|
|
||||||
|
|
||||||
ins_cost(VOLATILE_REF_COST);
|
|
||||||
|
|
||||||
// TODO
|
|
||||||
// do we need to do a store-conditional release or can we just use a
|
|
||||||
// plain store-conditional?
|
|
||||||
|
|
||||||
format %{
|
|
||||||
"stlxr rscratch1, $newval, $heap_top_ptr\t# ptr cond release"
|
|
||||||
"cmpw rscratch1, zr\t# EQ on successful write"
|
|
||||||
%}
|
|
||||||
|
|
||||||
ins_encode(aarch64_enc_stlxr(newval, heap_top_ptr));
|
|
||||||
|
|
||||||
ins_pipe(pipe_serial);
|
|
||||||
%}
|
|
||||||
|
|
||||||
instruct storeLConditional(indirect mem, iRegLNoSp oldval, iRegLNoSp newval, rFlagsReg cr)
|
|
||||||
%{
|
|
||||||
match(Set cr (StoreLConditional mem (Binary oldval newval)));
|
|
||||||
|
|
||||||
ins_cost(VOLATILE_REF_COST);
|
|
||||||
|
|
||||||
format %{
|
|
||||||
"cmpxchg rscratch1, $mem, $oldval, $newval, $mem\t# if $mem == $oldval then $mem <-- $newval"
|
|
||||||
"cmpw rscratch1, zr\t# EQ on successful write"
|
|
||||||
%}
|
|
||||||
|
|
||||||
ins_encode(aarch64_enc_cmpxchg_acq(mem, oldval, newval));
|
|
||||||
|
|
||||||
ins_pipe(pipe_slow);
|
|
||||||
%}
|
|
||||||
|
|
||||||
// storeIConditional also has acquire semantics, for no better reason
|
|
||||||
// than matching storeLConditional. At the time of writing this
|
|
||||||
// comment storeIConditional was not used anywhere by AArch64.
|
|
||||||
instruct storeIConditional(indirect mem, iRegINoSp oldval, iRegINoSp newval, rFlagsReg cr)
|
|
||||||
%{
|
|
||||||
match(Set cr (StoreIConditional mem (Binary oldval newval)));
|
|
||||||
|
|
||||||
ins_cost(VOLATILE_REF_COST);
|
|
||||||
|
|
||||||
format %{
|
|
||||||
"cmpxchgw rscratch1, $mem, $oldval, $newval, $mem\t# if $mem == $oldval then $mem <-- $newval"
|
|
||||||
"cmpw rscratch1, zr\t# EQ on successful write"
|
|
||||||
%}
|
|
||||||
|
|
||||||
ins_encode(aarch64_enc_cmpxchgw_acq(mem, oldval, newval));
|
|
||||||
|
|
||||||
ins_pipe(pipe_slow);
|
|
||||||
%}
|
|
||||||
|
|
||||||
// standard CompareAndSwapX when we are using barriers
|
// standard CompareAndSwapX when we are using barriers
|
||||||
// these have higher priority than the rules selected by a predicate
|
// these have higher priority than the rules selected by a predicate
|
||||||
|
|
|
@ -5430,63 +5430,6 @@ instruct addL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con, flagsReg ccr) %{
|
||||||
ins_pipe(ialu_reg_imm);
|
ins_pipe(ialu_reg_imm);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
//----------Conditional_store--------------------------------------------------
|
|
||||||
// Conditional-store of the updated heap-top.
|
|
||||||
// Used during allocation of the shared heap.
|
|
||||||
// Sets flags (EQ) on success.
|
|
||||||
|
|
||||||
// LoadP-locked.
|
|
||||||
instruct loadPLocked(iRegP dst, memoryex mem) %{
|
|
||||||
match(Set dst (LoadPLocked mem));
|
|
||||||
size(4);
|
|
||||||
format %{ "LDREX $dst,$mem" %}
|
|
||||||
ins_encode %{
|
|
||||||
__ ldrex($dst$$Register,$mem$$Address);
|
|
||||||
%}
|
|
||||||
ins_pipe(iload_mem);
|
|
||||||
%}
|
|
||||||
|
|
||||||
instruct storePConditional( memoryex heap_top_ptr, iRegP oldval, iRegP newval, iRegI tmp, flagsRegP pcc ) %{
|
|
||||||
predicate(_kids[1]->_kids[0]->_leaf->Opcode() == Op_LoadPLocked); // only works in conjunction with a LoadPLocked node
|
|
||||||
match(Set pcc (StorePConditional heap_top_ptr (Binary oldval newval)));
|
|
||||||
effect( TEMP tmp );
|
|
||||||
size(8);
|
|
||||||
format %{ "STREX $tmp,$newval,$heap_top_ptr\n\t"
|
|
||||||
"CMP $tmp, 0" %}
|
|
||||||
ins_encode %{
|
|
||||||
__ strex($tmp$$Register, $newval$$Register, $heap_top_ptr$$Address);
|
|
||||||
__ cmp($tmp$$Register, 0);
|
|
||||||
%}
|
|
||||||
ins_pipe( long_memory_op );
|
|
||||||
%}
|
|
||||||
|
|
||||||
// Conditional-store of an intx value.
|
|
||||||
instruct storeXConditional( memoryex mem, iRegX oldval, iRegX newval, iRegX tmp, flagsReg icc ) %{
|
|
||||||
match(Set icc (StoreIConditional mem (Binary oldval newval)));
|
|
||||||
effect( TEMP tmp );
|
|
||||||
size(28);
|
|
||||||
format %{ "loop: \n\t"
|
|
||||||
"LDREX $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem], DOESN'T set $newval=[$mem] in any case\n\t"
|
|
||||||
"XORS $tmp,$tmp, $oldval\n\t"
|
|
||||||
"STREX.eq $tmp, $newval, $mem\n\t"
|
|
||||||
"CMP.eq $tmp, 1 \n\t"
|
|
||||||
"B.eq loop \n\t"
|
|
||||||
"TEQ $tmp, 0\n\t"
|
|
||||||
"membar LoadStore|LoadLoad" %}
|
|
||||||
ins_encode %{
|
|
||||||
Label loop;
|
|
||||||
__ bind(loop);
|
|
||||||
__ ldrex($tmp$$Register, $mem$$Address);
|
|
||||||
__ eors($tmp$$Register, $tmp$$Register, $oldval$$Register);
|
|
||||||
__ strex($tmp$$Register, $newval$$Register, $mem$$Address, eq);
|
|
||||||
__ cmp($tmp$$Register, 1, eq);
|
|
||||||
__ b(loop, eq);
|
|
||||||
__ teq($tmp$$Register, 0);
|
|
||||||
__ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::LoadStore | MacroAssembler::LoadLoad), noreg);
|
|
||||||
%}
|
|
||||||
ins_pipe( long_memory_op );
|
|
||||||
%}
|
|
||||||
|
|
||||||
// No flag versions for CompareAndSwap{P,I,L} because matcher can't match them
|
// No flag versions for CompareAndSwap{P,I,L} because matcher can't match them
|
||||||
|
|
||||||
instruct compareAndSwapL_bool(memoryex mem, iRegL oldval, iRegLd newval, iRegI res, iRegLd tmp, flagsReg ccr ) %{
|
instruct compareAndSwapL_bool(memoryex mem, iRegL oldval, iRegLd newval, iRegI res, iRegLd tmp, flagsReg ccr ) %{
|
||||||
|
|
|
@ -7453,62 +7453,6 @@ instruct cmovD_reg(cmpOp cmp, flagsRegSrc crx, regD dst, regD src) %{
|
||||||
ins_pipe(pipe_class_default);
|
ins_pipe(pipe_class_default);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
//----------Conditional_store--------------------------------------------------
|
|
||||||
// Conditional-store of the updated heap-top.
|
|
||||||
// Used during allocation of the shared heap.
|
|
||||||
// Sets flags (EQ) on success. Implemented with a CASA on Sparc.
|
|
||||||
|
|
||||||
// As compareAndSwapL, but return flag register instead of boolean value in
|
|
||||||
// int register.
|
|
||||||
// Used by sun/misc/AtomicLongCSImpl.java.
|
|
||||||
// Mem_ptr must be a memory operand, else this node does not get
|
|
||||||
// Flag_needs_anti_dependence_check set by adlc. If this is not set this node
|
|
||||||
// can be rematerialized which leads to errors.
|
|
||||||
instruct storeLConditional_regP_regL_regL(flagsReg crx, indirect mem_ptr, iRegLsrc oldVal, iRegLsrc newVal, flagsRegCR0 cr0) %{
|
|
||||||
match(Set crx (StoreLConditional mem_ptr (Binary oldVal newVal)));
|
|
||||||
effect(TEMP cr0);
|
|
||||||
format %{ "CMPXCHGD if ($crx = ($oldVal == *$mem_ptr)) *mem_ptr = $newVal; as bool" %}
|
|
||||||
ins_encode %{
|
|
||||||
__ cmpxchgd($crx$$CondRegister, R0, $oldVal$$Register, $newVal$$Register, $mem_ptr$$Register,
|
|
||||||
MacroAssembler::MemBarAcq, MacroAssembler::cmpxchgx_hint_atomic_update(),
|
|
||||||
noreg, NULL, true);
|
|
||||||
%}
|
|
||||||
ins_pipe(pipe_class_default);
|
|
||||||
%}
|
|
||||||
|
|
||||||
// As compareAndSwapP, but return flag register instead of boolean value in
|
|
||||||
// int register.
|
|
||||||
// This instruction is matched if UseTLAB is off.
|
|
||||||
// Mem_ptr must be a memory operand, else this node does not get
|
|
||||||
// Flag_needs_anti_dependence_check set by adlc. If this is not set this node
|
|
||||||
// can be rematerialized which leads to errors.
|
|
||||||
instruct storePConditional_regP_regP_regP(flagsRegCR0 cr0, indirect mem_ptr, iRegPsrc oldVal, iRegPsrc newVal) %{
|
|
||||||
match(Set cr0 (StorePConditional mem_ptr (Binary oldVal newVal)));
|
|
||||||
ins_cost(2*MEMORY_REF_COST);
|
|
||||||
predicate(n->as_LoadStore()->barrier_data() == 0);
|
|
||||||
|
|
||||||
format %{ "STDCX_ if ($cr0 = ($oldVal == *$mem_ptr)) *mem_ptr = $newVal; as bool" %}
|
|
||||||
ins_encode %{
|
|
||||||
__ stdcx_($newVal$$Register, $mem_ptr$$Register);
|
|
||||||
%}
|
|
||||||
ins_pipe(pipe_class_memory);
|
|
||||||
%}
|
|
||||||
|
|
||||||
// Implement LoadPLocked. Must be ordered against changes of the memory location
|
|
||||||
// by storePConditional.
|
|
||||||
// Don't know whether this is ever used.
|
|
||||||
instruct loadPLocked(iRegPdst dst, memory mem) %{
|
|
||||||
match(Set dst (LoadPLocked mem));
|
|
||||||
ins_cost(2*MEMORY_REF_COST);
|
|
||||||
|
|
||||||
format %{ "LDARX $dst, $mem \t// loadPLocked\n\t" %}
|
|
||||||
size(4);
|
|
||||||
ins_encode %{
|
|
||||||
__ ldarx($dst$$Register, $mem$$Register, MacroAssembler::cmpxchgx_hint_atomic_update());
|
|
||||||
%}
|
|
||||||
ins_pipe(pipe_class_memory);
|
|
||||||
%}
|
|
||||||
|
|
||||||
//----------Compare-And-Swap---------------------------------------------------
|
//----------Compare-And-Swap---------------------------------------------------
|
||||||
|
|
||||||
// CompareAndSwap{P,I,L} have more than one output, therefore "CmpI
|
// CompareAndSwap{P,I,L} have more than one output, therefore "CmpI
|
||||||
|
|
|
@ -5134,108 +5134,6 @@ instruct storeNKlass(iRegN src, memory mem)
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Atomic operation instructions
|
// Atomic operation instructions
|
||||||
//
|
//
|
||||||
// Intel and SPARC both implement Ideal Node LoadPLocked and
|
|
||||||
// Store{PIL}Conditional instructions using a normal load for the
|
|
||||||
// LoadPLocked and a CAS for the Store{PIL}Conditional.
|
|
||||||
//
|
|
||||||
// The ideal code appears only to use LoadPLocked/storePConditional as a
|
|
||||||
// pair to lock object allocations from Eden space when not using
|
|
||||||
// TLABs.
|
|
||||||
//
|
|
||||||
// There does not appear to be a Load{IL}Locked Ideal Node and the
|
|
||||||
// Ideal code appears to use Store{IL}Conditional as an alias for CAS
|
|
||||||
// and to use StoreIConditional only for 32-bit and StoreLConditional
|
|
||||||
// only for 64-bit.
|
|
||||||
//
|
|
||||||
// We implement LoadPLocked and storePConditional instructions using,
|
|
||||||
// respectively the RISCV hw load-reserve and store-conditional
|
|
||||||
// instructions. Whereas we must implement each of
|
|
||||||
// Store{IL}Conditional using a CAS which employs a pair of
|
|
||||||
// instructions comprising a load-reserve followed by a
|
|
||||||
// store-conditional.
|
|
||||||
|
|
||||||
|
|
||||||
// Locked-load (load reserved) of the current heap-top
|
|
||||||
// used when updating the eden heap top
|
|
||||||
// implemented using lr_d on RISCV64
|
|
||||||
instruct loadPLocked(iRegPNoSp dst, indirect mem)
|
|
||||||
%{
|
|
||||||
match(Set dst (LoadPLocked mem));
|
|
||||||
|
|
||||||
ins_cost(ALU_COST * 2 + LOAD_COST);
|
|
||||||
|
|
||||||
format %{ "lr.d $dst, $mem\t# ptr load reserved, #@loadPLocked" %}
|
|
||||||
|
|
||||||
ins_encode %{
|
|
||||||
__ la(t0, Address(as_Register($mem$$base), $mem$$disp));
|
|
||||||
__ lr_d($dst$$Register, t0, Assembler::aq);
|
|
||||||
%}
|
|
||||||
|
|
||||||
ins_pipe(pipe_serial);
|
|
||||||
%}
|
|
||||||
|
|
||||||
// Conditional-store of the updated heap-top.
|
|
||||||
// Used during allocation of the shared heap.
|
|
||||||
// implemented using sc_d on RISCV64.
|
|
||||||
instruct storePConditional(memory heap_top_ptr, iRegP oldval, iRegP newval, rFlagsReg cr)
|
|
||||||
%{
|
|
||||||
match(Set cr (StorePConditional heap_top_ptr (Binary oldval newval)));
|
|
||||||
|
|
||||||
ins_cost(ALU_COST * 2 + STORE_COST);
|
|
||||||
|
|
||||||
format %{
|
|
||||||
"sc_d t1, $newval $heap_top_ptr,\t# ptr store conditional, #@storePConditional"
|
|
||||||
%}
|
|
||||||
|
|
||||||
ins_encode %{
|
|
||||||
__ la(t0, Address(as_Register($heap_top_ptr$$base), $heap_top_ptr$$disp));
|
|
||||||
__ sc_d($cr$$Register, $newval$$Register, t0, Assembler::rl);
|
|
||||||
%}
|
|
||||||
|
|
||||||
ins_pipe(pipe_serial);
|
|
||||||
%}
|
|
||||||
|
|
||||||
instruct storeLConditional(indirect mem, iRegL oldval, iRegL newval, rFlagsReg cr)
|
|
||||||
%{
|
|
||||||
match(Set cr (StoreLConditional mem (Binary oldval newval)));
|
|
||||||
|
|
||||||
ins_cost(LOAD_COST + STORE_COST + 2 * BRANCH_COST);
|
|
||||||
|
|
||||||
format %{
|
|
||||||
"cmpxchg t1, $mem, $oldval, $newval, $mem\t# if $mem == $oldval then $mem <-- $newval"
|
|
||||||
"xorr $cr, $cr, $oldval\t# $cr == 0 on successful write, #@storeLConditional"
|
|
||||||
%}
|
|
||||||
|
|
||||||
ins_encode %{
|
|
||||||
__ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int64,
|
|
||||||
/*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $cr$$Register);
|
|
||||||
__ xorr($cr$$Register,$cr$$Register, $oldval$$Register);
|
|
||||||
%}
|
|
||||||
|
|
||||||
ins_pipe(pipe_slow);
|
|
||||||
%}
|
|
||||||
|
|
||||||
// storeIConditional also has acquire semantics, for no better reason
|
|
||||||
// than matching storeLConditional.
|
|
||||||
instruct storeIConditional(indirect mem, iRegI oldval, iRegI newval, rFlagsReg cr)
|
|
||||||
%{
|
|
||||||
match(Set cr (StoreIConditional mem (Binary oldval newval)));
|
|
||||||
|
|
||||||
ins_cost(LOAD_COST + STORE_COST + BRANCH_COST * 2);
|
|
||||||
|
|
||||||
format %{
|
|
||||||
"cmpxchgw t1, $mem, $oldval, $newval, $mem\t# if $mem == $oldval then $mem <-- $newval"
|
|
||||||
"xorr $cr, $cr, $oldval\t# $cr == 0 on successful write, #@storeIConditional"
|
|
||||||
%}
|
|
||||||
|
|
||||||
ins_encode %{
|
|
||||||
__ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int32,
|
|
||||||
/*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $cr$$Register);
|
|
||||||
__ xorr($cr$$Register,$cr$$Register, $oldval$$Register);
|
|
||||||
%}
|
|
||||||
|
|
||||||
ins_pipe(pipe_slow);
|
|
||||||
%}
|
|
||||||
|
|
||||||
// standard CompareAndSwapX when we are using barriers
|
// standard CompareAndSwapX when we are using barriers
|
||||||
// these have higher priority than the rules selected by a predicate
|
// these have higher priority than the rules selected by a predicate
|
||||||
|
|
|
@ -5290,54 +5290,6 @@ instruct castVV(iRegL dst) %{
|
||||||
ins_pipe(pipe_class_dummy);
|
ins_pipe(pipe_class_dummy);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
//----------Conditional_store--------------------------------------------------
|
|
||||||
// Conditional-store of the updated heap-top.
|
|
||||||
// Used during allocation of the shared heap.
|
|
||||||
// Sets flags (EQ) on success.
|
|
||||||
|
|
||||||
// Implement LoadPLocked. Must be ordered against changes of the memory location
|
|
||||||
// by storePConditional.
|
|
||||||
// Don't know whether this is ever used.
|
|
||||||
instruct loadPLocked(iRegP dst, memory mem) %{
|
|
||||||
match(Set dst (LoadPLocked mem));
|
|
||||||
ins_cost(MEMORY_REF_COST);
|
|
||||||
size(Z_DISP3_SIZE);
|
|
||||||
format %{ "LG $dst,$mem\t # LoadPLocked" %}
|
|
||||||
opcode(LG_ZOPC, LG_ZOPC);
|
|
||||||
ins_encode(z_form_rt_mem_opt(dst, mem));
|
|
||||||
ins_pipe(pipe_class_dummy);
|
|
||||||
%}
|
|
||||||
|
|
||||||
// As compareAndSwapP, but return flag register instead of boolean value in
|
|
||||||
// int register.
|
|
||||||
// This instruction is matched if UseTLAB is off. Needed to pass
|
|
||||||
// option tests. Mem_ptr must be a memory operand, else this node
|
|
||||||
// does not get Flag_needs_anti_dependence_check set by adlc. If this
|
|
||||||
// is not set this node can be rematerialized which leads to errors.
|
|
||||||
instruct storePConditional(indirect mem_ptr, rarg5RegP oldval, iRegP_N2P newval, flagsReg cr) %{
|
|
||||||
match(Set cr (StorePConditional mem_ptr (Binary oldval newval)));
|
|
||||||
effect(KILL oldval);
|
|
||||||
// TODO: s390 port size(FIXED_SIZE);
|
|
||||||
format %{ "storePConditional $oldval,$newval,$mem_ptr" %}
|
|
||||||
ins_encode(z_enc_casL(oldval, newval, mem_ptr));
|
|
||||||
ins_pipe(pipe_class_dummy);
|
|
||||||
%}
|
|
||||||
|
|
||||||
// As compareAndSwapL, but return flag register instead of boolean value in
|
|
||||||
// int register.
|
|
||||||
// Used by sun/misc/AtomicLongCSImpl.java. Mem_ptr must be a memory
|
|
||||||
// operand, else this node does not get
|
|
||||||
// Flag_needs_anti_dependence_check set by adlc. If this is not set
|
|
||||||
// this node can be rematerialized which leads to errors.
|
|
||||||
instruct storeLConditional(indirect mem_ptr, rarg5RegL oldval, iRegL newval, flagsReg cr) %{
|
|
||||||
match(Set cr (StoreLConditional mem_ptr (Binary oldval newval)));
|
|
||||||
effect(KILL oldval);
|
|
||||||
// TODO: s390 port size(FIXED_SIZE);
|
|
||||||
format %{ "storePConditional $oldval,$newval,$mem_ptr" %}
|
|
||||||
ins_encode(z_enc_casL(oldval, newval, mem_ptr));
|
|
||||||
ins_pipe(pipe_class_dummy);
|
|
||||||
%}
|
|
||||||
|
|
||||||
// No flag versions for CompareAndSwap{P,I,L,N} because matcher can't match them.
|
// No flag versions for CompareAndSwap{P,I,L,N} because matcher can't match them.
|
||||||
|
|
||||||
instruct compareAndSwapI_bool(iRegP mem_ptr, rarg5RegI oldval, iRegI newval, iRegI res, flagsReg cr) %{
|
instruct compareAndSwapI_bool(iRegP mem_ptr, rarg5RegI oldval, iRegI newval, iRegI res, flagsReg cr) %{
|
||||||
|
|
|
@ -7257,61 +7257,6 @@ instruct castDD_PR( regDPR dst ) %{
|
||||||
ins_pipe( empty );
|
ins_pipe( empty );
|
||||||
%}
|
%}
|
||||||
|
|
||||||
// Load-locked - same as a regular pointer load when used with compare-swap
|
|
||||||
instruct loadPLocked(eRegP dst, memory mem) %{
|
|
||||||
match(Set dst (LoadPLocked mem));
|
|
||||||
|
|
||||||
ins_cost(125);
|
|
||||||
format %{ "MOV $dst,$mem\t# Load ptr. locked" %}
|
|
||||||
opcode(0x8B);
|
|
||||||
ins_encode( OpcP, RegMem(dst,mem));
|
|
||||||
ins_pipe( ialu_reg_mem );
|
|
||||||
%}
|
|
||||||
|
|
||||||
// Conditional-store of the updated heap-top.
|
|
||||||
// Used during allocation of the shared heap.
|
|
||||||
// Sets flags (EQ) on success. Implemented with a CMPXCHG on Intel.
|
|
||||||
instruct storePConditional( memory heap_top_ptr, eAXRegP oldval, eRegP newval, eFlagsReg cr ) %{
|
|
||||||
match(Set cr (StorePConditional heap_top_ptr (Binary oldval newval)));
|
|
||||||
// EAX is killed if there is contention, but then it's also unused.
|
|
||||||
// In the common case of no contention, EAX holds the new oop address.
|
|
||||||
format %{ "CMPXCHG $heap_top_ptr,$newval\t# If EAX==$heap_top_ptr Then store $newval into $heap_top_ptr" %}
|
|
||||||
ins_encode( lock_prefix, Opcode(0x0F), Opcode(0xB1), RegMem(newval,heap_top_ptr) );
|
|
||||||
ins_pipe( pipe_cmpxchg );
|
|
||||||
%}
|
|
||||||
|
|
||||||
// Conditional-store of an int value.
|
|
||||||
// ZF flag is set on success, reset otherwise. Implemented with a CMPXCHG on Intel.
|
|
||||||
instruct storeIConditional( memory mem, eAXRegI oldval, rRegI newval, eFlagsReg cr ) %{
|
|
||||||
match(Set cr (StoreIConditional mem (Binary oldval newval)));
|
|
||||||
effect(KILL oldval);
|
|
||||||
format %{ "CMPXCHG $mem,$newval\t# If EAX==$mem Then store $newval into $mem" %}
|
|
||||||
ins_encode( lock_prefix, Opcode(0x0F), Opcode(0xB1), RegMem(newval, mem) );
|
|
||||||
ins_pipe( pipe_cmpxchg );
|
|
||||||
%}
|
|
||||||
|
|
||||||
// Conditional-store of a long value.
|
|
||||||
// ZF flag is set on success, reset otherwise. Implemented with a CMPXCHG8 on Intel.
|
|
||||||
instruct storeLConditional( memory mem, eADXRegL oldval, eBCXRegL newval, eFlagsReg cr ) %{
|
|
||||||
match(Set cr (StoreLConditional mem (Binary oldval newval)));
|
|
||||||
effect(KILL oldval);
|
|
||||||
format %{ "XCHG EBX,ECX\t# correct order for CMPXCHG8 instruction\n\t"
|
|
||||||
"CMPXCHG8 $mem,ECX:EBX\t# If EDX:EAX==$mem Then store ECX:EBX into $mem\n\t"
|
|
||||||
"XCHG EBX,ECX"
|
|
||||||
%}
|
|
||||||
ins_encode %{
|
|
||||||
// Note: we need to swap rbx, and rcx before and after the
|
|
||||||
// cmpxchg8 instruction because the instruction uses
|
|
||||||
// rcx as the high order word of the new value to store but
|
|
||||||
// our register encoding uses rbx.
|
|
||||||
__ xchgl(as_Register(EBX_enc), as_Register(ECX_enc));
|
|
||||||
__ lock();
|
|
||||||
__ cmpxchg8($mem$$Address);
|
|
||||||
__ xchgl(as_Register(EBX_enc), as_Register(ECX_enc));
|
|
||||||
%}
|
|
||||||
ins_pipe( pipe_cmpxchg );
|
|
||||||
%}
|
|
||||||
|
|
||||||
// No flag versions for CompareAndSwap{P,I,L} because matcher can't match them
|
// No flag versions for CompareAndSwap{P,I,L} because matcher can't match them
|
||||||
|
|
||||||
instruct compareAndSwapL( rRegI res, eSIRegP mem_ptr, eADXRegL oldval, eBCXRegL newval, eFlagsReg cr ) %{
|
instruct compareAndSwapL( rRegI res, eSIRegP mem_ptr, eADXRegL oldval, eBCXRegL newval, eFlagsReg cr ) %{
|
||||||
|
|
|
@ -8068,71 +8068,6 @@ instruct castDD(regD dst)
|
||||||
ins_pipe(empty);
|
ins_pipe(empty);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
// LoadP-locked same as a regular LoadP when used with compare-swap
|
|
||||||
instruct loadPLocked(rRegP dst, memory mem)
|
|
||||||
%{
|
|
||||||
match(Set dst (LoadPLocked mem));
|
|
||||||
|
|
||||||
ins_cost(125); // XXX
|
|
||||||
format %{ "movq $dst, $mem\t# ptr locked" %}
|
|
||||||
ins_encode %{
|
|
||||||
__ movq($dst$$Register, $mem$$Address);
|
|
||||||
%}
|
|
||||||
ins_pipe(ialu_reg_mem); // XXX
|
|
||||||
%}
|
|
||||||
|
|
||||||
// Conditional-store of the updated heap-top.
|
|
||||||
// Used during allocation of the shared heap.
|
|
||||||
// Sets flags (EQ) on success. Implemented with a CMPXCHG on Intel.
|
|
||||||
|
|
||||||
instruct storePConditional(memory heap_top_ptr,
|
|
||||||
rax_RegP oldval, rRegP newval,
|
|
||||||
rFlagsReg cr)
|
|
||||||
%{
|
|
||||||
predicate(n->as_LoadStore()->barrier_data() == 0);
|
|
||||||
match(Set cr (StorePConditional heap_top_ptr (Binary oldval newval)));
|
|
||||||
|
|
||||||
format %{ "cmpxchgq $heap_top_ptr, $newval\t# (ptr) "
|
|
||||||
"If rax == $heap_top_ptr then store $newval into $heap_top_ptr" %}
|
|
||||||
ins_encode %{
|
|
||||||
__ lock();
|
|
||||||
__ cmpxchgq($newval$$Register, $heap_top_ptr$$Address);
|
|
||||||
%}
|
|
||||||
ins_pipe(pipe_cmpxchg);
|
|
||||||
%}
|
|
||||||
|
|
||||||
// Conditional-store of an int value.
|
|
||||||
// ZF flag is set on success, reset otherwise. Implemented with a CMPXCHG.
|
|
||||||
instruct storeIConditional(memory mem, rax_RegI oldval, rRegI newval, rFlagsReg cr)
|
|
||||||
%{
|
|
||||||
match(Set cr (StoreIConditional mem (Binary oldval newval)));
|
|
||||||
effect(KILL oldval);
|
|
||||||
|
|
||||||
format %{ "cmpxchgl $mem, $newval\t# If rax == $mem then store $newval into $mem" %}
|
|
||||||
opcode(0x0F, 0xB1);
|
|
||||||
ins_encode(lock_prefix,
|
|
||||||
REX_reg_mem(newval, mem),
|
|
||||||
OpcP, OpcS,
|
|
||||||
reg_mem(newval, mem));
|
|
||||||
ins_pipe(pipe_cmpxchg);
|
|
||||||
%}
|
|
||||||
|
|
||||||
// Conditional-store of a long value.
|
|
||||||
// ZF flag is set on success, reset otherwise. Implemented with a CMPXCHG.
|
|
||||||
instruct storeLConditional(memory mem, rax_RegL oldval, rRegL newval, rFlagsReg cr)
|
|
||||||
%{
|
|
||||||
match(Set cr (StoreLConditional mem (Binary oldval newval)));
|
|
||||||
effect(KILL oldval);
|
|
||||||
|
|
||||||
format %{ "cmpxchgq $mem, $newval\t# If rax == $mem then store $newval into $mem" %}
|
|
||||||
ins_encode %{
|
|
||||||
__ lock();
|
|
||||||
__ cmpxchgq($newval$$Register, $mem$$Address);
|
|
||||||
%}
|
|
||||||
ins_pipe(pipe_cmpxchg);
|
|
||||||
%}
|
|
||||||
|
|
||||||
|
|
||||||
// XXX No flag versions for CompareAndSwap{P,I,L} because matcher can't match them
|
// XXX No flag versions for CompareAndSwap{P,I,L} because matcher can't match them
|
||||||
instruct compareAndSwapP(rRegI res,
|
instruct compareAndSwapP(rRegI res,
|
||||||
memory mem_ptr,
|
memory mem_ptr,
|
||||||
|
|
|
@ -262,7 +262,6 @@ Form::DataType Form::is_load_from_memory(const char *opType) const {
|
||||||
if( strcmp(opType,"LoadNKlass")==0 ) return Form::idealNKlass;
|
if( strcmp(opType,"LoadNKlass")==0 ) return Form::idealNKlass;
|
||||||
if( strcmp(opType,"LoadL")==0 ) return Form::idealL;
|
if( strcmp(opType,"LoadL")==0 ) return Form::idealL;
|
||||||
if( strcmp(opType,"LoadL_unaligned")==0 ) return Form::idealL;
|
if( strcmp(opType,"LoadL_unaligned")==0 ) return Form::idealL;
|
||||||
if( strcmp(opType,"LoadPLocked")==0 ) return Form::idealP;
|
|
||||||
if( strcmp(opType,"LoadP")==0 ) return Form::idealP;
|
if( strcmp(opType,"LoadP")==0 ) return Form::idealP;
|
||||||
if( strcmp(opType,"LoadN")==0 ) return Form::idealN;
|
if( strcmp(opType,"LoadN")==0 ) return Form::idealN;
|
||||||
if( strcmp(opType,"LoadRange")==0 ) return Form::idealI;
|
if( strcmp(opType,"LoadRange")==0 ) return Form::idealI;
|
||||||
|
|
|
@ -3513,8 +3513,6 @@ int MatchNode::needs_ideal_memory_edge(FormDict &globals) const {
|
||||||
"StoreVector", "LoadVector", "LoadVectorMasked", "StoreVectorMasked",
|
"StoreVector", "LoadVector", "LoadVectorMasked", "StoreVectorMasked",
|
||||||
"LoadVectorGather", "StoreVectorScatter", "LoadVectorGatherMasked", "StoreVectorScatterMasked",
|
"LoadVectorGather", "StoreVectorScatter", "LoadVectorGatherMasked", "StoreVectorScatterMasked",
|
||||||
"LoadRange", "LoadKlass", "LoadNKlass", "LoadL_unaligned", "LoadD_unaligned",
|
"LoadRange", "LoadKlass", "LoadNKlass", "LoadL_unaligned", "LoadD_unaligned",
|
||||||
"LoadPLocked",
|
|
||||||
"StorePConditional", "StoreIConditional", "StoreLConditional",
|
|
||||||
"CompareAndSwapB", "CompareAndSwapS", "CompareAndSwapI", "CompareAndSwapL", "CompareAndSwapP", "CompareAndSwapN",
|
"CompareAndSwapB", "CompareAndSwapS", "CompareAndSwapI", "CompareAndSwapL", "CompareAndSwapP", "CompareAndSwapN",
|
||||||
"WeakCompareAndSwapB", "WeakCompareAndSwapS", "WeakCompareAndSwapI", "WeakCompareAndSwapL", "WeakCompareAndSwapP", "WeakCompareAndSwapN",
|
"WeakCompareAndSwapB", "WeakCompareAndSwapS", "WeakCompareAndSwapI", "WeakCompareAndSwapL", "WeakCompareAndSwapP", "WeakCompareAndSwapN",
|
||||||
"CompareAndExchangeB", "CompareAndExchangeS", "CompareAndExchangeI", "CompareAndExchangeL", "CompareAndExchangeP", "CompareAndExchangeN",
|
"CompareAndExchangeB", "CompareAndExchangeS", "CompareAndExchangeI", "CompareAndExchangeL", "CompareAndExchangeP", "CompareAndExchangeN",
|
||||||
|
|
|
@ -2822,8 +2822,6 @@ void MemoryGraphFixer::fix_memory_uses(Node* mem, Node* replacement, Node* rep_p
|
||||||
u->Opcode() == Op_Rethrow ||
|
u->Opcode() == Op_Rethrow ||
|
||||||
u->Opcode() == Op_Return ||
|
u->Opcode() == Op_Return ||
|
||||||
u->Opcode() == Op_SafePoint ||
|
u->Opcode() == Op_SafePoint ||
|
||||||
u->Opcode() == Op_StoreIConditional ||
|
|
||||||
u->Opcode() == Op_StoreLConditional ||
|
|
||||||
(u->is_CallStaticJava() && u->as_CallStaticJava()->uncommon_trap_request() != 0) ||
|
(u->is_CallStaticJava() && u->as_CallStaticJava()->uncommon_trap_request() != 0) ||
|
||||||
(u->is_CallStaticJava() && u->as_CallStaticJava()->_entry_point == OptoRuntime::rethrow_stub()) ||
|
(u->is_CallStaticJava() && u->as_CallStaticJava()->_entry_point == OptoRuntime::rethrow_stub()) ||
|
||||||
u->Opcode() == Op_CallLeaf, "%s", u->Name());
|
u->Opcode() == Op_CallLeaf, "%s", u->Name());
|
||||||
|
|
|
@ -206,7 +206,6 @@ macro(LoadKlass)
|
||||||
macro(LoadNKlass)
|
macro(LoadNKlass)
|
||||||
macro(LoadL)
|
macro(LoadL)
|
||||||
macro(LoadL_unaligned)
|
macro(LoadL_unaligned)
|
||||||
macro(LoadPLocked)
|
|
||||||
macro(LoadP)
|
macro(LoadP)
|
||||||
macro(LoadN)
|
macro(LoadN)
|
||||||
macro(LoadRange)
|
macro(LoadRange)
|
||||||
|
@ -337,9 +336,6 @@ macro(StartOSR)
|
||||||
macro(StoreB)
|
macro(StoreB)
|
||||||
macro(StoreC)
|
macro(StoreC)
|
||||||
macro(StoreCM)
|
macro(StoreCM)
|
||||||
macro(StorePConditional)
|
|
||||||
macro(StoreIConditional)
|
|
||||||
macro(StoreLConditional)
|
|
||||||
macro(StoreD)
|
macro(StoreD)
|
||||||
macro(StoreF)
|
macro(StoreF)
|
||||||
macro(StoreI)
|
macro(StoreI)
|
||||||
|
|
|
@ -3237,11 +3237,8 @@ void Compile::final_graph_reshaping_main_switch(Node* n, Final_Reshape_Counts& f
|
||||||
|
|
||||||
case Op_StoreB:
|
case Op_StoreB:
|
||||||
case Op_StoreC:
|
case Op_StoreC:
|
||||||
case Op_StorePConditional:
|
|
||||||
case Op_StoreI:
|
case Op_StoreI:
|
||||||
case Op_StoreL:
|
case Op_StoreL:
|
||||||
case Op_StoreIConditional:
|
|
||||||
case Op_StoreLConditional:
|
|
||||||
case Op_CompareAndSwapB:
|
case Op_CompareAndSwapB:
|
||||||
case Op_CompareAndSwapS:
|
case Op_CompareAndSwapS:
|
||||||
case Op_CompareAndSwapI:
|
case Op_CompareAndSwapI:
|
||||||
|
@ -3281,7 +3278,6 @@ void Compile::final_graph_reshaping_main_switch(Node* n, Final_Reshape_Counts& f
|
||||||
case Op_LoadNKlass:
|
case Op_LoadNKlass:
|
||||||
case Op_LoadL:
|
case Op_LoadL:
|
||||||
case Op_LoadL_unaligned:
|
case Op_LoadL_unaligned:
|
||||||
case Op_LoadPLocked:
|
|
||||||
case Op_LoadP:
|
case Op_LoadP:
|
||||||
case Op_LoadN:
|
case Op_LoadN:
|
||||||
case Op_LoadRange:
|
case Op_LoadRange:
|
||||||
|
|
|
@ -581,8 +581,7 @@ void ConnectionGraph::add_node_to_connection_graph(Node *n, Unique_Node_List *de
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Op_LoadP:
|
case Op_LoadP:
|
||||||
case Op_LoadN:
|
case Op_LoadN: {
|
||||||
case Op_LoadPLocked: {
|
|
||||||
add_objload_to_connection_graph(n, delayed_worklist);
|
add_objload_to_connection_graph(n, delayed_worklist);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -635,7 +634,6 @@ void ConnectionGraph::add_node_to_connection_graph(Node *n, Unique_Node_List *de
|
||||||
case Op_StoreP:
|
case Op_StoreP:
|
||||||
case Op_StoreN:
|
case Op_StoreN:
|
||||||
case Op_StoreNKlass:
|
case Op_StoreNKlass:
|
||||||
case Op_StorePConditional:
|
|
||||||
case Op_WeakCompareAndSwapP:
|
case Op_WeakCompareAndSwapP:
|
||||||
case Op_WeakCompareAndSwapN:
|
case Op_WeakCompareAndSwapN:
|
||||||
case Op_CompareAndSwapP:
|
case Op_CompareAndSwapP:
|
||||||
|
@ -738,8 +736,7 @@ void ConnectionGraph::add_final_edges(Node *n) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Op_LoadP:
|
case Op_LoadP:
|
||||||
case Op_LoadN:
|
case Op_LoadN: {
|
||||||
case Op_LoadPLocked: {
|
|
||||||
// Using isa_ptr() instead of isa_oopptr() for LoadP and Phi because
|
// Using isa_ptr() instead of isa_oopptr() for LoadP and Phi because
|
||||||
// ThreadLocal has RawPtr type.
|
// ThreadLocal has RawPtr type.
|
||||||
assert(_igvn->type(n)->make_ptr() != NULL, "Unexpected node type");
|
assert(_igvn->type(n)->make_ptr() != NULL, "Unexpected node type");
|
||||||
|
@ -794,8 +791,7 @@ void ConnectionGraph::add_final_edges(Node *n) {
|
||||||
case Op_WeakCompareAndSwapN:
|
case Op_WeakCompareAndSwapN:
|
||||||
case Op_StoreP:
|
case Op_StoreP:
|
||||||
case Op_StoreN:
|
case Op_StoreN:
|
||||||
case Op_StoreNKlass:
|
case Op_StoreNKlass:{
|
||||||
case Op_StorePConditional:{
|
|
||||||
add_final_edges_unsafe_access(n, opcode);
|
add_final_edges_unsafe_access(n, opcode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3435,10 +3435,7 @@ void IdealLoopTree::adjust_loop_exit_prob(PhaseIdealLoop *phase) {
|
||||||
if (iff->outcnt() == 2) { // Ignore dead tests
|
if (iff->outcnt() == 2) { // Ignore dead tests
|
||||||
Node *bol = iff->in(1);
|
Node *bol = iff->in(1);
|
||||||
if (bol && bol->req() > 1 && bol->in(1) &&
|
if (bol && bol->req() > 1 && bol->in(1) &&
|
||||||
((bol->in(1)->Opcode() == Op_StorePConditional) ||
|
((bol->in(1)->Opcode() == Op_CompareAndExchangeB) ||
|
||||||
(bol->in(1)->Opcode() == Op_StoreIConditional) ||
|
|
||||||
(bol->in(1)->Opcode() == Op_StoreLConditional) ||
|
|
||||||
(bol->in(1)->Opcode() == Op_CompareAndExchangeB) ||
|
|
||||||
(bol->in(1)->Opcode() == Op_CompareAndExchangeS) ||
|
(bol->in(1)->Opcode() == Op_CompareAndExchangeS) ||
|
||||||
(bol->in(1)->Opcode() == Op_CompareAndExchangeI) ||
|
(bol->in(1)->Opcode() == Op_CompareAndExchangeI) ||
|
||||||
(bol->in(1)->Opcode() == Op_CompareAndExchangeL) ||
|
(bol->in(1)->Opcode() == Op_CompareAndExchangeL) ||
|
||||||
|
|
|
@ -2326,9 +2326,6 @@ void Matcher::find_shared_post_visit(Node* n, uint opcode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(opcode) { // Handle some opcodes special
|
switch(opcode) { // Handle some opcodes special
|
||||||
case Op_StorePConditional:
|
|
||||||
case Op_StoreIConditional:
|
|
||||||
case Op_StoreLConditional:
|
|
||||||
case Op_CompareAndExchangeB:
|
case Op_CompareAndExchangeB:
|
||||||
case Op_CompareAndExchangeS:
|
case Op_CompareAndExchangeS:
|
||||||
case Op_CompareAndExchangeI:
|
case Op_CompareAndExchangeI:
|
||||||
|
|
|
@ -796,19 +796,6 @@ public:
|
||||||
int oop_alias_idx() const { return _oop_alias_idx; }
|
int oop_alias_idx() const { return _oop_alias_idx; }
|
||||||
};
|
};
|
||||||
|
|
||||||
//------------------------------LoadPLockedNode---------------------------------
|
|
||||||
// Load-locked a pointer from memory (either object or array).
|
|
||||||
// On Sparc & Intel this is implemented as a normal pointer load.
|
|
||||||
// On PowerPC and friends it's a real load-locked.
|
|
||||||
class LoadPLockedNode : public LoadPNode {
|
|
||||||
public:
|
|
||||||
LoadPLockedNode(Node *c, Node *mem, Node *adr, MemOrd mo)
|
|
||||||
: LoadPNode(c, mem, adr, TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM, mo) {}
|
|
||||||
virtual int Opcode() const;
|
|
||||||
virtual int store_Opcode() const { return Op_StorePConditional; }
|
|
||||||
virtual bool depends_only_on_test() const { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
//------------------------------SCMemProjNode---------------------------------------
|
//------------------------------SCMemProjNode---------------------------------------
|
||||||
// This class defines a projection of the memory state of a store conditional node.
|
// This class defines a projection of the memory state of a store conditional node.
|
||||||
// These nodes return a value, but also update memory.
|
// These nodes return a value, but also update memory.
|
||||||
|
@ -865,39 +852,6 @@ public:
|
||||||
virtual const Type* Value(PhaseGVN* phase) const;
|
virtual const Type* Value(PhaseGVN* phase) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
//------------------------------StorePConditionalNode---------------------------
|
|
||||||
// Conditionally store pointer to memory, if no change since prior
|
|
||||||
// load-locked. Sets flags for success or failure of the store.
|
|
||||||
class StorePConditionalNode : public LoadStoreConditionalNode {
|
|
||||||
public:
|
|
||||||
StorePConditionalNode( Node *c, Node *mem, Node *adr, Node *val, Node *ll ) : LoadStoreConditionalNode(c, mem, adr, val, ll) { }
|
|
||||||
virtual int Opcode() const;
|
|
||||||
// Produces flags
|
|
||||||
virtual uint ideal_reg() const { return Op_RegFlags; }
|
|
||||||
};
|
|
||||||
|
|
||||||
//------------------------------StoreIConditionalNode---------------------------
|
|
||||||
// Conditionally store int to memory, if no change since prior
|
|
||||||
// load-locked. Sets flags for success or failure of the store.
|
|
||||||
class StoreIConditionalNode : public LoadStoreConditionalNode {
|
|
||||||
public:
|
|
||||||
StoreIConditionalNode( Node *c, Node *mem, Node *adr, Node *val, Node *ii ) : LoadStoreConditionalNode(c, mem, adr, val, ii) { }
|
|
||||||
virtual int Opcode() const;
|
|
||||||
// Produces flags
|
|
||||||
virtual uint ideal_reg() const { return Op_RegFlags; }
|
|
||||||
};
|
|
||||||
|
|
||||||
//------------------------------StoreLConditionalNode---------------------------
|
|
||||||
// Conditionally store long to memory, if no change since prior
|
|
||||||
// load-locked. Sets flags for success or failure of the store.
|
|
||||||
class StoreLConditionalNode : public LoadStoreConditionalNode {
|
|
||||||
public:
|
|
||||||
StoreLConditionalNode( Node *c, Node *mem, Node *adr, Node *val, Node *ll ) : LoadStoreConditionalNode(c, mem, adr, val, ll) { }
|
|
||||||
virtual int Opcode() const;
|
|
||||||
// Produces flags
|
|
||||||
virtual uint ideal_reg() const { return Op_RegFlags; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class CompareAndSwapNode : public LoadStoreConditionalNode {
|
class CompareAndSwapNode : public LoadStoreConditionalNode {
|
||||||
private:
|
private:
|
||||||
const MemNode::MemOrd _mem_ord;
|
const MemNode::MemOrd _mem_ord;
|
||||||
|
|
|
@ -1653,11 +1653,8 @@
|
||||||
declare_c2_type(StoreNNode, StoreNode) \
|
declare_c2_type(StoreNNode, StoreNode) \
|
||||||
declare_c2_type(StoreNKlassNode, StoreNode) \
|
declare_c2_type(StoreNKlassNode, StoreNode) \
|
||||||
declare_c2_type(StoreCMNode, StoreNode) \
|
declare_c2_type(StoreCMNode, StoreNode) \
|
||||||
declare_c2_type(LoadPLockedNode, LoadPNode) \
|
|
||||||
declare_c2_type(SCMemProjNode, ProjNode) \
|
declare_c2_type(SCMemProjNode, ProjNode) \
|
||||||
declare_c2_type(LoadStoreNode, Node) \
|
declare_c2_type(LoadStoreNode, Node) \
|
||||||
declare_c2_type(StorePConditionalNode, LoadStoreNode) \
|
|
||||||
declare_c2_type(StoreLConditionalNode, LoadStoreNode) \
|
|
||||||
declare_c2_type(CompareAndSwapNode, LoadStoreConditionalNode) \
|
declare_c2_type(CompareAndSwapNode, LoadStoreConditionalNode) \
|
||||||
declare_c2_type(CompareAndSwapBNode, CompareAndSwapNode) \
|
declare_c2_type(CompareAndSwapBNode, CompareAndSwapNode) \
|
||||||
declare_c2_type(CompareAndSwapSNode, CompareAndSwapNode) \
|
declare_c2_type(CompareAndSwapSNode, CompareAndSwapNode) \
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue