Mercurial > hg > truffle
diff src/cpu/x86/vm/x86_64.ad @ 344:6aae2f9d0294
Merge
author | ysr |
---|---|
date | Thu, 12 Jun 2008 13:50:55 -0700 |
parents | 44abbb0d4c18 |
children | d1605aabd0a1 1e026f8da827 |
line wrap: on
line diff
--- a/src/cpu/x86/vm/x86_64.ad Thu Jun 05 15:57:56 2008 -0700 +++ b/src/cpu/x86/vm/x86_64.ad Thu Jun 12 13:50:55 2008 -0700 @@ -3808,6 +3808,78 @@ masm.bind(DONE_LABEL); %} + enc_class enc_Array_Equals(rdi_RegP ary1, rsi_RegP ary2, rax_RegI tmp1, rbx_RegI tmp2, rcx_RegI result) %{ + Label TRUE_LABEL, FALSE_LABEL, DONE_LABEL, COMPARE_LOOP_HDR, COMPARE_LOOP; + MacroAssembler masm(&cbuf); + + Register ary1Reg = as_Register($ary1$$reg); + Register ary2Reg = as_Register($ary2$$reg); + Register tmp1Reg = as_Register($tmp1$$reg); + Register tmp2Reg = as_Register($tmp2$$reg); + Register resultReg = as_Register($result$$reg); + + int length_offset = arrayOopDesc::length_offset_in_bytes(); + int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); + + // Check the input args + masm.cmpq(ary1Reg, ary2Reg); + masm.jcc(Assembler::equal, TRUE_LABEL); + masm.testq(ary1Reg, ary1Reg); + masm.jcc(Assembler::zero, FALSE_LABEL); + masm.testq(ary2Reg, ary2Reg); + masm.jcc(Assembler::zero, FALSE_LABEL); + + // Check the lengths + masm.movl(tmp2Reg, Address(ary1Reg, length_offset)); + masm.movl(resultReg, Address(ary2Reg, length_offset)); + masm.cmpl(tmp2Reg, resultReg); + masm.jcc(Assembler::notEqual, FALSE_LABEL); + masm.testl(resultReg, resultReg); + masm.jcc(Assembler::zero, TRUE_LABEL); + + // Get the number of 4 byte vectors to compare + masm.shrl(resultReg, 1); + + // Check for odd-length arrays + masm.andl(tmp2Reg, 1); + masm.testl(tmp2Reg, tmp2Reg); + masm.jcc(Assembler::zero, COMPARE_LOOP_HDR); + + // Compare 2-byte "tail" at end of arrays + masm.load_unsigned_word(tmp1Reg, Address(ary1Reg, resultReg, Address::times_4, base_offset)); + masm.load_unsigned_word(tmp2Reg, Address(ary2Reg, resultReg, Address::times_4, base_offset)); + masm.cmpl(tmp1Reg, tmp2Reg); + masm.jcc(Assembler::notEqual, FALSE_LABEL); + masm.testl(resultReg, resultReg); + masm.jcc(Assembler::zero, TRUE_LABEL); + + // Setup compare loop + masm.bind(COMPARE_LOOP_HDR); + // Shift tmp1Reg and tmp2Reg to the last 4-byte boundary of the arrays + masm.leaq(tmp1Reg, Address(ary1Reg, resultReg, Address::times_4, base_offset)); + masm.leaq(tmp2Reg, Address(ary2Reg, resultReg, Address::times_4, base_offset)); + masm.negq(resultReg); + + // 4-byte-wide compare loop + masm.bind(COMPARE_LOOP); + masm.movl(ary1Reg, Address(tmp1Reg, resultReg, Address::times_4, 0)); + masm.movl(ary2Reg, Address(tmp2Reg, resultReg, Address::times_4, 0)); + masm.cmpl(ary1Reg, ary2Reg); + masm.jcc(Assembler::notEqual, FALSE_LABEL); + masm.incrementq(resultReg); + masm.jcc(Assembler::notZero, COMPARE_LOOP); + + masm.bind(TRUE_LABEL); + masm.movl(resultReg, 1); // return true + masm.jmp(DONE_LABEL); + + masm.bind(FALSE_LABEL); + masm.xorl(resultReg, resultReg); // return false + + // That's it + masm.bind(DONE_LABEL); + %} + enc_class enc_rethrow() %{ cbuf.set_inst_mark(); @@ -5202,15 +5274,15 @@ %} %} -// Indirect Memory Times Scale Plus Index Register Plus Offset Operand -operand indIndexScaleOffsetComp(rRegN src, immL32 off, r12RegL base) %{ +// Indirect Narrow Oop Plus Offset Operand +operand indNarrowOopOffset(rRegN src, immL32 off) %{ constraint(ALLOC_IN_RC(ptr_reg)); - match(AddP (DecodeN src base) off); + match(AddP (DecodeN src) off); op_cost(10); - format %{"[$base + $src << 3 + $off] (compressed)" %} + format %{"[R12 + $src << 3 + $off] (compressed oop addressing)" %} interface(MEMORY_INTER) %{ - base($base); + base(0xc); // R12 index($src); scale(0x3); disp($off); @@ -5365,7 +5437,7 @@ opclass memory(indirect, indOffset8, indOffset32, indIndexOffset, indIndex, indIndexScale, indIndexScaleOffset, indPosIndexScaleOffset, - indIndexScaleOffsetComp); + indNarrowOopOffset); //----------PIPELINE----------------------------------------------------------- // Rules which define the behavior of the target architectures pipeline. @@ -6044,10 +6116,9 @@ %} // Load Compressed Pointer -instruct loadN(rRegN dst, memory mem, rFlagsReg cr) +instruct loadN(rRegN dst, memory mem) %{ match(Set dst (LoadN mem)); - effect(KILL cr); ins_cost(125); // XXX format %{ "movl $dst, $mem\t# compressed ptr" %} @@ -6064,7 +6135,6 @@ instruct loadKlass(rRegP dst, memory mem) %{ match(Set dst (LoadKlass mem)); - predicate(!n->in(MemNode::Address)->bottom_type()->is_narrow()); ins_cost(125); // XXX format %{ "movq $dst, $mem\t# class" %} @@ -6073,22 +6143,17 @@ ins_pipe(ialu_reg_mem); // XXX %} -// Load Klass Pointer -instruct loadKlassComp(rRegP dst, memory mem) -%{ - match(Set dst (LoadKlass mem)); - predicate(n->in(MemNode::Address)->bottom_type()->is_narrow()); +// Load narrow Klass Pointer +instruct loadNKlass(rRegN dst, memory mem) +%{ + match(Set dst (LoadNKlass mem)); ins_cost(125); // XXX - format %{ "movl $dst, $mem\t# compressed class\n\t" - "decode_heap_oop $dst,$dst" %} + format %{ "movl $dst, $mem\t# compressed klass ptr" %} ins_encode %{ Address addr = build_address($mem$$base, $mem$$index, $mem$$scale, $mem$$disp); Register dst = as_Register($dst$$reg); __ movl(dst, addr); - // klass is never null in the header but this is generated for all - // klass loads not just the _klass field in the header. - __ decode_heap_oop(dst); %} ins_pipe(ialu_reg_mem); // XXX %} @@ -6362,16 +6427,14 @@ match(Set dst src); ins_cost(125); - format %{ "movq $dst, $src\t# compressed ptr\n\t" - "encode_heap_oop_not_null $dst,$dst" %} + format %{ "movl $dst, $src\t# compressed ptr" %} ins_encode %{ address con = (address)$src$$constant; Register dst = $dst$$Register; if (con == NULL) { ShouldNotReachHere(); } else { - __ movoop(dst, (jobject)$src$$constant); - __ encode_heap_oop_not_null(dst); + __ set_narrow_oop(dst, (jobject)$src$$constant); } %} ins_pipe(ialu_reg_fat); // XXX @@ -6633,13 +6696,12 @@ %} // Store Compressed Pointer -instruct storeN(memory mem, rRegN src, rFlagsReg cr) +instruct storeN(memory mem, rRegN src) %{ match(Set mem (StoreN mem src)); - effect(KILL cr); ins_cost(125); // XXX - format %{ "movl $mem, $src\t# ptr" %} + format %{ "movl $mem, $src\t# compressed ptr" %} ins_encode %{ Address addr = build_address($mem$$base, $mem$$index, $mem$$scale, $mem$$disp); Register src = as_Register($src$$reg); @@ -7027,7 +7089,8 @@ %} instruct decodeHeapOop(rRegP dst, rRegN src, rFlagsReg cr) %{ - predicate(n->bottom_type()->is_oopptr()->ptr() != TypePtr::NotNull); + predicate(n->bottom_type()->is_oopptr()->ptr() != TypePtr::NotNull && + n->bottom_type()->is_oopptr()->ptr() != TypePtr::Constant); match(Set dst (DecodeN src)); effect(KILL cr); format %{ "decode_heap_oop $dst,$src" %} @@ -7043,7 +7106,8 @@ %} instruct decodeHeapOop_not_null(rRegP dst, rRegN src) %{ - predicate(n->bottom_type()->is_oopptr()->ptr() == TypePtr::NotNull); + predicate(n->bottom_type()->is_oopptr()->ptr() == TypePtr::NotNull || + n->bottom_type()->is_oopptr()->ptr() == TypePtr::Constant); match(Set dst (DecodeN src)); format %{ "decode_heap_oop_not_null $dst,$src" %} ins_encode %{ @@ -7143,6 +7207,30 @@ %} // Conditional move +instruct cmovN_reg(rRegN dst, rRegN src, rFlagsReg cr, cmpOp cop) +%{ + match(Set dst (CMoveN (Binary cop cr) (Binary dst src))); + + ins_cost(200); // XXX + format %{ "cmovl$cop $dst, $src\t# signed, compressed ptr" %} + opcode(0x0F, 0x40); + ins_encode(REX_reg_reg(dst, src), enc_cmov(cop), reg_reg(dst, src)); + ins_pipe(pipe_cmov_reg); +%} + +// Conditional move +instruct cmovN_regU(rRegN dst, rRegN src, rFlagsRegU cr, cmpOpU cop) +%{ + match(Set dst (CMoveN (Binary cop cr) (Binary dst src))); + + ins_cost(200); // XXX + format %{ "cmovl$cop $dst, $src\t# unsigned, compressed ptr" %} + opcode(0x0F, 0x40); + ins_encode(REX_reg_reg(dst, src), enc_cmov(cop), reg_reg(dst, src)); + ins_pipe(pipe_cmov_reg); +%} + +// Conditional move instruct cmovP_reg(rRegP dst, rRegP src, rFlagsReg cr, cmpOp cop) %{ match(Set dst (CMoveP (Binary cop cr) (Binary dst src))); @@ -10862,6 +10950,18 @@ ins_pipe( pipe_slow ); %} +// fast array equals +instruct array_equals(rdi_RegP ary1, rsi_RegP ary2, rax_RegI tmp1, + rbx_RegI tmp2, rcx_RegI result, rFlagsReg cr) %{ + match(Set result (AryEq ary1 ary2)); + effect(USE_KILL ary1, USE_KILL ary2, KILL tmp1, KILL tmp2, KILL cr); + //ins_cost(300); + + format %{ "Array Equals $ary1,$ary2 -> $result // KILL RAX, RBX" %} + ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, result) ); + ins_pipe( pipe_slow ); +%} + //----------Control Flow Instructions------------------------------------------ // Signed compare Instructions @@ -11055,14 +11155,50 @@ ins_pipe(ialu_cr_reg_imm); %} + +instruct compN_rReg(rFlagsRegU cr, rRegN op1, rRegN op2) +%{ + match(Set cr (CmpN op1 op2)); + + format %{ "cmpl $op1, $op2\t# compressed ptr" %} + ins_encode %{ __ cmpl(as_Register($op1$$reg), as_Register($op2$$reg)); %} + ins_pipe(ialu_cr_reg_reg); +%} + +instruct compN_rReg_mem(rFlagsRegU cr, rRegN src, memory mem) +%{ + match(Set cr (CmpN src (LoadN mem))); + + ins_cost(500); // XXX + format %{ "cmpl $src, mem\t# compressed ptr" %} + ins_encode %{ + Address adr = build_address($mem$$base, $mem$$index, $mem$$scale, $mem$$disp); + __ cmpl(as_Register($src$$reg), adr); + %} + ins_pipe(ialu_cr_reg_mem); +%} + instruct testN_reg(rFlagsReg cr, rRegN src, immN0 zero) %{ match(Set cr (CmpN src zero)); - format %{ "testl $src, $src" %} + format %{ "testl $src, $src\t# compressed ptr" %} ins_encode %{ __ testl($src$$Register, $src$$Register); %} ins_pipe(ialu_cr_reg_imm); %} +instruct testN_reg_mem(rFlagsReg cr, memory mem, immN0 zero) +%{ + match(Set cr (CmpN (LoadN mem) zero)); + + ins_cost(500); // XXX + format %{ "testl $mem, 0xffffffff\t# compressed ptr" %} + ins_encode %{ + Address addr = build_address($mem$$base, $mem$$index, $mem$$scale, $mem$$disp); + __ cmpl(addr, (int)0xFFFFFFFF); + %} + ins_pipe(ialu_cr_reg_mem); +%} + // Yanked all unsigned pointer compare operations. // Pointer compares are done with CmpP which is already unsigned.