# HG changeset patch # User never # Date 1225211490 25200 # Node ID 128fe18951ed73cdb56cdc5534d518eca2ca7cd8 # Parent 812e89e3d769969698344a3a0ac363f4c9d5a1bf 6754519: don't emit flag fixup for NaN when condition being tested doesn't need it Reviewed-by: kvn, rasbold diff -r 812e89e3d769 -r 128fe18951ed hotspot/src/cpu/sparc/vm/sparc.ad --- a/hotspot/src/cpu/sparc/vm/sparc.ad Tue Oct 21 11:23:52 2008 -0700 +++ b/hotspot/src/cpu/sparc/vm/sparc.ad Tue Oct 28 09:31:30 2008 -0700 @@ -1743,7 +1743,7 @@ // // NOTE: If the platform does not provide any short branch variants, then // this method should return false for offset 0. -bool Matcher::is_short_branch_offset(int offset) { +bool Matcher::is_short_branch_offset(int rule, int offset) { return false; } @@ -1926,18 +1926,23 @@ $mem$$base, $mem$$disp, $mem$$index, $dst$$reg); %} + enc_class simple_form3_mem_reg( memory mem, iRegI dst ) %{ + emit_form3_mem_reg(cbuf, this, $primary, -1, + $mem$$base, $mem$$disp, $mem$$index, $dst$$reg); + %} + enc_class form3_mem_reg_little( memory mem, iRegI dst) %{ - emit_form3_mem_reg_asi(cbuf, this, $primary, $tertiary, + emit_form3_mem_reg_asi(cbuf, this, $primary, -1, $mem$$base, $mem$$disp, $mem$$index, $dst$$reg, Assembler::ASI_PRIMARY_LITTLE); %} enc_class form3_mem_prefetch_read( memory mem ) %{ - emit_form3_mem_reg(cbuf, this, $primary, $tertiary, + emit_form3_mem_reg(cbuf, this, $primary, -1, $mem$$base, $mem$$disp, $mem$$index, 0/*prefetch function many-reads*/); %} enc_class form3_mem_prefetch_write( memory mem ) %{ - emit_form3_mem_reg(cbuf, this, $primary, $tertiary, + emit_form3_mem_reg(cbuf, this, $primary, -1, $mem$$base, $mem$$disp, $mem$$index, 2/*prefetch function many-writes*/); %} @@ -1945,8 +1950,8 @@ assert( Assembler::is_simm13($mem$$disp ), "need disp and disp+4" ); assert( Assembler::is_simm13($mem$$disp+4), "need disp and disp+4" ); guarantee($mem$$index == R_G0_enc, "double index?"); - emit_form3_mem_reg(cbuf, this, $primary, $tertiary, $mem$$base, $mem$$disp+4, R_G0_enc, R_O7_enc ); - emit_form3_mem_reg(cbuf, this, $primary, $tertiary, $mem$$base, $mem$$disp, R_G0_enc, $reg$$reg ); + emit_form3_mem_reg(cbuf, this, $primary, -1, $mem$$base, $mem$$disp+4, R_G0_enc, R_O7_enc ); + emit_form3_mem_reg(cbuf, this, $primary, -1, $mem$$base, $mem$$disp, R_G0_enc, $reg$$reg ); emit3_simm13( cbuf, Assembler::arith_op, $reg$$reg, Assembler::sllx_op3, $reg$$reg, 0x1020 ); emit3( cbuf, Assembler::arith_op, $reg$$reg, Assembler::or_op3, $reg$$reg, 0, R_O7_enc ); %} @@ -1956,14 +1961,14 @@ assert( Assembler::is_simm13($mem$$disp+4), "need disp and disp+4" ); guarantee($mem$$index == R_G0_enc, "double index?"); // Load long with 2 instructions - emit_form3_mem_reg(cbuf, this, $primary, $tertiary, $mem$$base, $mem$$disp, R_G0_enc, $reg$$reg+0 ); - emit_form3_mem_reg(cbuf, this, $primary, $tertiary, $mem$$base, $mem$$disp+4, R_G0_enc, $reg$$reg+1 ); + emit_form3_mem_reg(cbuf, this, $primary, -1, $mem$$base, $mem$$disp, R_G0_enc, $reg$$reg+0 ); + emit_form3_mem_reg(cbuf, this, $primary, -1, $mem$$base, $mem$$disp+4, R_G0_enc, $reg$$reg+1 ); %} //%%% form3_mem_plus_4_reg is a hack--get rid of it enc_class form3_mem_plus_4_reg( memory mem, iRegI dst ) %{ guarantee($mem$$disp, "cannot offset a reg-reg operand by 4"); - emit_form3_mem_reg(cbuf, this, $primary, $tertiary, $mem$$base, $mem$$disp + 4, $mem$$index, $dst$$reg); + emit_form3_mem_reg(cbuf, this, $primary, -1, $mem$$base, $mem$$disp + 4, $mem$$index, $dst$$reg); %} enc_class form3_g0_rs2_rd_move( iRegI rs2, iRegI rd ) %{ @@ -5062,7 +5067,7 @@ size(4); format %{ "LDF $src,$dst\t! stkI to regF" %} opcode(Assembler::ldf_op3); - ins_encode(form3_mem_reg(src, dst)); + ins_encode(simple_form3_mem_reg(src, dst)); ins_pipe(floadF_stk); %} @@ -5073,7 +5078,7 @@ size(4); format %{ "LDDF $src,$dst\t! stkL to regD" %} opcode(Assembler::lddf_op3); - ins_encode(form3_mem_reg(src, dst)); + ins_encode(simple_form3_mem_reg(src, dst)); ins_pipe(floadD_stk); %} @@ -5084,7 +5089,7 @@ size(4); format %{ "STF $src,$dst\t! regF to stkI" %} opcode(Assembler::stf_op3); - ins_encode(form3_mem_reg(dst, src)); + ins_encode(simple_form3_mem_reg(dst, src)); ins_pipe(fstoreF_stk_reg); %} @@ -5095,7 +5100,7 @@ size(4); format %{ "STDF $src,$dst\t! regD to stkL" %} opcode(Assembler::stdf_op3); - ins_encode(form3_mem_reg(dst, src)); + ins_encode(simple_form3_mem_reg(dst, src)); ins_pipe(fstoreD_stk_reg); %} @@ -5106,7 +5111,7 @@ format %{ "STW $src,$dst.hi\t! long\n\t" "STW R_G0,$dst.lo" %} opcode(Assembler::stw_op3); - ins_encode(form3_mem_reg(dst, src), form3_mem_plus_4_reg(dst, R_G0)); + ins_encode(simple_form3_mem_reg(dst, src), form3_mem_plus_4_reg(dst, R_G0)); ins_pipe(lstoreI_stk_reg); %} @@ -5117,7 +5122,7 @@ size(4); format %{ "STX $src,$dst\t! regL to stkD" %} opcode(Assembler::stx_op3); - ins_encode( form3_mem_reg( dst, src ) ); + ins_encode(simple_form3_mem_reg( dst, src ) ); ins_pipe(istore_stk_reg); %} @@ -5131,7 +5136,7 @@ size(4); format %{ "LDUW $src,$dst\t!stk" %} opcode(Assembler::lduw_op3); - ins_encode( form3_mem_reg( src, dst ) ); + ins_encode(simple_form3_mem_reg( src, dst ) ); ins_pipe(iload_mem); %} @@ -5143,7 +5148,7 @@ size(4); format %{ "STW $src,$dst\t!stk" %} opcode(Assembler::stw_op3); - ins_encode( form3_mem_reg( dst, src ) ); + ins_encode(simple_form3_mem_reg( dst, src ) ); ins_pipe(istore_mem_reg); %} @@ -5155,7 +5160,7 @@ size(4); format %{ "LDX $src,$dst\t! long" %} opcode(Assembler::ldx_op3); - ins_encode( form3_mem_reg( src, dst ) ); + ins_encode(simple_form3_mem_reg( src, dst ) ); ins_pipe(iload_mem); %} @@ -5167,7 +5172,7 @@ size(4); format %{ "STX $src,$dst\t! long" %} opcode(Assembler::stx_op3); - ins_encode( form3_mem_reg( dst, src ) ); + ins_encode(simple_form3_mem_reg( dst, src ) ); ins_pipe(istore_mem_reg); %} @@ -5179,7 +5184,7 @@ size(4); format %{ "LDX $src,$dst\t!ptr" %} opcode(Assembler::ldx_op3); - ins_encode( form3_mem_reg( src, dst ) ); + ins_encode(simple_form3_mem_reg( src, dst ) ); ins_pipe(iload_mem); %} @@ -5190,7 +5195,7 @@ size(4); format %{ "STX $src,$dst\t!ptr" %} opcode(Assembler::stx_op3); - ins_encode( form3_mem_reg( dst, src ) ); + ins_encode(simple_form3_mem_reg( dst, src ) ); ins_pipe(istore_mem_reg); %} #else // _LP64 @@ -5200,7 +5205,7 @@ ins_cost(MEMORY_REF_COST); format %{ "LDUW $src,$dst\t!ptr" %} opcode(Assembler::lduw_op3, Assembler::ldst_op); - ins_encode( form3_mem_reg( src, dst ) ); + ins_encode(simple_form3_mem_reg( src, dst ) ); ins_pipe(iload_mem); %} @@ -5210,7 +5215,7 @@ ins_cost(MEMORY_REF_COST); format %{ "STW $src,$dst\t!ptr" %} opcode(Assembler::stw_op3, Assembler::ldst_op); - ins_encode( form3_mem_reg( dst, src ) ); + ins_encode(simple_form3_mem_reg( dst, src ) ); ins_pipe(istore_mem_reg); %} #endif // _LP64 @@ -5273,7 +5278,7 @@ size(4); format %{ "LDSB $mem,$dst" %} opcode(Assembler::ldsb_op3); - ins_encode( form3_mem_reg( mem, dst ) ); + ins_encode(simple_form3_mem_reg( mem, dst ) ); ins_pipe(iload_mask_mem); %} @@ -5285,7 +5290,7 @@ size(4); format %{ "LDUB $mem,$dst" %} opcode(Assembler::ldub_op3); - ins_encode( form3_mem_reg( mem, dst ) ); + ins_encode(simple_form3_mem_reg( mem, dst ) ); ins_pipe(iload_mask_mem); %} @@ -5297,7 +5302,7 @@ size(4); format %{ "LDUB $mem,$dst" %} opcode(Assembler::ldub_op3); - ins_encode( form3_mem_reg( mem, dst ) ); + ins_encode(simple_form3_mem_reg( mem, dst ) ); ins_pipe(iload_mask_mem); %} @@ -5309,7 +5314,7 @@ size(4); format %{ "LDUH $mem,$dst" %} opcode(Assembler::lduh_op3); - ins_encode( form3_mem_reg( mem, dst ) ); + ins_encode(simple_form3_mem_reg( mem, dst ) ); ins_pipe(iload_mask_mem); %} @@ -5321,7 +5326,7 @@ size(4); format %{ "LDUH $mem,$dst" %} opcode(Assembler::lduh_op3); - ins_encode( form3_mem_reg( mem, dst ) ); + ins_encode(simple_form3_mem_reg( mem, dst ) ); ins_pipe(iload_mask_mem); %} @@ -5333,7 +5338,7 @@ format %{ "LDUW $mem,$dst" %} opcode(Assembler::lduw_op3); - ins_encode( form3_mem_reg( mem, dst ) ); + ins_encode(simple_form3_mem_reg( mem, dst ) ); ins_pipe(iload_mem); %} @@ -5344,7 +5349,7 @@ size(4); format %{ "LDX $mem,$dst\t! long" %} opcode(Assembler::ldx_op3); - ins_encode( form3_mem_reg( mem, dst ) ); + ins_encode(simple_form3_mem_reg( mem, dst ) ); ins_pipe(iload_mem); %} @@ -5359,7 +5364,7 @@ "\tSLLX #32, $dst, $dst\n" "\tOR $dst, R_O7, $dst" %} opcode(Assembler::lduw_op3); - ins_encode( form3_mem_reg_long_unaligned_marshal( mem, dst )); + ins_encode(form3_mem_reg_long_unaligned_marshal( mem, dst )); ins_pipe(iload_mem); %} @@ -5370,7 +5375,7 @@ size(4); format %{ "LDDF $mem,$dst\t! packed8B" %} opcode(Assembler::lddf_op3); - ins_encode( form3_mem_reg( mem, dst ) ); + ins_encode(simple_form3_mem_reg( mem, dst ) ); ins_pipe(floadD_mem); %} @@ -5381,7 +5386,7 @@ size(4); format %{ "LDDF $mem,$dst\t! packed4C" %} opcode(Assembler::lddf_op3); - ins_encode( form3_mem_reg( mem, dst ) ); + ins_encode(simple_form3_mem_reg( mem, dst ) ); ins_pipe(floadD_mem); %} @@ -5392,7 +5397,7 @@ size(4); format %{ "LDDF $mem,$dst\t! packed4S" %} opcode(Assembler::lddf_op3); - ins_encode( form3_mem_reg( mem, dst ) ); + ins_encode(simple_form3_mem_reg( mem, dst ) ); ins_pipe(floadD_mem); %} @@ -5403,7 +5408,7 @@ size(4); format %{ "LDDF $mem,$dst\t! packed2I" %} opcode(Assembler::lddf_op3); - ins_encode( form3_mem_reg( mem, dst ) ); + ins_encode(simple_form3_mem_reg( mem, dst ) ); ins_pipe(floadD_mem); %} @@ -5415,7 +5420,7 @@ size(4); format %{ "LDUW $mem,$dst\t! range" %} opcode(Assembler::lduw_op3); - ins_encode( form3_mem_reg( mem, dst ) ); + ins_encode(simple_form3_mem_reg( mem, dst ) ); ins_pipe(iload_mem); %} @@ -5427,7 +5432,7 @@ format %{ "LDF $mem,$dst\t! for fitos/fitod" %} opcode(Assembler::ldf_op3); - ins_encode( form3_mem_reg( mem, dst ) ); + ins_encode(simple_form3_mem_reg( mem, dst ) ); ins_pipe(floadF_mem); %} @@ -5514,7 +5519,7 @@ size(4); format %{ "LDSH $mem,$dst" %} opcode(Assembler::ldsh_op3); - ins_encode( form3_mem_reg( mem, dst ) ); + ins_encode(simple_form3_mem_reg( mem, dst ) ); ins_pipe(iload_mask_mem); %} @@ -5526,7 +5531,7 @@ size(4); format %{ "LDDF $mem,$dst" %} opcode(Assembler::lddf_op3); - ins_encode( form3_mem_reg( mem, dst ) ); + ins_encode(simple_form3_mem_reg( mem, dst ) ); ins_pipe(floadD_mem); %} @@ -5550,7 +5555,7 @@ size(4); format %{ "LDF $mem,$dst" %} opcode(Assembler::ldf_op3); - ins_encode( form3_mem_reg( mem, dst ) ); + ins_encode(simple_form3_mem_reg( mem, dst ) ); ins_pipe(floadF_mem); %} @@ -5719,7 +5724,7 @@ size(4); format %{ "STB $src,$mem\t! byte" %} opcode(Assembler::stb_op3); - ins_encode( form3_mem_reg( mem, src ) ); + ins_encode(simple_form3_mem_reg( mem, src ) ); ins_pipe(istore_mem_reg); %} @@ -5730,7 +5735,7 @@ size(4); format %{ "STB $src,$mem\t! byte" %} opcode(Assembler::stb_op3); - ins_encode( form3_mem_reg( mem, R_G0 ) ); + ins_encode(simple_form3_mem_reg( mem, R_G0 ) ); ins_pipe(istore_mem_zero); %} @@ -5741,7 +5746,7 @@ size(4); format %{ "STB $src,$mem\t! CMS card-mark byte 0" %} opcode(Assembler::stb_op3); - ins_encode( form3_mem_reg( mem, R_G0 ) ); + ins_encode(simple_form3_mem_reg( mem, R_G0 ) ); ins_pipe(istore_mem_zero); %} @@ -5753,7 +5758,7 @@ size(4); format %{ "STH $src,$mem\t! short" %} opcode(Assembler::sth_op3); - ins_encode( form3_mem_reg( mem, src ) ); + ins_encode(simple_form3_mem_reg( mem, src ) ); ins_pipe(istore_mem_reg); %} @@ -5764,7 +5769,7 @@ size(4); format %{ "STH $src,$mem\t! short" %} opcode(Assembler::sth_op3); - ins_encode( form3_mem_reg( mem, R_G0 ) ); + ins_encode(simple_form3_mem_reg( mem, R_G0 ) ); ins_pipe(istore_mem_zero); %} @@ -5776,7 +5781,7 @@ size(4); format %{ "STW $src,$mem" %} opcode(Assembler::stw_op3); - ins_encode( form3_mem_reg( mem, src ) ); + ins_encode(simple_form3_mem_reg( mem, src ) ); ins_pipe(istore_mem_reg); %} @@ -5787,7 +5792,7 @@ size(4); format %{ "STX $src,$mem\t! long" %} opcode(Assembler::stx_op3); - ins_encode( form3_mem_reg( mem, src ) ); + ins_encode(simple_form3_mem_reg( mem, src ) ); ins_pipe(istore_mem_reg); %} @@ -5798,7 +5803,7 @@ size(4); format %{ "STW $src,$mem" %} opcode(Assembler::stw_op3); - ins_encode( form3_mem_reg( mem, R_G0 ) ); + ins_encode(simple_form3_mem_reg( mem, R_G0 ) ); ins_pipe(istore_mem_zero); %} @@ -5809,7 +5814,7 @@ size(4); format %{ "STX $src,$mem" %} opcode(Assembler::stx_op3); - ins_encode( form3_mem_reg( mem, R_G0 ) ); + ins_encode(simple_form3_mem_reg( mem, R_G0 ) ); ins_pipe(istore_mem_zero); %} @@ -5821,7 +5826,7 @@ size(4); format %{ "STF $src,$mem\t! after fstoi/fdtoi" %} opcode(Assembler::stf_op3); - ins_encode( form3_mem_reg( mem, src ) ); + ins_encode(simple_form3_mem_reg( mem, src ) ); ins_pipe(fstoreF_mem_reg); %} @@ -5904,7 +5909,7 @@ size(4); format %{ "STDF $src,$mem" %} opcode(Assembler::stdf_op3); - ins_encode( form3_mem_reg( mem, src ) ); + ins_encode(simple_form3_mem_reg( mem, src ) ); ins_pipe(fstoreD_mem_reg); %} @@ -5915,7 +5920,7 @@ size(4); format %{ "STX $src,$mem" %} opcode(Assembler::stx_op3); - ins_encode( form3_mem_reg( mem, R_G0 ) ); + ins_encode(simple_form3_mem_reg( mem, R_G0 ) ); ins_pipe(fstoreD_mem_zero); %} @@ -5927,7 +5932,7 @@ size(4); format %{ "STF $src,$mem" %} opcode(Assembler::stf_op3); - ins_encode( form3_mem_reg( mem, src ) ); + ins_encode(simple_form3_mem_reg( mem, src ) ); ins_pipe(fstoreF_mem_reg); %} @@ -5938,7 +5943,7 @@ size(4); format %{ "STW $src,$mem\t! storeF0" %} opcode(Assembler::stw_op3); - ins_encode( form3_mem_reg( mem, R_G0 ) ); + ins_encode(simple_form3_mem_reg( mem, R_G0 ) ); ins_pipe(fstoreF_mem_zero); %} @@ -5949,7 +5954,7 @@ size(4); format %{ "STDF $src,$mem\t! packed8B" %} opcode(Assembler::stdf_op3); - ins_encode( form3_mem_reg( mem, src ) ); + ins_encode(simple_form3_mem_reg( mem, src ) ); ins_pipe(fstoreD_mem_reg); %} @@ -6004,7 +6009,7 @@ size(4); format %{ "STX $zero,$mem\t! packed8B" %} opcode(Assembler::stx_op3); - ins_encode( form3_mem_reg( mem, R_G0 ) ); + ins_encode(simple_form3_mem_reg( mem, R_G0 ) ); ins_pipe(fstoreD_mem_zero); %} @@ -6015,7 +6020,7 @@ size(4); format %{ "STDF $src,$mem\t! packed4C" %} opcode(Assembler::stdf_op3); - ins_encode( form3_mem_reg( mem, src ) ); + ins_encode(simple_form3_mem_reg( mem, src ) ); ins_pipe(fstoreD_mem_reg); %} @@ -6026,7 +6031,7 @@ size(4); format %{ "STX $zero,$mem\t! packed4C" %} opcode(Assembler::stx_op3); - ins_encode( form3_mem_reg( mem, R_G0 ) ); + ins_encode(simple_form3_mem_reg( mem, R_G0 ) ); ins_pipe(fstoreD_mem_zero); %} @@ -6037,7 +6042,7 @@ size(4); format %{ "STDF $src,$mem\t! packed2I" %} opcode(Assembler::stdf_op3); - ins_encode( form3_mem_reg( mem, src ) ); + ins_encode(simple_form3_mem_reg( mem, src ) ); ins_pipe(fstoreD_mem_reg); %} @@ -6048,7 +6053,7 @@ size(4); format %{ "STX $zero,$mem\t! packed2I" %} opcode(Assembler::stx_op3); - ins_encode( form3_mem_reg( mem, R_G0 ) ); + ins_encode(simple_form3_mem_reg( mem, R_G0 ) ); ins_pipe(fstoreD_mem_zero); %} @@ -6162,7 +6167,7 @@ ins_cost(MEMORY_REF_COST); format %{ "STDF $src,$stkSlot\t!stk" %} opcode(Assembler::stdf_op3); - ins_encode(form3_mem_reg(stkSlot, src)); + ins_encode(simple_form3_mem_reg(stkSlot, src)); ins_pipe(fstoreD_stk_reg); %} @@ -6172,7 +6177,7 @@ ins_cost(MEMORY_REF_COST); format %{ "LDDF $stkSlot,$dst\t!stk" %} opcode(Assembler::lddf_op3); - ins_encode(form3_mem_reg(stkSlot, dst)); + ins_encode(simple_form3_mem_reg(stkSlot, dst)); ins_pipe(floadD_stk); %} @@ -6182,7 +6187,7 @@ ins_cost(MEMORY_REF_COST); format %{ "STF $src,$stkSlot\t!stk" %} opcode(Assembler::stf_op3); - ins_encode(form3_mem_reg(stkSlot, src)); + ins_encode(simple_form3_mem_reg(stkSlot, src)); ins_pipe(fstoreF_stk_reg); %} @@ -6584,7 +6589,7 @@ size(4); format %{ "LDX $mem,$dst\t! long" %} opcode(Assembler::ldx_op3); - ins_encode( form3_mem_reg( mem, dst ) ); + ins_encode(simple_form3_mem_reg( mem, dst ) ); ins_pipe(iload_mem); %} @@ -7666,7 +7671,7 @@ format %{ "LDF $mem,$dst\n\t" "FITOD $dst,$dst" %} opcode(Assembler::ldf_op3, Assembler::fitod_opf); - ins_encode( form3_mem_reg( mem, dst ), form3_convI2F(dst, dst)); + ins_encode(simple_form3_mem_reg( mem, dst ), form3_convI2F(dst, dst)); ins_pipe(floadF_mem); %} @@ -7696,7 +7701,7 @@ format %{ "LDF $mem,$dst\n\t" "FITOS $dst,$dst" %} opcode(Assembler::ldf_op3, Assembler::fitos_opf); - ins_encode( form3_mem_reg( mem, dst ), form3_convI2F(dst, dst)); + ins_encode(simple_form3_mem_reg( mem, dst ), form3_convI2F(dst, dst)); ins_pipe(floadF_mem); %} @@ -7738,7 +7743,7 @@ size(4); format %{ "LDUW $src,$dst\t! MoveF2I" %} opcode(Assembler::lduw_op3); - ins_encode( form3_mem_reg( src, dst ) ); + ins_encode(simple_form3_mem_reg( src, dst ) ); ins_pipe(iload_mem); %} @@ -7750,7 +7755,7 @@ size(4); format %{ "LDF $src,$dst\t! MoveI2F" %} opcode(Assembler::ldf_op3); - ins_encode(form3_mem_reg(src, dst)); + ins_encode(simple_form3_mem_reg(src, dst)); ins_pipe(floadF_stk); %} @@ -7762,7 +7767,7 @@ size(4); format %{ "LDX $src,$dst\t! MoveD2L" %} opcode(Assembler::ldx_op3); - ins_encode( form3_mem_reg( src, dst ) ); + ins_encode(simple_form3_mem_reg( src, dst ) ); ins_pipe(iload_mem); %} @@ -7774,7 +7779,7 @@ size(4); format %{ "LDDF $src,$dst\t! MoveL2D" %} opcode(Assembler::lddf_op3); - ins_encode(form3_mem_reg(src, dst)); + ins_encode(simple_form3_mem_reg(src, dst)); ins_pipe(floadD_stk); %} @@ -7786,7 +7791,7 @@ size(4); format %{ "STF $src,$dst\t!MoveF2I" %} opcode(Assembler::stf_op3); - ins_encode(form3_mem_reg(dst, src)); + ins_encode(simple_form3_mem_reg(dst, src)); ins_pipe(fstoreF_stk_reg); %} @@ -7798,7 +7803,7 @@ size(4); format %{ "STW $src,$dst\t!MoveI2F" %} opcode(Assembler::stw_op3); - ins_encode( form3_mem_reg( dst, src ) ); + ins_encode(simple_form3_mem_reg( dst, src ) ); ins_pipe(istore_mem_reg); %} @@ -7810,7 +7815,7 @@ size(4); format %{ "STDF $src,$dst\t!MoveD2L" %} opcode(Assembler::stdf_op3); - ins_encode(form3_mem_reg(dst, src)); + ins_encode(simple_form3_mem_reg(dst, src)); ins_pipe(fstoreD_stk_reg); %} @@ -7822,7 +7827,7 @@ size(4); format %{ "STX $src,$dst\t!MoveL2D" %} opcode(Assembler::stx_op3); - ins_encode( form3_mem_reg( dst, src ) ); + ins_encode(simple_form3_mem_reg( dst, src ) ); ins_pipe(istore_mem_reg); %} diff -r 812e89e3d769 -r 128fe18951ed hotspot/src/cpu/x86/vm/x86_32.ad --- a/hotspot/src/cpu/x86/vm/x86_32.ad Tue Oct 21 11:23:52 2008 -0700 +++ b/hotspot/src/cpu/x86/vm/x86_32.ad Tue Oct 28 09:31:30 2008 -0700 @@ -495,8 +495,8 @@ void MachPrologNode::format( PhaseRegAlloc *ra_, outputStream* st ) const { Compile* C = ra_->C; if( C->in_24_bit_fp_mode() ) { - tty->print("FLDCW 24 bit fpu control word"); - tty->print_cr(""); tty->print("\t"); + st->print("FLDCW 24 bit fpu control word"); + st->print_cr(""); st->print("\t"); } int framesize = C->frame_slots() << LogBytesPerInt; @@ -510,22 +510,22 @@ // stack. But the stack safety zone should account for that. // See bugs 4446381, 4468289, 4497237. if (C->need_stack_bang(framesize)) { - tty->print_cr("# stack bang"); tty->print("\t"); + st->print_cr("# stack bang"); st->print("\t"); } - tty->print_cr("PUSHL EBP"); tty->print("\t"); + st->print_cr("PUSHL EBP"); st->print("\t"); if( VerifyStackAtCalls ) { // Majik cookie to verify stack depth - tty->print("PUSH 0xBADB100D\t# Majik cookie for stack depth check"); - tty->print_cr(""); tty->print("\t"); + st->print("PUSH 0xBADB100D\t# Majik cookie for stack depth check"); + st->print_cr(""); st->print("\t"); framesize -= wordSize; } if ((C->in_24_bit_fp_mode() || VerifyStackAtCalls ) && framesize < 128 ) { if (framesize) { - tty->print("SUB ESP,%d\t# Create frame",framesize); + st->print("SUB ESP,%d\t# Create frame",framesize); } } else { - tty->print("SUB ESP,%d\t# Create frame",framesize); + st->print("SUB ESP,%d\t# Create frame",framesize); } } #endif @@ -725,18 +725,19 @@ return rc_xmm; } -static int impl_helper( CodeBuffer *cbuf, bool do_size, bool is_load, int offset, int reg, int opcode, const char *op_str, int size ) { +static int impl_helper( CodeBuffer *cbuf, bool do_size, bool is_load, int offset, int reg, + int opcode, const char *op_str, int size, outputStream* st ) { if( cbuf ) { emit_opcode (*cbuf, opcode ); encode_RegMem(*cbuf, Matcher::_regEncode[reg], ESP_enc, 0x4, 0, offset, false); #ifndef PRODUCT } else if( !do_size ) { - if( size != 0 ) tty->print("\n\t"); + if( size != 0 ) st->print("\n\t"); if( opcode == 0x8B || opcode == 0x89 ) { // MOV - if( is_load ) tty->print("%s %s,[ESP + #%d]",op_str,Matcher::regName[reg],offset); - else tty->print("%s [ESP + #%d],%s",op_str,offset,Matcher::regName[reg]); + if( is_load ) st->print("%s %s,[ESP + #%d]",op_str,Matcher::regName[reg],offset); + else st->print("%s [ESP + #%d],%s",op_str,offset,Matcher::regName[reg]); } else { // FLD, FST, PUSH, POP - tty->print("%s [ESP + #%d]",op_str,offset); + st->print("%s [ESP + #%d]",op_str,offset); } #endif } @@ -746,7 +747,7 @@ // Helper for XMM registers. Extra opcode bits, limited syntax. static int impl_x_helper( CodeBuffer *cbuf, bool do_size, bool is_load, - int offset, int reg_lo, int reg_hi, int size ) { + int offset, int reg_lo, int reg_hi, int size, outputStream* st ) { if( cbuf ) { if( reg_lo+1 == reg_hi ) { // double move? if( is_load && !UseXmmLoadAndClearUpper ) @@ -764,17 +765,17 @@ encode_RegMem(*cbuf, Matcher::_regEncode[reg_lo], ESP_enc, 0x4, 0, offset, false); #ifndef PRODUCT } else if( !do_size ) { - if( size != 0 ) tty->print("\n\t"); + if( size != 0 ) st->print("\n\t"); if( reg_lo+1 == reg_hi ) { // double move? - if( is_load ) tty->print("%s %s,[ESP + #%d]", + if( is_load ) st->print("%s %s,[ESP + #%d]", UseXmmLoadAndClearUpper ? "MOVSD " : "MOVLPD", Matcher::regName[reg_lo], offset); - else tty->print("MOVSD [ESP + #%d],%s", + else st->print("MOVSD [ESP + #%d],%s", offset, Matcher::regName[reg_lo]); } else { - if( is_load ) tty->print("MOVSS %s,[ESP + #%d]", + if( is_load ) st->print("MOVSS %s,[ESP + #%d]", Matcher::regName[reg_lo], offset); - else tty->print("MOVSS [ESP + #%d],%s", + else st->print("MOVSS [ESP + #%d],%s", offset, Matcher::regName[reg_lo]); } #endif @@ -785,7 +786,7 @@ static int impl_movx_helper( CodeBuffer *cbuf, bool do_size, int src_lo, int dst_lo, - int src_hi, int dst_hi, int size ) { + int src_hi, int dst_hi, int size, outputStream* st ) { if( UseXmmRegToRegMoveAll ) {//Use movaps,movapd to move between xmm registers if( cbuf ) { if( (src_lo+1 == src_hi && dst_lo+1 == dst_hi) ) { @@ -796,11 +797,11 @@ emit_rm (*cbuf, 0x3, Matcher::_regEncode[dst_lo], Matcher::_regEncode[src_lo] ); #ifndef PRODUCT } else if( !do_size ) { - if( size != 0 ) tty->print("\n\t"); + if( size != 0 ) st->print("\n\t"); if( src_lo+1 == src_hi && dst_lo+1 == dst_hi ) { // double move? - tty->print("MOVAPD %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]); + st->print("MOVAPD %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]); } else { - tty->print("MOVAPS %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]); + st->print("MOVAPS %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]); } #endif } @@ -813,11 +814,11 @@ emit_rm (*cbuf, 0x3, Matcher::_regEncode[dst_lo], Matcher::_regEncode[src_lo] ); #ifndef PRODUCT } else if( !do_size ) { - if( size != 0 ) tty->print("\n\t"); + if( size != 0 ) st->print("\n\t"); if( src_lo+1 == src_hi && dst_lo+1 == dst_hi ) { // double move? - tty->print("MOVSD %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]); + st->print("MOVSD %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]); } else { - tty->print("MOVSS %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]); + st->print("MOVSS %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]); } #endif } @@ -825,28 +826,29 @@ } } -static int impl_mov_helper( CodeBuffer *cbuf, bool do_size, int src, int dst, int size ) { +static int impl_mov_helper( CodeBuffer *cbuf, bool do_size, int src, int dst, int size, outputStream* st ) { if( cbuf ) { emit_opcode(*cbuf, 0x8B ); emit_rm (*cbuf, 0x3, Matcher::_regEncode[dst], Matcher::_regEncode[src] ); #ifndef PRODUCT } else if( !do_size ) { - if( size != 0 ) tty->print("\n\t"); - tty->print("MOV %s,%s",Matcher::regName[dst],Matcher::regName[src]); + if( size != 0 ) st->print("\n\t"); + st->print("MOV %s,%s",Matcher::regName[dst],Matcher::regName[src]); #endif } return size+2; } -static int impl_fp_store_helper( CodeBuffer *cbuf, bool do_size, int src_lo, int src_hi, int dst_lo, int dst_hi, int offset, int size ) { +static int impl_fp_store_helper( CodeBuffer *cbuf, bool do_size, int src_lo, int src_hi, int dst_lo, int dst_hi, + int offset, int size, outputStream* st ) { if( src_lo != FPR1L_num ) { // Move value to top of FP stack, if not already there if( cbuf ) { emit_opcode( *cbuf, 0xD9 ); // FLD (i.e., push it) emit_d8( *cbuf, 0xC0-1+Matcher::_regEncode[src_lo] ); #ifndef PRODUCT } else if( !do_size ) { - if( size != 0 ) tty->print("\n\t"); - tty->print("FLD %s",Matcher::regName[src_lo]); + if( size != 0 ) st->print("\n\t"); + st->print("FLD %s",Matcher::regName[src_lo]); #endif } size += 2; @@ -864,7 +866,7 @@ assert( !OptoReg::is_valid(src_hi) && !OptoReg::is_valid(dst_hi), "no non-adjacent float-stores" ); } - return impl_helper(cbuf,do_size,false,offset,st_op,op,op_str,size); + return impl_helper(cbuf,do_size,false,offset,st_op,op,op_str,size, st); } uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, PhaseRegAlloc *ra_, bool do_size, outputStream* st ) const { @@ -892,16 +894,16 @@ if( src_first_rc == rc_stack && dst_first_rc == rc_stack ) { if( src_second == dst_first ) { // overlapping stack copy ranges assert( src_second_rc == rc_stack && dst_second_rc == rc_stack, "we only expect a stk-stk copy here" ); - size = impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_second),ESI_num,0xFF,"PUSH ",size); - size = impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_second),EAX_num,0x8F,"POP ",size); + size = impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_second),ESI_num,0xFF,"PUSH ",size, st); + size = impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_second),EAX_num,0x8F,"POP ",size, st); src_second_rc = dst_second_rc = rc_bad; // flag as already moved the second bits } // move low bits - size = impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_first),ESI_num,0xFF,"PUSH ",size); - size = impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_first),EAX_num,0x8F,"POP ",size); + size = impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_first),ESI_num,0xFF,"PUSH ",size, st); + size = impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_first),EAX_num,0x8F,"POP ",size, st); if( src_second_rc == rc_stack && dst_second_rc == rc_stack ) { // mov second bits - size = impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_second),ESI_num,0xFF,"PUSH ",size); - size = impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_second),EAX_num,0x8F,"POP ",size); + size = impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_second),ESI_num,0xFF,"PUSH ",size, st); + size = impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_second),EAX_num,0x8F,"POP ",size, st); } return size; } @@ -909,15 +911,15 @@ // -------------------------------------- // Check for integer reg-reg copy if( src_first_rc == rc_int && dst_first_rc == rc_int ) - size = impl_mov_helper(cbuf,do_size,src_first,dst_first,size); + size = impl_mov_helper(cbuf,do_size,src_first,dst_first,size, st); // Check for integer store if( src_first_rc == rc_int && dst_first_rc == rc_stack ) - size = impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_first),src_first,0x89,"MOV ",size); + size = impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_first),src_first,0x89,"MOV ",size, st); // Check for integer load if( dst_first_rc == rc_int && src_first_rc == rc_stack ) - size = impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_first),dst_first,0x8B,"MOV ",size); + size = impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_first),dst_first,0x8B,"MOV ",size, st); // -------------------------------------- // Check for float reg-reg copy @@ -951,7 +953,7 @@ // Check for float store if( src_first_rc == rc_float && dst_first_rc == rc_stack ) { - return impl_fp_store_helper(cbuf,do_size,src_first,src_second,dst_first,dst_second,ra_->reg2offset(dst_first),size); + return impl_fp_store_helper(cbuf,do_size,src_first,src_second,dst_first,dst_second,ra_->reg2offset(dst_first),size, st); } // Check for float load @@ -987,17 +989,17 @@ assert( (src_second_rc == rc_bad && dst_second_rc == rc_bad) || (src_first+1 == src_second && dst_first+1 == dst_second), "no non-adjacent float-moves" ); - return impl_movx_helper(cbuf,do_size,src_first,dst_first,src_second, dst_second, size); + return impl_movx_helper(cbuf,do_size,src_first,dst_first,src_second, dst_second, size, st); } // Check for xmm store if( src_first_rc == rc_xmm && dst_first_rc == rc_stack ) { - return impl_x_helper(cbuf,do_size,false,ra_->reg2offset(dst_first),src_first, src_second, size); + return impl_x_helper(cbuf,do_size,false,ra_->reg2offset(dst_first),src_first, src_second, size, st); } // Check for float xmm load if( dst_first_rc == rc_xmm && src_first_rc == rc_stack ) { - return impl_x_helper(cbuf,do_size,true ,ra_->reg2offset(src_first),dst_first, dst_second, size); + return impl_x_helper(cbuf,do_size,true ,ra_->reg2offset(src_first),dst_first, dst_second, size, st); } // Copy from float reg to xmm reg @@ -1017,10 +1019,10 @@ } size += 4; - size = impl_fp_store_helper(cbuf,do_size,src_first,src_second,dst_first,dst_second,0,size); + size = impl_fp_store_helper(cbuf,do_size,src_first,src_second,dst_first,dst_second,0,size, st); // Copy from the temp memory to the xmm reg. - size = impl_x_helper(cbuf,do_size,true ,0,dst_first, dst_second, size); + size = impl_x_helper(cbuf,do_size,true ,0,dst_first, dst_second, size, st); if( cbuf ) { emit_opcode(*cbuf,0x8D); // LEA ESP,[ESP+8] @@ -1047,15 +1049,15 @@ // Check for second word int-int move if( src_second_rc == rc_int && dst_second_rc == rc_int ) - return impl_mov_helper(cbuf,do_size,src_second,dst_second,size); + return impl_mov_helper(cbuf,do_size,src_second,dst_second,size, st); // Check for second word integer store if( src_second_rc == rc_int && dst_second_rc == rc_stack ) - return impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_second),src_second,0x89,"MOV ",size); + return impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_second),src_second,0x89,"MOV ",size, st); // Check for second word integer load if( dst_second_rc == rc_int && src_second_rc == rc_stack ) - return impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_second),dst_second,0x8B,"MOV ",size); + return impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_second),dst_second,0x8B,"MOV ",size, st); Unimplemented(); @@ -1318,7 +1320,11 @@ // // NOTE: If the platform does not provide any short branch variants, then // this method should return false for offset 0. -bool Matcher::is_short_branch_offset(int offset) { +bool Matcher::is_short_branch_offset(int rule, int offset) { + // the short version of jmpConUCF2 contains multiple branches, + // making the reach slightly less + if (rule == jmpConUCF2_rule) + return (-126 <= offset && offset <= 125); return (-128 <= offset && offset <= 127); } @@ -5272,6 +5278,15 @@ interface(REG_INTER); %} +operand eFlagsRegUCF() %{ + constraint(ALLOC_IN_RC(int_flags)); + match(RegFlags); + predicate(false); + + format %{ "EFLAGS_U_CF" %} + interface(REG_INTER); +%} + // Condition Code Register used by long compare operand flagsReg_long_LTGE() %{ constraint(ALLOC_IN_RC(int_flags)); @@ -5749,12 +5764,12 @@ format %{ "" %} interface(COND_INTER) %{ - equal(0x4); - not_equal(0x5); - less(0xC); - greater_equal(0xD); - less_equal(0xE); - greater(0xF); + equal(0x4, "e"); + not_equal(0x5, "ne"); + less(0xC, "l"); + greater_equal(0xD, "ge"); + less_equal(0xE, "le"); + greater(0xF, "g"); %} %} @@ -5766,12 +5781,47 @@ format %{ "" %} interface(COND_INTER) %{ - equal(0x4); - not_equal(0x5); - less(0x2); - greater_equal(0x3); - less_equal(0x6); - greater(0x7); + equal(0x4, "e"); + not_equal(0x5, "ne"); + less(0x2, "b"); + greater_equal(0x3, "nb"); + less_equal(0x6, "be"); + greater(0x7, "nbe"); + %} +%} + +// Floating comparisons that don't require any fixup for the unordered case +operand cmpOpUCF() %{ + match(Bool); + predicate(n->as_Bool()->_test._test == BoolTest::lt || + n->as_Bool()->_test._test == BoolTest::ge || + n->as_Bool()->_test._test == BoolTest::le || + n->as_Bool()->_test._test == BoolTest::gt); + format %{ "" %} + interface(COND_INTER) %{ + equal(0x4, "e"); + not_equal(0x5, "ne"); + less(0x2, "b"); + greater_equal(0x3, "nb"); + less_equal(0x6, "be"); + greater(0x7, "nbe"); + %} +%} + + +// Floating comparisons that can be fixed up with extra conditional jumps +operand cmpOpUCF2() %{ + match(Bool); + predicate(n->as_Bool()->_test._test == BoolTest::ne || + n->as_Bool()->_test._test == BoolTest::eq); + format %{ "" %} + interface(COND_INTER) %{ + equal(0x4, "e"); + not_equal(0x5, "ne"); + less(0x2, "b"); + greater_equal(0x3, "nb"); + less_equal(0x6, "be"); + greater(0x7, "nbe"); %} %} @@ -5796,12 +5846,12 @@ format %{ "" %} interface(COND_INTER) %{ - equal(0x4); - not_equal(0x5); - less(0xF); - greater_equal(0xE); - less_equal(0xD); - greater(0xC); + equal(0x4, "e"); + not_equal(0x5, "ne"); + less(0xF, "g"); + greater_equal(0xE, "le"); + less_equal(0xD, "ge"); + greater(0xC, "l"); %} %} @@ -7357,7 +7407,7 @@ ins_pipe( pipe_cmov_reg ); %} -instruct cmovI_regU( eRegI dst, eRegI src, eFlagsRegU cr, cmpOpU cop ) %{ +instruct cmovI_regU( cmpOpU cop, eFlagsRegU cr, eRegI dst, eRegI src ) %{ predicate(VM_Version::supports_cmov() ); match(Set dst (CMoveI (Binary cop cr) (Binary dst src))); ins_cost(200); @@ -7367,6 +7417,15 @@ ins_pipe( pipe_cmov_reg ); %} +instruct cmovI_regUCF( cmpOpUCF cop, eFlagsRegUCF cr, eRegI dst, eRegI src ) %{ + predicate(VM_Version::supports_cmov() ); + match(Set dst (CMoveI (Binary cop cr) (Binary dst src))); + ins_cost(200); + expand %{ + cmovI_regU(cop, cr, dst, src); + %} +%} + // Conditional move instruct cmovI_mem(cmpOp cop, eFlagsReg cr, eRegI dst, memory src) %{ predicate(VM_Version::supports_cmov() ); @@ -7379,7 +7438,7 @@ %} // Conditional move -instruct cmovI_memu(cmpOpU cop, eFlagsRegU cr, eRegI dst, memory src) %{ +instruct cmovI_memU(cmpOpU cop, eFlagsRegU cr, eRegI dst, memory src) %{ predicate(VM_Version::supports_cmov() ); match(Set dst (CMoveI (Binary cop cr) (Binary dst (LoadI src)))); ins_cost(250); @@ -7389,6 +7448,15 @@ ins_pipe( pipe_cmov_mem ); %} +instruct cmovI_memUCF(cmpOpUCF cop, eFlagsRegUCF cr, eRegI dst, memory src) %{ + predicate(VM_Version::supports_cmov() ); + match(Set dst (CMoveI (Binary cop cr) (Binary dst (LoadI src)))); + ins_cost(250); + expand %{ + cmovI_memU(cop, cr, dst, src); + %} +%} + // Conditional move instruct cmovP_reg(eRegP dst, eRegP src, eFlagsReg cr, cmpOp cop ) %{ predicate(VM_Version::supports_cmov() ); @@ -7416,7 +7484,7 @@ %} // Conditional move -instruct cmovP_regU(eRegP dst, eRegP src, eFlagsRegU cr, cmpOpU cop ) %{ +instruct cmovP_regU(cmpOpU cop, eFlagsRegU cr, eRegP dst, eRegP src ) %{ predicate(VM_Version::supports_cmov() ); match(Set dst (CMoveP (Binary cop cr) (Binary dst src))); ins_cost(200); @@ -7426,6 +7494,15 @@ ins_pipe( pipe_cmov_reg ); %} +instruct cmovP_regUCF(cmpOpUCF cop, eFlagsRegUCF cr, eRegP dst, eRegP src ) %{ + predicate(VM_Version::supports_cmov() ); + match(Set dst (CMoveP (Binary cop cr) (Binary dst src))); + ins_cost(200); + expand %{ + cmovP_regU(cop, cr, dst, src); + %} +%} + // DISABLED: Requires the ADLC to emit a bottom_type call that // correctly meets the two pointer arguments; one is an incoming // register but the other is a memory operand. ALSO appears to @@ -7555,6 +7632,15 @@ ins_pipe( pipe_slow ); %} +instruct fcmovX_regUCF(cmpOpUCF cop, eFlagsRegUCF cr, regX dst, regX src) %{ + predicate (UseSSE>=1); + match(Set dst (CMoveF (Binary cop cr) (Binary dst src))); + ins_cost(200); + expand %{ + fcmovX_regU(cop, cr, dst, src); + %} +%} + // unsigned version instruct fcmovXD_regU(cmpOpU cop, eFlagsRegU cr, regXD dst, regXD src) %{ predicate (UseSSE>=2); @@ -7573,6 +7659,15 @@ ins_pipe( pipe_slow ); %} +instruct fcmovXD_regUCF(cmpOpUCF cop, eFlagsRegUCF cr, regXD dst, regXD src) %{ + predicate (UseSSE>=2); + match(Set dst (CMoveD (Binary cop cr) (Binary dst src))); + ins_cost(200); + expand %{ + fcmovXD_regU(cop, cr, dst, src); + %} +%} + instruct cmovL_reg(cmpOp cop, eFlagsReg cr, eRegL dst, eRegL src) %{ predicate(VM_Version::supports_cmov() ); match(Set dst (CMoveL (Binary cop cr) (Binary dst src))); @@ -7595,6 +7690,15 @@ ins_pipe( pipe_cmov_reg_long ); %} +instruct cmovL_regUCF(cmpOpUCF cop, eFlagsRegUCF cr, eRegL dst, eRegL src) %{ + predicate(VM_Version::supports_cmov() ); + match(Set dst (CMoveL (Binary cop cr) (Binary dst src))); + ins_cost(200); + expand %{ + cmovL_regU(cop, cr, dst, src); + %} +%} + //----------Arithmetic Instructions-------------------------------------------- //----------Addition Instructions---------------------------------------------- // Integer Addition Instructions @@ -9200,6 +9304,18 @@ ins_pipe( pipe_slow ); %} +instruct cmpD_cc_P6CF(eFlagsRegUCF cr, regD src1, regD src2) %{ + predicate(VM_Version::supports_cmov() && UseSSE <=1); + match(Set cr (CmpD src1 src2)); + ins_cost(150); + format %{ "FLD $src1\n\t" + "FUCOMIP ST,$src2 // P6 instruction" %} + opcode(0xDF, 0x05); /* DF E8+i or DF /5 */ + ins_encode( Push_Reg_D(src1), + OpcP, RegOpc(src2)); + ins_pipe( pipe_slow ); +%} + // Compare & branch instruct cmpD_cc(eFlagsRegU cr, regD src1, regD src2, eAXRegI rax) %{ predicate(UseSSE<=1); @@ -9264,6 +9380,16 @@ ins_pipe( pipe_slow ); %} +instruct cmpXD_ccCF(eFlagsRegUCF cr, regXD dst, regXD src) %{ + predicate(UseSSE>=2); + match(Set cr (CmpD dst src)); + ins_cost(100); + format %{ "COMISD $dst,$src" %} + opcode(0x66, 0x0F, 0x2F); + ins_encode(OpcP, OpcS, Opcode(tertiary), RegReg(dst, src)); + ins_pipe( pipe_slow ); +%} + // float compare and set condition codes in EFLAGS by XMM regs instruct cmpXD_ccmem(eFlagsRegU cr, regXD dst, memory src, eAXRegI rax) %{ predicate(UseSSE>=2); @@ -9280,6 +9406,16 @@ ins_pipe( pipe_slow ); %} +instruct cmpXD_ccmemCF(eFlagsRegUCF cr, regXD dst, memory src) %{ + predicate(UseSSE>=2); + match(Set cr (CmpD dst (LoadD src))); + ins_cost(100); + format %{ "COMISD $dst,$src" %} + opcode(0x66, 0x0F, 0x2F); + ins_encode(OpcP, OpcS, Opcode(tertiary), RegMem(dst, src)); + ins_pipe( pipe_slow ); +%} + // Compare into -1,0,1 in XMM instruct cmpXD_reg(eRegI dst, regXD src1, regXD src2, eFlagsReg cr) %{ predicate(UseSSE>=2); @@ -10167,6 +10303,18 @@ ins_pipe( pipe_slow ); %} +instruct cmpF_cc_P6CF(eFlagsRegUCF cr, regF src1, regF src2) %{ + predicate(VM_Version::supports_cmov() && UseSSE == 0); + match(Set cr (CmpF src1 src2)); + ins_cost(100); + format %{ "FLD $src1\n\t" + "FUCOMIP ST,$src2 // P6 instruction" %} + opcode(0xDF, 0x05); /* DF E8+i or DF /5 */ + ins_encode( Push_Reg_D(src1), + OpcP, RegOpc(src2)); + ins_pipe( pipe_slow ); +%} + // Compare & branch instruct cmpF_cc(eFlagsRegU cr, regF src1, regF src2, eAXRegI rax) %{ @@ -10232,6 +10380,16 @@ ins_pipe( pipe_slow ); %} +instruct cmpX_ccCF(eFlagsRegUCF cr, regX dst, regX src) %{ + predicate(UseSSE>=1); + match(Set cr (CmpF dst src)); + ins_cost(100); + format %{ "COMISS $dst,$src" %} + opcode(0x0F, 0x2F); + ins_encode(OpcP, OpcS, RegReg(dst, src)); + ins_pipe( pipe_slow ); +%} + // float compare and set condition codes in EFLAGS by XMM regs instruct cmpX_ccmem(eFlagsRegU cr, regX dst, memory src, eAXRegI rax) %{ predicate(UseSSE>=1); @@ -10248,6 +10406,16 @@ ins_pipe( pipe_slow ); %} +instruct cmpX_ccmemCF(eFlagsRegUCF cr, regX dst, memory src) %{ + predicate(UseSSE>=1); + match(Set cr (CmpF dst (LoadF src))); + ins_cost(100); + format %{ "COMISS $dst,$src" %} + opcode(0x0F, 0x2F); + ins_encode(OpcP, OpcS, RegMem(dst, src)); + ins_pipe( pipe_slow ); +%} + // Compare into -1,0,1 in XMM instruct cmpX_reg(eRegI dst, regX src1, regX src2, eFlagsReg cr) %{ predicate(UseSSE>=1); @@ -12099,6 +12267,19 @@ ins_pc_relative(1); %} +instruct jmpLoopEndUCF(cmpOpUCF cop, eFlagsRegUCF cmp, label labl) %{ + match(CountedLoopEnd cop cmp); + effect(USE labl); + + ins_cost(200); + format %{ "J$cop,u $labl\t# Loop end" %} + size(6); + opcode(0x0F, 0x80); + ins_encode( Jcc( cop, labl) ); + ins_pipe( pipe_jcc ); + ins_pc_relative(1); +%} + // Jump Direct Conditional - using unsigned comparison instruct jmpConU(cmpOpU cop, eFlagsRegU cmp, label labl) %{ match(If cop cmp); @@ -12108,8 +12289,63 @@ format %{ "J$cop,u $labl" %} size(6); opcode(0x0F, 0x80); - ins_encode( Jcc( cop, labl) ); - ins_pipe( pipe_jcc ); + ins_encode(Jcc(cop, labl)); + ins_pipe(pipe_jcc); + ins_pc_relative(1); +%} + +instruct jmpConUCF(cmpOpUCF cop, eFlagsRegUCF cmp, label labl) %{ + match(If cop cmp); + effect(USE labl); + + ins_cost(200); + format %{ "J$cop,u $labl" %} + size(6); + opcode(0x0F, 0x80); + ins_encode(Jcc(cop, labl)); + ins_pipe(pipe_jcc); + ins_pc_relative(1); +%} + +instruct jmpConUCF2(cmpOpUCF2 cop, eFlagsRegUCF cmp, label labl) %{ + match(If cop cmp); + effect(USE labl); + + ins_cost(200); + format %{ $$template + if ($cop$$cmpcode == Assembler::notEqual) { + $$emit$$"JP,u $labl\n\t" + $$emit$$"J$cop,u $labl" + } else { + $$emit$$"JP,u done\n\t" + $$emit$$"J$cop,u $labl\n\t" + $$emit$$"done:" + } + %} + size(12); + opcode(0x0F, 0x80); + ins_encode %{ + Label* l = $labl$$label; + $$$emit8$primary; + emit_cc(cbuf, $secondary, Assembler::parity); + int parity_disp = -1; + bool ok = false; + if ($cop$$cmpcode == Assembler::notEqual) { + // the two jumps 6 bytes apart so the jump distances are too + parity_disp = l ? (l->loc_pos() - (cbuf.code_size() + 4)) : 0; + } else if ($cop$$cmpcode == Assembler::equal) { + parity_disp = 6; + ok = true; + } else { + ShouldNotReachHere(); + } + emit_d32(cbuf, parity_disp); + $$$emit8$primary; + emit_cc(cbuf, $secondary, $cop$$cmpcode); + int disp = l ? (l->loc_pos() - (cbuf.code_size() + 4)) : 0; + emit_d32(cbuf, disp); + %} + ins_pipe(pipe_jcc); ins_pc_relative(1); %} @@ -12208,7 +12444,7 @@ effect(USE labl); ins_cost(300); - format %{ "J$cop,s $labl" %} + format %{ "J$cop,s $labl\t# Loop end" %} size(2); opcode(0x70); ins_encode( JccShort( cop, labl) ); @@ -12223,7 +12459,21 @@ effect(USE labl); ins_cost(300); - format %{ "J$cop,us $labl" %} + format %{ "J$cop,us $labl\t# Loop end" %} + size(2); + opcode(0x70); + ins_encode( JccShort( cop, labl) ); + ins_pipe( pipe_jcc ); + ins_pc_relative(1); + ins_short_branch(1); +%} + +instruct jmpLoopEndUCF_short(cmpOpUCF cop, eFlagsRegUCF cmp, label labl) %{ + match(CountedLoopEnd cop cmp); + effect(USE labl); + + ins_cost(300); + format %{ "J$cop,us $labl\t# Loop end" %} size(2); opcode(0x70); ins_encode( JccShort( cop, labl) ); @@ -12247,6 +12497,60 @@ ins_short_branch(1); %} +instruct jmpConUCF_short(cmpOpUCF cop, eFlagsRegUCF cmp, label labl) %{ + match(If cop cmp); + effect(USE labl); + + ins_cost(300); + format %{ "J$cop,us $labl" %} + size(2); + opcode(0x70); + ins_encode( JccShort( cop, labl) ); + ins_pipe( pipe_jcc ); + ins_pc_relative(1); + ins_short_branch(1); +%} + +instruct jmpConUCF2_short(cmpOpUCF2 cop, eFlagsRegUCF cmp, label labl) %{ + match(If cop cmp); + effect(USE labl); + + ins_cost(300); + format %{ $$template + if ($cop$$cmpcode == Assembler::notEqual) { + $$emit$$"JP,u,s $labl\n\t" + $$emit$$"J$cop,u,s $labl" + } else { + $$emit$$"JP,u,s done\n\t" + $$emit$$"J$cop,u,s $labl\n\t" + $$emit$$"done:" + } + %} + size(4); + opcode(0x70); + ins_encode %{ + Label* l = $labl$$label; + emit_cc(cbuf, $primary, Assembler::parity); + int parity_disp = -1; + if ($cop$$cmpcode == Assembler::notEqual) { + parity_disp = l ? (l->loc_pos() - (cbuf.code_size() + 1)) : 0; + } else if ($cop$$cmpcode == Assembler::equal) { + parity_disp = 2; + } else { + ShouldNotReachHere(); + } + emit_d8(cbuf, parity_disp); + emit_cc(cbuf, $primary, $cop$$cmpcode); + int disp = l ? (l->loc_pos() - (cbuf.code_size() + 1)) : 0; + emit_d8(cbuf, disp); + assert(-128 <= disp && disp <= 127, "Displacement too large for short jmp"); + assert(-128 <= parity_disp && parity_disp <= 127, "Displacement too large for short jmp"); + %} + ins_pipe(pipe_jcc); + ins_pc_relative(1); + ins_short_branch(1); +%} + // ============================================================================ // Long Compare // diff -r 812e89e3d769 -r 128fe18951ed hotspot/src/cpu/x86/vm/x86_64.ad --- a/hotspot/src/cpu/x86/vm/x86_64.ad Tue Oct 21 11:23:52 2008 -0700 +++ b/hotspot/src/cpu/x86/vm/x86_64.ad Tue Oct 28 09:31:30 2008 -0700 @@ -2004,9 +2004,12 @@ // // NOTE: If the platform does not provide any short branch variants, then // this method should return false for offset 0. -bool Matcher::is_short_branch_offset(int offset) -{ - return -0x80 <= offset && offset < 0x80; +bool Matcher::is_short_branch_offset(int rule, int offset) { + // the short version of jmpConUCF2 contains multiple branches, + // making the reach slightly less + if (rule == jmpConUCF2_rule) + return (-126 <= offset && offset <= 125); + return (-128 <= offset && offset <= 127); } const bool Matcher::isSimpleConstant64(jlong value) { @@ -5134,6 +5137,15 @@ interface(REG_INTER); %} +operand rFlagsRegUCF() %{ + constraint(ALLOC_IN_RC(int_flags)); + match(RegFlags); + predicate(false); + + format %{ "RFLAGS_U_CF" %} + interface(REG_INTER); +%} + // Float register operands operand regF() %{ @@ -5405,12 +5417,12 @@ format %{ "" %} interface(COND_INTER) %{ - equal(0x4); - not_equal(0x5); - less(0xC); - greater_equal(0xD); - less_equal(0xE); - greater(0xF); + equal(0x4, "e"); + not_equal(0x5, "ne"); + less(0xC, "l"); + greater_equal(0xD, "ge"); + less_equal(0xE, "le"); + greater(0xF, "g"); %} %} @@ -5423,12 +5435,48 @@ format %{ "" %} interface(COND_INTER) %{ - equal(0x4); - not_equal(0x5); - less(0x2); - greater_equal(0x3); - less_equal(0x6); - greater(0x7); + equal(0x4, "e"); + not_equal(0x5, "ne"); + less(0x2, "b"); + greater_equal(0x3, "nb"); + less_equal(0x6, "be"); + greater(0x7, "nbe"); + %} +%} + + +// Floating comparisons that don't require any fixup for the unordered case +operand cmpOpUCF() %{ + match(Bool); + predicate(n->as_Bool()->_test._test == BoolTest::lt || + n->as_Bool()->_test._test == BoolTest::ge || + n->as_Bool()->_test._test == BoolTest::le || + n->as_Bool()->_test._test == BoolTest::gt); + format %{ "" %} + interface(COND_INTER) %{ + equal(0x4, "e"); + not_equal(0x5, "ne"); + less(0x2, "b"); + greater_equal(0x3, "nb"); + less_equal(0x6, "be"); + greater(0x7, "nbe"); + %} +%} + + +// Floating comparisons that can be fixed up with extra conditional jumps +operand cmpOpUCF2() %{ + match(Bool); + predicate(n->as_Bool()->_test._test == BoolTest::ne || + n->as_Bool()->_test._test == BoolTest::eq); + format %{ "" %} + interface(COND_INTER) %{ + equal(0x4, "e"); + not_equal(0x5, "ne"); + less(0x2, "b"); + greater_equal(0x3, "nb"); + less_equal(0x6, "be"); + greater(0x7, "nbe"); %} %} @@ -7176,8 +7224,7 @@ ins_pipe(pipe_cmov_reg); %} -instruct cmovI_regU(rRegI dst, rRegI src, rFlagsRegU cr, cmpOpU cop) -%{ +instruct cmovI_regU(cmpOpU cop, rFlagsRegU cr, rRegI dst, rRegI src) %{ match(Set dst (CMoveI (Binary cop cr) (Binary dst src))); ins_cost(200); // XXX @@ -7187,9 +7234,16 @@ ins_pipe(pipe_cmov_reg); %} +instruct cmovI_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegI dst, rRegI src) %{ + match(Set dst (CMoveI (Binary cop cr) (Binary dst src))); + ins_cost(200); + expand %{ + cmovI_regU(cop, cr, dst, src); + %} +%} + // Conditional move -instruct cmovI_mem(cmpOp cop, rFlagsReg cr, rRegI dst, memory src) -%{ +instruct cmovI_mem(cmpOp cop, rFlagsReg cr, rRegI dst, memory src) %{ match(Set dst (CMoveI (Binary cop cr) (Binary dst (LoadI src)))); ins_cost(250); // XXX @@ -7211,6 +7265,14 @@ ins_pipe(pipe_cmov_mem); %} +instruct cmovI_memUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegI dst, memory src) %{ + match(Set dst (CMoveI (Binary cop cr) (Binary dst (LoadI src)))); + ins_cost(250); + expand %{ + cmovI_memU(cop, cr, dst, src); + %} +%} + // Conditional move instruct cmovN_reg(rRegN dst, rRegN src, rFlagsReg cr, cmpOp cop) %{ @@ -7224,7 +7286,7 @@ %} // Conditional move -instruct cmovN_regU(rRegN dst, rRegN src, rFlagsRegU cr, cmpOpU cop) +instruct cmovN_regU(cmpOpU cop, rFlagsRegU cr, rRegN dst, rRegN src) %{ match(Set dst (CMoveN (Binary cop cr) (Binary dst src))); @@ -7235,6 +7297,14 @@ ins_pipe(pipe_cmov_reg); %} +instruct cmovN_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegN dst, rRegN src) %{ + match(Set dst (CMoveN (Binary cop cr) (Binary dst src))); + ins_cost(200); + expand %{ + cmovN_regU(cop, cr, dst, src); + %} +%} + // Conditional move instruct cmovP_reg(rRegP dst, rRegP src, rFlagsReg cr, cmpOp cop) %{ @@ -7248,7 +7318,7 @@ %} // Conditional move -instruct cmovP_regU(rRegP dst, rRegP src, rFlagsRegU cr, cmpOpU cop) +instruct cmovP_regU(cmpOpU cop, rFlagsRegU cr, rRegP dst, rRegP src) %{ match(Set dst (CMoveP (Binary cop cr) (Binary dst src))); @@ -7259,6 +7329,14 @@ ins_pipe(pipe_cmov_reg); // XXX %} +instruct cmovP_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegP dst, rRegP src) %{ + match(Set dst (CMoveP (Binary cop cr) (Binary dst src))); + ins_cost(200); + expand %{ + cmovP_regU(cop, cr, dst, src); + %} +%} + // DISABLED: Requires the ADLC to emit a bottom_type call that // correctly meets the two pointer arguments; one is an incoming // register but the other is a memory operand. ALSO appears to @@ -7319,6 +7397,14 @@ ins_pipe(pipe_cmov_reg); // XXX %} +instruct cmovL_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegL dst, rRegL src) %{ + match(Set dst (CMoveL (Binary cop cr) (Binary dst src))); + ins_cost(200); + expand %{ + cmovL_regU(cop, cr, dst, src); + %} +%} + instruct cmovL_memU(cmpOpU cop, rFlagsRegU cr, rRegL dst, memory src) %{ match(Set dst (CMoveL (Binary cop cr) (Binary dst (LoadL src)))); @@ -7330,6 +7416,14 @@ ins_pipe(pipe_cmov_mem); // XXX %} +instruct cmovL_memUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegL dst, memory src) %{ + match(Set dst (CMoveL (Binary cop cr) (Binary dst (LoadL src)))); + ins_cost(200); + expand %{ + cmovL_memU(cop, cr, dst, src); + %} +%} + instruct cmovF_reg(cmpOp cop, rFlagsReg cr, regF dst, regF src) %{ match(Set dst (CMoveF (Binary cop cr) (Binary dst src))); @@ -7366,6 +7460,14 @@ ins_pipe(pipe_slow); %} +instruct cmovF_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, regF dst, regF src) %{ + match(Set dst (CMoveF (Binary cop cr) (Binary dst src))); + ins_cost(200); + expand %{ + cmovF_regU(cop, cr, dst, src); + %} +%} + instruct cmovD_reg(cmpOp cop, rFlagsReg cr, regD dst, regD src) %{ match(Set dst (CMoveD (Binary cop cr) (Binary dst src))); @@ -7390,6 +7492,14 @@ ins_pipe(pipe_slow); %} +instruct cmovD_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, regD dst, regD src) %{ + match(Set dst (CMoveD (Binary cop cr) (Binary dst src))); + ins_cost(200); + expand %{ + cmovD_regU(cop, cr, dst, src); + %} +%} + //----------Arithmetic Instructions-------------------------------------------- //----------Addition Instructions---------------------------------------------- @@ -9716,6 +9826,17 @@ ins_pipe(pipe_slow); %} +instruct cmpF_cc_reg_CF(rFlagsRegUCF cr, regF src1, regF src2) %{ + match(Set cr (CmpF src1 src2)); + + ins_cost(145); + format %{ "ucomiss $src1, $src2" %} + ins_encode %{ + __ ucomiss($src1$$XMMRegister, $src2$$XMMRegister); + %} + ins_pipe(pipe_slow); +%} + instruct cmpF_cc_mem(rFlagsRegU cr, regF src1, memory src2) %{ match(Set cr (CmpF src1 (LoadF src2))); @@ -9733,6 +9854,16 @@ ins_pipe(pipe_slow); %} +instruct cmpF_cc_memCF(rFlagsRegUCF cr, regF src1, memory src2) %{ + match(Set cr (CmpF src1 (LoadF src2))); + + ins_cost(100); + format %{ "ucomiss $src1, $src2" %} + opcode(0x0F, 0x2E); + ins_encode(REX_reg_mem(src1, src2), OpcP, OpcS, reg_mem(src1, src2)); + ins_pipe(pipe_slow); +%} + instruct cmpF_cc_imm(rFlagsRegU cr, regF src1, immF src2) %{ match(Set cr (CmpF src1 src2)); @@ -9750,6 +9881,16 @@ ins_pipe(pipe_slow); %} +instruct cmpF_cc_immCF(rFlagsRegUCF cr, regF src1, immF src2) %{ + match(Set cr (CmpF src1 src2)); + + ins_cost(100); + format %{ "ucomiss $src1, $src2" %} + opcode(0x0F, 0x2E); + ins_encode(REX_reg_mem(src1, src2), OpcP, OpcS, load_immF(src1, src2)); + ins_pipe(pipe_slow); +%} + instruct cmpD_cc_reg(rFlagsRegU cr, regD src1, regD src2) %{ match(Set cr (CmpD src1 src2)); @@ -9767,6 +9908,17 @@ ins_pipe(pipe_slow); %} +instruct cmpD_cc_reg_CF(rFlagsRegUCF cr, regD src1, regD src2) %{ + match(Set cr (CmpD src1 src2)); + + ins_cost(100); + format %{ "ucomisd $src1, $src2 test" %} + ins_encode %{ + __ ucomisd($src1$$XMMRegister, $src2$$XMMRegister); + %} + ins_pipe(pipe_slow); +%} + instruct cmpD_cc_mem(rFlagsRegU cr, regD src1, memory src2) %{ match(Set cr (CmpD src1 (LoadD src2))); @@ -9784,6 +9936,16 @@ ins_pipe(pipe_slow); %} +instruct cmpD_cc_memCF(rFlagsRegUCF cr, regD src1, memory src2) %{ + match(Set cr (CmpD src1 (LoadD src2))); + + ins_cost(100); + format %{ "ucomisd $src1, $src2" %} + opcode(0x66, 0x0F, 0x2E); + ins_encode(OpcP, REX_reg_mem(src1, src2), OpcS, OpcT, reg_mem(src1, src2)); + ins_pipe(pipe_slow); +%} + instruct cmpD_cc_imm(rFlagsRegU cr, regD src1, immD src2) %{ match(Set cr (CmpD src1 src2)); @@ -9801,6 +9963,16 @@ ins_pipe(pipe_slow); %} +instruct cmpD_cc_immCF(rFlagsRegUCF cr, regD src1, immD src2) %{ + match(Set cr (CmpD src1 src2)); + + ins_cost(100); + format %{ "ucomisd $src1, [$src2]" %} + opcode(0x66, 0x0F, 0x2E); + ins_encode(OpcP, REX_reg_mem(src1, src2), OpcS, OpcT, load_immD(src1, src2)); + ins_pipe(pipe_slow); +%} + // Compare into -1,0,1 instruct cmpF_reg(rRegI dst, regF src1, regF src2, rFlagsReg cr) %{ @@ -11406,8 +11578,7 @@ %} // Jump Direct Conditional - Label defines a relative address from Jcc+1 -instruct jmpLoopEndU(cmpOpU cop, rFlagsRegU cmp, label labl) -%{ +instruct jmpLoopEndU(cmpOpU cop, rFlagsRegU cmp, label labl) %{ match(CountedLoopEnd cop cmp); effect(USE labl); @@ -11420,14 +11591,39 @@ ins_pc_relative(1); %} +instruct jmpLoopEndUCF(cmpOpUCF cop, rFlagsRegUCF cmp, label labl) %{ + match(CountedLoopEnd cop cmp); + effect(USE labl); + + ins_cost(200); + format %{ "j$cop,u $labl\t# loop end" %} + size(6); + opcode(0x0F, 0x80); + ins_encode(Jcc(cop, labl)); + ins_pipe(pipe_jcc); + ins_pc_relative(1); +%} + // Jump Direct Conditional - using unsigned comparison -instruct jmpConU(cmpOpU cop, rFlagsRegU cmp, label labl) -%{ +instruct jmpConU(cmpOpU cop, rFlagsRegU cmp, label labl) %{ match(If cop cmp); effect(USE labl); ins_cost(300); - format %{ "j$cop,u $labl" %} + format %{ "j$cop,u $labl" %} + size(6); + opcode(0x0F, 0x80); + ins_encode(Jcc(cop, labl)); + ins_pipe(pipe_jcc); + ins_pc_relative(1); +%} + +instruct jmpConUCF(cmpOpUCF cop, rFlagsRegUCF cmp, label labl) %{ + match(If cop cmp); + effect(USE labl); + + ins_cost(200); + format %{ "j$cop,u $labl" %} size(6); opcode(0x0F, 0x80); ins_encode(Jcc(cop, labl)); @@ -11435,6 +11631,46 @@ ins_pc_relative(1); %} +instruct jmpConUCF2(cmpOpUCF2 cop, rFlagsRegUCF cmp, label labl) %{ + match(If cop cmp); + effect(USE labl); + + ins_cost(200); + format %{ $$template + if ($cop$$cmpcode == Assembler::notEqual) { + $$emit$$"jp,u $labl\n\t" + $$emit$$"j$cop,u $labl" + } else { + $$emit$$"jp,u done\n\t" + $$emit$$"j$cop,u $labl\n\t" + $$emit$$"done:" + } + %} + size(12); + opcode(0x0F, 0x80); + ins_encode %{ + Label* l = $labl$$label; + $$$emit8$primary; + emit_cc(cbuf, $secondary, Assembler::parity); + int parity_disp = -1; + if ($cop$$cmpcode == Assembler::notEqual) { + // the two jumps 6 bytes apart so the jump distances are too + parity_disp = l ? (l->loc_pos() - (cbuf.code_size() + 4)) : 0; + } else if ($cop$$cmpcode == Assembler::equal) { + parity_disp = 6; + } else { + ShouldNotReachHere(); + } + emit_d32(cbuf, parity_disp); + $$$emit8$primary; + emit_cc(cbuf, $secondary, $cop$$cmpcode); + int disp = l ? (l->loc_pos() - (cbuf.code_size() + 4)) : 0; + emit_d32(cbuf, disp); + %} + ins_pipe(pipe_jcc); + ins_pc_relative(1); +%} + // ============================================================================ // The 2nd slow-half of a subtype check. Scan the subklass's 2ndary // superklass array for an instance of the superklass. Set a hidden @@ -11505,8 +11741,7 @@ // specific code section of the file. // Jump Direct - Label defines a relative address from JMP+1 -instruct jmpDir_short(label labl) -%{ +instruct jmpDir_short(label labl) %{ match(Goto); effect(USE labl); @@ -11521,8 +11756,7 @@ %} // Jump Direct Conditional - Label defines a relative address from Jcc+1 -instruct jmpCon_short(cmpOp cop, rFlagsReg cr, label labl) -%{ +instruct jmpCon_short(cmpOp cop, rFlagsReg cr, label labl) %{ match(If cop cr); effect(USE labl); @@ -11537,13 +11771,12 @@ %} // Jump Direct Conditional - Label defines a relative address from Jcc+1 -instruct jmpLoopEnd_short(cmpOp cop, rFlagsReg cr, label labl) -%{ +instruct jmpLoopEnd_short(cmpOp cop, rFlagsReg cr, label labl) %{ match(CountedLoopEnd cop cr); effect(USE labl); ins_cost(300); - format %{ "j$cop,s $labl" %} + format %{ "j$cop,s $labl\t# loop end" %} size(2); opcode(0x70); ins_encode(JccShort(cop, labl)); @@ -11553,12 +11786,40 @@ %} // Jump Direct Conditional - Label defines a relative address from Jcc+1 -instruct jmpLoopEndU_short(cmpOpU cop, rFlagsRegU cmp, label labl) -%{ +instruct jmpLoopEndU_short(cmpOpU cop, rFlagsRegU cmp, label labl) %{ + match(CountedLoopEnd cop cmp); + effect(USE labl); + + ins_cost(300); + format %{ "j$cop,us $labl\t# loop end" %} + size(2); + opcode(0x70); + ins_encode(JccShort(cop, labl)); + ins_pipe(pipe_jcc); + ins_pc_relative(1); + ins_short_branch(1); +%} + +instruct jmpLoopEndUCF_short(cmpOpUCF cop, rFlagsRegUCF cmp, label labl) %{ match(CountedLoopEnd cop cmp); effect(USE labl); ins_cost(300); + format %{ "j$cop,us $labl\t# loop end" %} + size(2); + opcode(0x70); + ins_encode(JccShort(cop, labl)); + ins_pipe(pipe_jcc); + ins_pc_relative(1); + ins_short_branch(1); +%} + +// Jump Direct Conditional - using unsigned comparison +instruct jmpConU_short(cmpOpU cop, rFlagsRegU cmp, label labl) %{ + match(If cop cmp); + effect(USE labl); + + ins_cost(300); format %{ "j$cop,us $labl" %} size(2); opcode(0x70); @@ -11568,9 +11829,7 @@ ins_short_branch(1); %} -// Jump Direct Conditional - using unsigned comparison -instruct jmpConU_short(cmpOpU cop, rFlagsRegU cmp, label labl) -%{ +instruct jmpConUCF_short(cmpOpUCF cop, rFlagsRegUCF cmp, label labl) %{ match(If cop cmp); effect(USE labl); @@ -11584,6 +11843,46 @@ ins_short_branch(1); %} +instruct jmpConUCF2_short(cmpOpUCF2 cop, rFlagsRegUCF cmp, label labl) %{ + match(If cop cmp); + effect(USE labl); + + ins_cost(300); + format %{ $$template + if ($cop$$cmpcode == Assembler::notEqual) { + $$emit$$"jp,u,s $labl\n\t" + $$emit$$"j$cop,u,s $labl" + } else { + $$emit$$"jp,u,s done\n\t" + $$emit$$"j$cop,u,s $labl\n\t" + $$emit$$"done:" + } + %} + size(4); + opcode(0x70); + ins_encode %{ + Label* l = $labl$$label; + emit_cc(cbuf, $primary, Assembler::parity); + int parity_disp = -1; + if ($cop$$cmpcode == Assembler::notEqual) { + parity_disp = l ? (l->loc_pos() - (cbuf.code_size() + 1)) : 0; + } else if ($cop$$cmpcode == Assembler::equal) { + parity_disp = 2; + } else { + ShouldNotReachHere(); + } + emit_d8(cbuf, parity_disp); + emit_cc(cbuf, $primary, $cop$$cmpcode); + int disp = l ? (l->loc_pos() - (cbuf.code_size() + 1)) : 0; + emit_d8(cbuf, disp); + assert(-128 <= disp && disp <= 127, "Displacement too large for short jmp"); + assert(-128 <= parity_disp && parity_disp <= 127, "Displacement too large for short jmp"); + %} + ins_pipe(pipe_jcc); + ins_pc_relative(1); + ins_short_branch(1); +%} + // ============================================================================ // inlined locking and unlocking diff -r 812e89e3d769 -r 128fe18951ed hotspot/src/share/vm/adlc/adlparse.cpp --- a/hotspot/src/share/vm/adlc/adlparse.cpp Tue Oct 21 11:23:52 2008 -0700 +++ b/hotspot/src/share/vm/adlc/adlparse.cpp Tue Oct 28 09:31:30 2008 -0700 @@ -33,7 +33,6 @@ _globalNames(archDesc.globalNames()) { _AD._syntax_errs = _AD._semantic_errs = 0; // No errors so far this file _AD._warnings = 0; // No warnings either - _linenum = 0; // Will increment to first line _curline = _ptr = NULL; // No pointers into buffer yet _preproc_depth = 0; @@ -76,7 +75,7 @@ } if (!_AD._quiet_mode) fprintf(stderr,"-----------------------------------------------------------------------------\n"); - _AD._TotalLines += _linenum-1; // -1 for overshoot in "nextline" routine + _AD._TotalLines += linenum()-1; // -1 for overshoot in "nextline" routine // Write out information we have stored // // UNIXism == fsync(stderr); @@ -148,7 +147,7 @@ if( (ident = get_unique_ident(_globalNames,"instruction")) == NULL ) return; instr = new InstructForm(ident); // Create new instruction form - instr->_linenum = _linenum; + instr->_linenum = linenum(); _globalNames.Insert(ident, instr); // Add name to the name table // Debugging Stuff if (_AD._adl_debug > 1) @@ -404,7 +403,7 @@ if( (ident = get_unique_ident(_globalNames,"operand")) == NULL ) return; oper = new OperandForm(ident); // Create new operand form - oper->_linenum = _linenum; + oper->_linenum = linenum(); _globalNames.Insert(ident, oper); // Add name to the name table // Debugging Stuff @@ -774,7 +773,7 @@ // Create the RegisterForm for the architecture description. RegisterForm *regBlock = new RegisterForm(); // Build new Source object - regBlock->_linenum = _linenum; + regBlock->_linenum = linenum(); _AD.addForm(regBlock); skipws(); // Skip leading whitespace @@ -847,7 +846,7 @@ } EncClass *encoding = _AD._encode->add_EncClass(ec_name); - encoding->_linenum = _linenum; + encoding->_linenum = linenum(); skipws(); // Skip leading whitespace // Check for optional parameter list @@ -905,7 +904,7 @@ // Prepend location descriptor, for debugging; cf. ADLParser::find_cpp_block if (_AD._adlocation_debug) { const char* file = _AD._ADL_file._name; - int line = _linenum; + int line = linenum(); char* location = (char *)malloc(strlen(file) + 100); sprintf(location, "#line %d \"%s\"\n", line, file); encoding->add_code(location); @@ -2776,7 +2775,7 @@ assert(_AD._encode->encClass(ec_name) == NULL, "shouldn't already exist"); EncClass *encoding = _AD._encode->add_EncClass(ec_name); - encoding->_linenum = _linenum; + encoding->_linenum = linenum(); // synthesize the arguments list for the enc_class from the // arguments to the instruct definition. @@ -2852,7 +2851,7 @@ skipws(); InsEncode *encrule = new InsEncode(); // Encode class for instruction - encrule->_linenum = _linenum; + encrule->_linenum = linenum(); char *ec_name = NULL; // String representation of encode rule // identifier is optional. while (_curchar != ')') { @@ -3203,6 +3202,12 @@ char *greater_equal; char *less_equal; char *greater; + const char *equal_format = "eq"; + const char *not_equal_format = "ne"; + const char *less_format = "lt"; + const char *greater_equal_format = "ge"; + const char *less_equal_format = "le"; + const char *greater_format = "gt"; if (_curchar != '%') { parse_err(SYNERR, "Missing '%{' for 'cond_interface' block.\n"); @@ -3222,22 +3227,22 @@ return NULL; } if ( strcmp(field,"equal") == 0 ) { - equal = interface_field_parse(); + equal = interface_field_parse(&equal_format); } else if ( strcmp(field,"not_equal") == 0 ) { - not_equal = interface_field_parse(); + not_equal = interface_field_parse(¬_equal_format); } else if ( strcmp(field,"less") == 0 ) { - less = interface_field_parse(); + less = interface_field_parse(&less_format); } else if ( strcmp(field,"greater_equal") == 0 ) { - greater_equal = interface_field_parse(); + greater_equal = interface_field_parse(&greater_equal_format); } else if ( strcmp(field,"less_equal") == 0 ) { - less_equal = interface_field_parse(); + less_equal = interface_field_parse(&less_equal_format); } else if ( strcmp(field,"greater") == 0 ) { - greater = interface_field_parse(); + greater = interface_field_parse(&greater_format); } else { parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%}' ending interface.\n"); @@ -3252,14 +3257,18 @@ next_char(); // Skip '}' // Construct desired object and return - Interface *inter = new CondInterface(equal, not_equal, less, greater_equal, - less_equal, greater); + Interface *inter = new CondInterface(equal, equal_format, + not_equal, not_equal_format, + less, less_format, + greater_equal, greater_equal_format, + less_equal, less_equal_format, + greater, greater_format); return inter; } //------------------------------interface_field_parse-------------------------- -char *ADLParser::interface_field_parse(void) { +char *ADLParser::interface_field_parse(const char ** format) { char *iface_field = NULL; // Get interface field @@ -3280,6 +3289,32 @@ return NULL; } skipws(); + if (format != NULL && _curchar == ',') { + next_char(); + skipws(); + if (_curchar != '"') { + parse_err(SYNERR, "Missing '\"' in field format .\n"); + return NULL; + } + next_char(); + char *start = _ptr; // Record start of the next string + while ((_curchar != '"') && (_curchar != '%') && (_curchar != '\n')) { + if (_curchar == '\\') next_char(); // superquote + if (_curchar == '\n') parse_err(SYNERR, "newline in string"); // unimplemented! + next_char(); + } + if (_curchar != '"') { + parse_err(SYNERR, "Missing '\"' at end of field format .\n"); + return NULL; + } + // If a string was found, terminate it and record in FormatRule + if ( start != _ptr ) { + *_ptr = '\0'; // Terminate the string + *format = start; + } + next_char(); + skipws(); + } if (_curchar != ')') { parse_err(SYNERR, "Missing ')' after interface field.\n"); return NULL; @@ -3342,6 +3377,12 @@ next_char(); // Move past the '{' skipws(); + if (_curchar == '$') { + char* ident = get_rep_var_ident(); + if (strcmp(ident, "$$template") == 0) return template_parse(); + parse_err(SYNERR, "Unknown \"%s\" directive in format", ident); + return NULL; + } // Check for the opening '"' inside the format description if ( _curchar == '"' ) { next_char(); // Move past the initial '"' @@ -3433,6 +3474,131 @@ } +//------------------------------template_parse----------------------------------- +FormatRule* ADLParser::template_parse(void) { + char *desc = NULL; + FormatRule *format = (new FormatRule(desc)); + + skipws(); + while ( (_curchar != '%') && (*(_ptr+1) != '}') ) { + + // (1) + // Check if there is a string to pass through to output + char *start = _ptr; // Record start of the next string + while ((_curchar != '$') && ((_curchar != '%') || (*(_ptr+1) != '}')) ) { + // If at the start of a comment, skip past it + if( (_curchar == '/') && ((*(_ptr+1) == '/') || (*(_ptr+1) == '*')) ) { + skipws_no_preproc(); + } else { + // ELSE advance to the next character, or start of the next line + next_char_or_line(); + } + } + // If a string was found, terminate it and record in EncClass + if ( start != _ptr ) { + *_ptr = '\0'; // Terminate the string + // Add flag to _strings list indicating we should check _rep_vars + format->_strings.addName(NameList::_signal2); + format->_strings.addName(start); + } + + // (2) + // If we are at a replacement variable, + // copy it and record in EncClass + if ( _curchar == '$' ) { + // Found replacement Variable + char *rep_var = get_rep_var_ident_dup(); + if (strcmp(rep_var, "$emit") == 0) { + // switch to normal format parsing + next_char(); + next_char(); + skipws(); + // Check for the opening '"' inside the format description + if ( _curchar == '"' ) { + next_char(); // Move past the initial '"' + if( _curchar == '"' ) { // Handle empty format string case + *_ptr = '\0'; // Terminate empty string + format->_strings.addName(_ptr); + } + + // Collect the parts of the format description + // (1) strings that are passed through to tty->print + // (2) replacement/substitution variable, preceeded by a '$' + // (3) multi-token ANSIY C style strings + while ( true ) { + if ( _curchar == '%' || _curchar == '\n' ) { + parse_err(SYNERR, "missing '\"' at end of format block"); + return NULL; + } + + // (1) + // Check if there is a string to pass through to output + char *start = _ptr; // Record start of the next string + while ((_curchar != '$') && (_curchar != '"') && (_curchar != '%') && (_curchar != '\n')) { + if (_curchar == '\\') next_char(); // superquote + if (_curchar == '\n') parse_err(SYNERR, "newline in string"); // unimplemented! + next_char(); + } + // If a string was found, terminate it and record in FormatRule + if ( start != _ptr ) { + *_ptr = '\0'; // Terminate the string + format->_strings.addName(start); + } + + // (2) + // If we are at a replacement variable, + // copy it and record in FormatRule + if ( _curchar == '$' ) { + next_char(); // Move past the '$' + char* rep_var = get_ident(); // Nil terminate the variable name + rep_var = strdup(rep_var);// Copy the string + *_ptr = _curchar; // and replace Nil with original character + format->_rep_vars.addName(rep_var); + // Add flag to _strings list indicating we should check _rep_vars + format->_strings.addName(NameList::_signal); + } + + // (3) + // Allow very long strings to be broken up, + // using the ANSI C syntax "foo\n" "bar" + if ( _curchar == '"') { + next_char(); // Move past the '"' + skipws(); // Skip white space before next string token + if ( _curchar != '"') { + break; + } else { + // Found one. Skip both " and the whitespace in between. + next_char(); + } + } + } // end while part of format description + } + } else { + // Add flag to _strings list indicating we should check _rep_vars + format->_rep_vars.addName(rep_var); + // Add flag to _strings list indicating we should check _rep_vars + format->_strings.addName(NameList::_signal3); + } + } // end while part of format description + } + + skipws(); + // Past format description, at '%' + if ( _curchar != '%' || *(_ptr+1) != '}' ) { + parse_err(SYNERR, "missing '%}' at end of format block"); + return NULL; + } + next_char(); // Move past the '%' + next_char(); // Move past the '}' + + // Debug Stuff + if (_AD._adl_debug > 1) fprintf(stderr,"Format Rule: %s\n", desc); + + skipws(); + return format; +} + + //------------------------------effect_parse----------------------------------- void ADLParser::effect_parse(InstructForm *instr) { char* desc = NULL; @@ -3777,7 +3943,7 @@ skipws_no_preproc(); // Skip leading whitespace cppBlock = _ptr; // Point to start of expression const char* file = _AD._ADL_file._name; - int line = _linenum; + int line = linenum(); next = _ptr + 1; while(((_curchar != '%') || (*next != '}')) && (_curchar != '\0')) { next_char_or_line(); @@ -4297,11 +4463,11 @@ va_start(args, fmt); if (flag == 1) - _AD._syntax_errs += _AD.emit_msg(0, flag, _linenum, fmt, args); + _AD._syntax_errs += _AD.emit_msg(0, flag, linenum(), fmt, args); else if (flag == 2) - _AD._semantic_errs += _AD.emit_msg(0, flag, _linenum, fmt, args); + _AD._semantic_errs += _AD.emit_msg(0, flag, linenum(), fmt, args); else - _AD._warnings += _AD.emit_msg(0, flag, _linenum, fmt, args); + _AD._warnings += _AD.emit_msg(0, flag, linenum(), fmt, args); int error_char = _curchar; char* error_ptr = _ptr+1; @@ -4515,7 +4681,7 @@ //---------------------------next_line----------------------------------------- void ADLParser::next_line() { - _curline = _buf.get_line(); _linenum++; + _curline = _buf.get_line(); } //-------------------------is_literal_constant--------------------------------- diff -r 812e89e3d769 -r 128fe18951ed hotspot/src/share/vm/adlc/adlparse.hpp --- a/hotspot/src/share/vm/adlc/adlparse.hpp Tue Oct 21 11:23:52 2008 -0700 +++ b/hotspot/src/share/vm/adlc/adlparse.hpp Tue Oct 28 09:31:30 2008 -0700 @@ -70,7 +70,6 @@ protected: char *_curline; // Start of current line char *_ptr; // Pointer into current location in File Buffer - int _linenum; // Count of line numbers seen so far char _curchar; // Current character from buffer FormDict &_globalNames; // Global names @@ -160,9 +159,10 @@ Interface *interface_parse(); // Parse operand interface rule Interface *mem_interface_parse(); // Parse memory interface rule Interface *cond_interface_parse(); // Parse conditional interface rule - char *interface_field_parse();// Parse field contents + char *interface_field_parse(const char** format = NULL);// Parse field contents FormatRule *format_parse(void); // Parse format rule + FormatRule *template_parse(void); // Parse format rule void effect_parse(InstructForm *instr); // Parse effect rule ExpandRule *expand_parse(InstructForm *instr); // Parse expand rule RewriteRule *rewrite_parse(void); // Parse rewrite rule @@ -263,7 +263,7 @@ void parse(void); // Do the parsing & build forms lists - int getlines( ) { return _linenum; } + int linenum() { return _buf.linenum(); } static bool is_literal_constant(const char *hex_string); static bool is_hex_digit(char digit); diff -r 812e89e3d769 -r 128fe18951ed hotspot/src/share/vm/adlc/filebuff.cpp --- a/hotspot/src/share/vm/adlc/filebuff.cpp Tue Oct 21 11:23:52 2008 -0700 +++ b/hotspot/src/share/vm/adlc/filebuff.cpp Tue Oct 28 09:31:30 2008 -0700 @@ -41,6 +41,7 @@ exit(1); // Exit on seek error } _filepos = ftell(_fp->_fp); // Reset current file position + _linenum = 0; _bigbuf = new char[_bufferSize]; // Create buffer to hold text for parser if( !_bigbuf ) { @@ -76,6 +77,7 @@ // Check for end of file & return NULL if (_bufeol >= _bufmax) return NULL; + _linenum++; retval = ++_bufeol; // return character following end of previous line if (*retval == '\0') return NULL; // Check for EOF sentinal // Search for newline character which must end each line diff -r 812e89e3d769 -r 128fe18951ed hotspot/src/share/vm/adlc/filebuff.hpp --- a/hotspot/src/share/vm/adlc/filebuff.hpp Tue Oct 21 11:23:52 2008 -0700 +++ b/hotspot/src/share/vm/adlc/filebuff.hpp Tue Oct 28 09:31:30 2008 -0700 @@ -51,6 +51,7 @@ int _err; // Error flag for file seek/read operations long _filepos; // Current offset from start of file + int _linenum; ArchDesc& _AD; // Reference to Architecture Description @@ -66,6 +67,7 @@ // This returns a pointer to the start of the current line in the buffer, // and increments bufeol and filepos to point at the end of that line. char *get_line(void); + int linenum() const { return _linenum; } // This converts a pointer into the buffer to a file offset. It only works // when the pointer is valid (i.e. just obtained from getline()). diff -r 812e89e3d769 -r 128fe18951ed hotspot/src/share/vm/adlc/forms.cpp --- a/hotspot/src/share/vm/adlc/forms.cpp Tue Oct 21 11:23:52 2008 -0700 +++ b/hotspot/src/share/vm/adlc/forms.cpp Tue Oct 28 09:31:30 2008 -0700 @@ -35,6 +35,8 @@ //------------------------------NameList--------------------------------------- // reserved user-defined string const char *NameList::_signal = "$$SIGNAL$$"; +const char *NameList::_signal2 = "$$SIGNAL2$$"; +const char *NameList::_signal3 = "$$SIGNAL3$$"; // Constructor and Destructor NameList::NameList() : _cur(0), _max(4), _iter(0), _justReset(true) { diff -r 812e89e3d769 -r 128fe18951ed hotspot/src/share/vm/adlc/forms.hpp --- a/hotspot/src/share/vm/adlc/forms.hpp Tue Oct 21 11:23:52 2008 -0700 +++ b/hotspot/src/share/vm/adlc/forms.hpp Tue Oct 28 09:31:30 2008 -0700 @@ -329,6 +329,8 @@ public: static const char *_signal; // reserved user-defined string + static const char *_signal2; // reserved user-defined string + static const char *_signal3; // reserved user-defined string enum { Not_in_list = -1 }; void addName(const char *name); diff -r 812e89e3d769 -r 128fe18951ed hotspot/src/share/vm/adlc/formssel.cpp --- a/hotspot/src/share/vm/adlc/formssel.cpp Tue Oct 21 11:23:52 2008 -0700 +++ b/hotspot/src/share/vm/adlc/formssel.cpp Tue Oct 28 09:31:30 2008 -0700 @@ -1574,10 +1574,10 @@ return Opcode::NOT_AN_OPCODE; } -void Opcode::print_opcode(FILE *fp, Opcode::opcode_type desired_opcode) { +bool Opcode::print_opcode(FILE *fp, Opcode::opcode_type desired_opcode) { // Default values previously provided by MachNode::primary()... - const char *description = "default_opcode()"; - const char *value = "-1"; + const char *description = NULL; + const char *value = NULL; // Check if user provided any opcode definitions if( this != NULL ) { // Update 'value' if user provided a definition in the instruction @@ -1599,7 +1599,10 @@ break; } } - fprintf(fp, "(%s /*%s*/)", value, description); + if (value != NULL) { + fprintf(fp, "(%s /*%s*/)", value, description); + } + return value != NULL; } void Opcode::dump() { @@ -2610,14 +2613,19 @@ } //------------------------------CondInterface---------------------------------- -CondInterface::CondInterface(char *equal, char *not_equal, - char *less, char *greater_equal, - char *less_equal, char *greater) +CondInterface::CondInterface(const char* equal, const char* equal_format, + const char* not_equal, const char* not_equal_format, + const char* less, const char* less_format, + const char* greater_equal, const char* greater_equal_format, + const char* less_equal, const char* less_equal_format, + const char* greater, const char* greater_format) : Interface("COND_INTER"), - _equal(equal), _not_equal(not_equal), - _less(less), _greater_equal(greater_equal), - _less_equal(less_equal), _greater(greater) { - // + _equal(equal), _equal_format(equal_format), + _not_equal(not_equal), _not_equal_format(not_equal_format), + _less(less), _less_format(less_format), + _greater_equal(greater_equal), _greater_equal_format(greater_equal_format), + _less_equal(less_equal), _less_equal_format(less_equal_format), + _greater(greater), _greater_format(greater_format) { } CondInterface::~CondInterface() { // not owner of any character arrays diff -r 812e89e3d769 -r 128fe18951ed hotspot/src/share/vm/adlc/formssel.hpp --- a/hotspot/src/share/vm/adlc/formssel.hpp Tue Oct 21 11:23:52 2008 -0700 +++ b/hotspot/src/share/vm/adlc/formssel.hpp Tue Oct 28 09:31:30 2008 -0700 @@ -397,7 +397,7 @@ void output(FILE *fp); // --------------------------- FILE *output_routines - void print_opcode(FILE *fp, Opcode::opcode_type desired_opcode); + bool print_opcode(FILE *fp, Opcode::opcode_type desired_opcode); }; //------------------------------InsEncode-------------------------------------- @@ -779,10 +779,20 @@ const char *_greater_equal; const char *_less_equal; const char *_greater; + const char *_equal_format; + const char *_not_equal_format; + const char *_less_format; + const char *_greater_equal_format; + const char *_less_equal_format; + const char *_greater_format; // Public Methods - CondInterface(char *equal, char *not_equal, char *less, char *greater_equal, - char *less_equal, char *greater); + CondInterface(const char* equal, const char* equal_format, + const char* not_equal, const char* not_equal_format, + const char* less, const char* less_format, + const char* greater_equal, const char* greater_equal_format, + const char* less_equal, const char* less_equal_format, + const char* greater, const char* greater_format); ~CondInterface(); void dump(); diff -r 812e89e3d769 -r 128fe18951ed hotspot/src/share/vm/adlc/output_c.cpp --- a/hotspot/src/share/vm/adlc/output_c.cpp Tue Oct 21 11:23:52 2008 -0700 +++ b/hotspot/src/share/vm/adlc/output_c.cpp Tue Oct 28 09:31:30 2008 -0700 @@ -1619,6 +1619,7 @@ } // Iterate over the new instruction's operands + int prev_pos = -1; for( expand_instr->reset(); (opid = expand_instr->iter()) != NULL; ) { // Use 'parameter' at current position in list of new instruction's formals // instead of 'opid' when looking up info internal to new_inst @@ -1642,6 +1643,18 @@ // ins = (InstructForm *) _globalNames[new_id]; exp_pos = node->operand_position_format(opid); assert(exp_pos != -1, "Bad expand rule"); + if (prev_pos > exp_pos && expand_instruction->_matrule != NULL) { + // For the add_req calls below to work correctly they need + // to added in the same order that a match would add them. + // This means that they would need to be in the order of + // the components list instead of the formal parameters. + // This is a sort of hidden invariant that previously + // wasn't checked and could lead to incorrectly + // constructed nodes. + syntax_err(node->_linenum, "For expand in %s to work, parameter declaration order in %s must follow matchrule\n", + node->_ident, new_inst->_ident); + } + prev_pos = exp_pos; new_pos = new_inst->operand_position(parameter,Component::USE); if (new_pos != -1) { @@ -2306,7 +2319,12 @@ _processing_noninput = false; // A replacement variable, originally '$' if ( Opcode::as_opcode_type(rep_var) != Opcode::NOT_AN_OPCODE ) { - _inst._opcode->print_opcode(_fp, Opcode::as_opcode_type(rep_var) ); + if (!_inst._opcode->print_opcode(_fp, Opcode::as_opcode_type(rep_var) )) { + // Missing opcode + _AD.syntax_err( _inst._linenum, + "Missing $%s opcode definition in %s, used by encoding %s\n", + rep_var, _inst._ident, _encoding._name); + } } else { // Lookup its position in parameter list @@ -2348,7 +2366,13 @@ else if( Opcode::as_opcode_type(inst_rep_var) != Opcode::NOT_AN_OPCODE ) { // else check if "primary", "secondary", "tertiary" assert( _constant_status == LITERAL_ACCESSED, "Must be processing a literal constant parameter"); - _inst._opcode->print_opcode(_fp, Opcode::as_opcode_type(inst_rep_var) ); + if (!_inst._opcode->print_opcode(_fp, Opcode::as_opcode_type(inst_rep_var) )) { + // Missing opcode + _AD.syntax_err( _inst._linenum, + "Missing $%s opcode definition in %s\n", + rep_var, _inst._ident); + + } _constant_status = LITERAL_OUTPUT; } else if((_AD.get_registers() != NULL ) && (_AD.get_registers()->getRegDef(inst_rep_var) != NULL)) { diff -r 812e89e3d769 -r 128fe18951ed hotspot/src/share/vm/adlc/output_h.cpp --- a/hotspot/src/share/vm/adlc/output_h.cpp Tue Oct 21 11:23:52 2008 -0700 +++ b/hotspot/src/share/vm/adlc/output_h.cpp Tue Oct 28 09:31:30 2008 -0700 @@ -355,17 +355,19 @@ // --------------------------------------------------------------------------- // Generate the format rule for condition codes -static void defineCCodeDump(FILE *fp, int i) { - fprintf(fp, " if( _c%d == BoolTest::eq ) st->print(\"eq\");\n",i); - fprintf(fp, " else if( _c%d == BoolTest::ne ) st->print(\"ne\");\n",i); - fprintf(fp, " else if( _c%d == BoolTest::le ) st->print(\"le\");\n",i); - fprintf(fp, " else if( _c%d == BoolTest::ge ) st->print(\"ge\");\n",i); - fprintf(fp, " else if( _c%d == BoolTest::lt ) st->print(\"lt\");\n",i); - fprintf(fp, " else if( _c%d == BoolTest::gt ) st->print(\"gt\");\n",i); +static void defineCCodeDump(OperandForm* oper, FILE *fp, int i) { + assert(oper != NULL, "what"); + CondInterface* cond = oper->_interface->is_CondInterface(); + fprintf(fp, " if( _c%d == BoolTest::eq ) st->print(\"%s\");\n",i,cond->_equal_format); + fprintf(fp, " else if( _c%d == BoolTest::ne ) st->print(\"%s\");\n",i,cond->_not_equal_format); + fprintf(fp, " else if( _c%d == BoolTest::le ) st->print(\"%s\");\n",i,cond->_less_equal_format); + fprintf(fp, " else if( _c%d == BoolTest::ge ) st->print(\"%s\");\n",i,cond->_greater_equal_format); + fprintf(fp, " else if( _c%d == BoolTest::lt ) st->print(\"%s\");\n",i,cond->_less_format); + fprintf(fp, " else if( _c%d == BoolTest::gt ) st->print(\"%s\");\n",i,cond->_greater_format); } // Output code that dumps constant values, increment "i" if type is constant -static uint dump_spec_constant(FILE *fp, const char *ideal_type, uint i) { +static uint dump_spec_constant(FILE *fp, const char *ideal_type, uint i, OperandForm* oper) { if (!strcmp(ideal_type, "ConI")) { fprintf(fp," st->print(\"#%%d\", _c%d);\n", i); ++i; @@ -391,7 +393,7 @@ ++i; } else if (!strcmp(ideal_type, "Bool")) { - defineCCodeDump(fp,i); + defineCCodeDump(oper, fp,i); ++i; } @@ -476,7 +478,7 @@ } // ALWAYS! Provide a special case output for condition codes. if( oper.is_ideal_bool() ) { - defineCCodeDump(fp,0); + defineCCodeDump(&oper, fp,0); } fprintf(fp,"}\n"); @@ -549,7 +551,7 @@ } // ALWAYS! Provide a special case output for condition codes. if( oper.is_ideal_bool() ) { - defineCCodeDump(fp,0); + defineCCodeDump(&oper, fp,0); } fprintf(fp, "}\n"); fprintf(fp, "#endif\n"); @@ -583,10 +585,53 @@ while( (string = inst._format->_strings.iter()) != NULL ) { fprintf(fp," "); // Check if this is a standard string or a replacement variable - if( string != NameList::_signal ) // Normal string. Pass through. + if( string == NameList::_signal ) { // Replacement variable + const char* rep_var = inst._format->_rep_vars.iter(); + inst.rep_var_format( fp, rep_var); + } else if( string == NameList::_signal3 ) { // Replacement variable in raw text + const char* rep_var = inst._format->_rep_vars.iter(); + const Form *form = inst._localNames[rep_var]; + if (form == NULL) { + fprintf(stderr, "unknown replacement variable in format statement: '%s'\n", rep_var); + assert(false, "ShouldNotReachHere()"); + } + OpClassForm *opc = form->is_opclass(); + assert( opc, "replacement variable was not found in local names"); + // Lookup the index position of the replacement variable + int idx = inst.operand_position_format(rep_var); + if ( idx == -1 ) { + assert( strcmp(opc->_ident,"label")==0, "Unimplemented"); + assert( false, "ShouldNotReachHere()"); + } + + if (inst.is_noninput_operand(idx)) { + assert( false, "ShouldNotReachHere()"); + } else { + // Output the format call for this operand + fprintf(fp,"opnd_array(%d)",idx); + } + rep_var = inst._format->_rep_vars.iter(); + inst._format->_strings.iter(); + if ( strcmp(rep_var,"$constant") == 0 && opc->is_operand()) { + Form::DataType constant_type = form->is_operand()->is_base_constant(globals); + if ( constant_type == Form::idealD ) { + fprintf(fp,"->constantD()"); + } else if ( constant_type == Form::idealF ) { + fprintf(fp,"->constantF()"); + } else if ( constant_type == Form::idealL ) { + fprintf(fp,"->constantL()"); + } else { + fprintf(fp,"->constant()"); + } + } else if ( strcmp(rep_var,"$cmpcode") == 0) { + fprintf(fp,"->ccode()"); + } else { + assert( false, "ShouldNotReachHere()"); + } + } else if( string == NameList::_signal2 ) // Raw program text + fputs(inst._format->_strings.iter(), fp); + else fprintf(fp,"st->print(\"%s\");\n", string); - else // Replacement variable - inst.rep_var_format( fp, inst._format->_rep_vars.iter() ); } // Done with all format strings } // Done generating the user-defined portion of the format @@ -1404,7 +1449,7 @@ oper->_components.reset(); if ((comp = oper->_components.iter()) == NULL) { assert(num_consts == 1, "Bad component list detected.\n"); - i = dump_spec_constant( fp, type, i ); + i = dump_spec_constant( fp, type, i, oper ); // Check that type actually matched assert( i != 0, "Non-constant operand lacks component list."); } // end if NULL @@ -1414,7 +1459,7 @@ oper->_components.reset(); while((comp = oper->_components.iter()) != NULL) { type = comp->base_type(_globalNames); - i = dump_spec_constant( fp, type, i ); + i = dump_spec_constant( fp, type, i, NULL ); } } // finish line (3) diff -r 812e89e3d769 -r 128fe18951ed hotspot/src/share/vm/opto/matcher.hpp --- a/hotspot/src/share/vm/opto/matcher.hpp Tue Oct 21 11:23:52 2008 -0700 +++ b/hotspot/src/share/vm/opto/matcher.hpp Tue Oct 28 09:31:30 2008 -0700 @@ -324,7 +324,7 @@ virtual int regnum_to_fpu_offset(int regnum); // Is this branch offset small enough to be addressed by a short branch? - bool is_short_branch_offset(int offset); + bool is_short_branch_offset(int rule, int offset); // Optional scaling for the parameter to the ClearArray/CopyArray node. static const bool init_array_count_is_in_bytes; diff -r 812e89e3d769 -r 128fe18951ed hotspot/src/share/vm/opto/output.cpp --- a/hotspot/src/share/vm/opto/output.cpp Tue Oct 21 11:23:52 2008 -0700 +++ b/hotspot/src/share/vm/opto/output.cpp Tue Oct 28 09:31:30 2008 -0700 @@ -332,6 +332,7 @@ uint *jmp_end = NEW_RESOURCE_ARRAY(uint,_cfg->_num_blocks); uint *blk_starts = NEW_RESOURCE_ARRAY(uint,_cfg->_num_blocks+1); DEBUG_ONLY( uint *jmp_target = NEW_RESOURCE_ARRAY(uint,_cfg->_num_blocks); ) + DEBUG_ONLY( uint *jmp_rule = NEW_RESOURCE_ARRAY(uint,_cfg->_num_blocks); ) blk_starts[0] = 0; // Initialize the sizes to 0 @@ -443,9 +444,9 @@ uintptr_t target = blk_starts[bnum]; if( mach->is_pc_relative() ) { int offset = target-(blk_starts[i] + jmp_end[i]); - if (_matcher->is_short_branch_offset(offset)) { + if (_matcher->is_short_branch_offset(mach->rule(), offset)) { // We've got a winner. Replace this branch. - MachNode *replacement = mach->short_branch_version(this); + MachNode* replacement = mach->short_branch_version(this); b->_nodes.map(j, replacement); mach->subsume_by(replacement); @@ -453,6 +454,7 @@ // next pass. jmp_end[i] -= (mach->size(_regalloc) - replacement->size(_regalloc)); DEBUG_ONLY( jmp_target[i] = bnum; ); + DEBUG_ONLY( jmp_rule[i] = mach->rule(); ); } } else { #ifndef PRODUCT @@ -524,10 +526,10 @@ for( i=0; i<_cfg->_num_blocks; i++ ) { // For all blocks if( jmp_target[i] != 0 ) { int offset = blk_starts[jmp_target[i]]-(blk_starts[i] + jmp_end[i]); - if (!_matcher->is_short_branch_offset(offset)) { + if (!_matcher->is_short_branch_offset(jmp_rule[i], offset)) { tty->print_cr("target (%d) - jmp_end(%d) = offset (%d), jmp_block B%d, target_block B%d", blk_starts[jmp_target[i]], blk_starts[i] + jmp_end[i], offset, i, jmp_target[i]); } - assert(_matcher->is_short_branch_offset(offset), "Displacement too large for short jmp"); + assert(_matcher->is_short_branch_offset(jmp_rule[i], offset), "Displacement too large for short jmp"); } } #endif @@ -1069,7 +1071,7 @@ // If this machine supports different size branch offsets, then pre-compute // the length of the blocks - if( _matcher->is_short_branch_offset(0) ) { + if( _matcher->is_short_branch_offset(-1, 0) ) { Shorten_branches(blk_labels, code_req, locs_req, stub_req, const_req); labels_not_set = false; } diff -r 812e89e3d769 -r 128fe18951ed hotspot/src/share/vm/opto/reg_split.cpp --- a/hotspot/src/share/vm/opto/reg_split.cpp Tue Oct 21 11:23:52 2008 -0700 +++ b/hotspot/src/share/vm/opto/reg_split.cpp Tue Oct 28 09:31:30 2008 -0700 @@ -53,6 +53,7 @@ // Bail rather than abort int ireg = def->ideal_reg(); if( ireg == 0 || ireg == Op_RegFlags ) { + assert(false, "attempted to spill a non-spillable item"); C->record_method_not_compilable("attempted to spill a non-spillable item"); return NULL; }