From: Dave G. <dgr...@us...> - 2006-07-18 19:51:37
|
Update of /cvsroot/jikesrvm/rvm/src/vm/arch/intel/compilers/optimizing/ir/conversions/mir2mc In directory sc8-pr-cvs6.sourceforge.net:/tmp/cvs-serv14358/src/vm/arch/intel/compilers/optimizing/ir/conversions/mir2mc Modified Files: OPT_AssemblerBase.java Log Message: fix for bug 1494784: intermitent build failure on IA32 when patching short branches. Bug fixed by making the estimate of instruction size more precise in particular doing a much better job of modeling of memory operands Index: OPT_AssemblerBase.java =================================================================== RCS file: /cvsroot/jikesrvm/rvm/src/vm/arch/intel/compilers/optimizing/ir/conversions/mir2mc/OPT_AssemblerBase.java,v retrieving revision 1.25 retrieving revision 1.26 diff -C2 -d -r1.25 -r1.26 *** OPT_AssemblerBase.java 13 Jul 2006 14:50:03 -0000 1.25 --- OPT_AssemblerBase.java 18 Jul 2006 19:51:23 -0000 1.26 *************** *** 25,28 **** --- 25,46 ---- implements OPT_Operators, VM_Constants, OPT_PhysicalRegisterConstants { + private static final boolean DEBUG_ESTIMATE = false; + + /** + * Hold EBP register object for use in estimating size of memory operands. + * Having this in a static field is extremely hacky, but it's quite an + * annoying plumbing problem to pass an OPT_IR all the way down to + * the code that needs to get EBP, so this is probably the cleanest solution. + */ + private static OPT_Register EBP; + + /** + * Hold EBP register object for use in estimating size of memory operands. + * Having this in a static field is extremely hacky, but it's quite an + * annoying plumbing problem to pass an OPT_IR all the way down to + * the code that needs to get EBP, so this is probably the cleanest solution. + */ + private static OPT_Register ESP; + /** * This class requires no particular construction behavior; this *************** *** 503,511 **** private static int estimateSize(OPT_Instruction inst) { - int size = 0; switch (inst.getOpcode()) { case LABEL_opcode:case BBEND_opcode:case UNINT_BEGIN_opcode:case UNINT_END_opcode: // these generate no code ! break; // Generated from the same case in VM_Assembler --- 521,528 ---- private static int estimateSize(OPT_Instruction inst) { switch (inst.getOpcode()) { case LABEL_opcode:case BBEND_opcode:case UNINT_BEGIN_opcode:case UNINT_END_opcode: // these generate no code ! return 0; // Generated from the same case in VM_Assembler *************** *** 513,534 **** case IA32_OR_opcode:case IA32_SBB_opcode: case IA32_XOR_opcode: ! size += 2; // opcode + modr/m ! size += operandCost(MIR_BinaryAcc.getResult(inst), true); ! size += operandCost(MIR_BinaryAcc.getValue(inst), true); ! break; case IA32_CMP_opcode: ! size += 2; // opcode + modr/m ! size += operandCost(MIR_Compare.getVal1(inst), true); ! size += operandCost(MIR_Compare.getVal2(inst), true); ! break; case IA32_TEST_opcode: ! size += 2; // opcode + modr/m ! size += operandCost(MIR_Test.getVal1(inst), true); ! size += operandCost(MIR_Test.getVal2(inst), true); ! break; case IA32_PUSH_opcode: { OPT_Operand op = MIR_UnaryNoRes.getVal(inst); if (op instanceof OPT_RegisterOperand) { size += 1; --- 530,558 ---- case IA32_OR_opcode:case IA32_SBB_opcode: case IA32_XOR_opcode: ! { ! int size = 2; // opcode + modr/m ! size += operandCost(MIR_BinaryAcc.getResult(inst), true); ! size += operandCost(MIR_BinaryAcc.getValue(inst), true); ! return size; ! } case IA32_CMP_opcode: ! { ! int size = 2; // opcode + modr/m ! size += operandCost(MIR_Compare.getVal1(inst), true); ! size += operandCost(MIR_Compare.getVal2(inst), true); ! return size; ! } case IA32_TEST_opcode: ! { ! int size = 2; // opcode + modr/m ! size += operandCost(MIR_Test.getVal1(inst), true); ! size += operandCost(MIR_Test.getVal2(inst), true); ! return size; ! } case IA32_PUSH_opcode: { OPT_Operand op = MIR_UnaryNoRes.getVal(inst); + int size = 0; if (op instanceof OPT_RegisterOperand) { size += 1; *************** *** 542,594 **** size += (2+operandCost(op, true)); } } - break; case IA32_MOV_opcode: ! size += 2; // opcode + modr/m ! size += operandCost(MIR_Move.getResult(inst), false); ! size += operandCost(MIR_Move.getValue(inst), false); ! break; case IA32_OFFSET_opcode: ! size += 4; ! break; case IA32_JCC_opcode: case IA32_JMP_opcode: ! size += 6; // assume long form ! break; case IA32_LOCK_opcode: ! size += 1; ! break; case IG_PATCH_POINT_opcode: ! size += 6; ! break; case IA32_INT_opcode: ! size += 2; ! break; case IA32_RET_opcode: ! size += 3; ! break; default: ! size += 3; // 2 bytes opcode + 1 byte modr/m ! for (OPT_OperandEnumeration opEnum = inst.getRootOperands(); ! opEnum.hasMoreElements();) { ! OPT_Operand op = opEnum.next(); ! size += operandCost(op, false); } ! break; ! } ! return size; } private static int operandCost(OPT_Operand op, boolean shortFormImmediate) { if (op instanceof OPT_MemoryOperand) { - int cost = 1; // might need SIB byte OPT_MemoryOperand mop = (OPT_MemoryOperand)op; ! if (!mop.disp.isZero()) { if (fits(mop.disp,8)) { ! cost += 1; } else { ! cost += 4; } } ! return cost; } else if (op instanceof OPT_IntConstantOperand) { if (shortFormImmediate && fits(((OPT_IntConstantOperand)op).value,8)) { --- 566,675 ---- size += (2+operandCost(op, true)); } + return size; + } + case IA32_LEA_opcode: + { + int size = 2; // opcode + 1 byte modr/m + size += operandCost(MIR_Lea.getResult(inst), false); + size += operandCost(MIR_Lea.getValue(inst), false); + return size; } case IA32_MOV_opcode: ! { ! int size = 2; // opcode + modr/m ! OPT_Operand result = MIR_Move.getResult(inst); ! OPT_Operand value = MIR_Move.getValue(inst); ! size += operandCost(result, false); ! size += operandCost(value, false); ! return size; ! } case IA32_OFFSET_opcode: ! return 4; case IA32_JCC_opcode: case IA32_JMP_opcode: ! return 6; // assume long form case IA32_LOCK_opcode: ! return 1; case IG_PATCH_POINT_opcode: ! return 6; case IA32_INT_opcode: ! return 2; case IA32_RET_opcode: ! return 3; ! case IA32_CALL_opcode: ! OPT_Operand target = MIR_Call.getTarget(inst); ! if (isImmOrLabel(target)) { ! return 5; // opcode + 32bit immediate ! } else { ! return 2 + operandCost(target, false); // opcode + modr/m ! } default: ! { ! int size = 3; // 2 bytes opcode + 1 byte modr/m ! for (OPT_OperandEnumeration opEnum = inst.getRootOperands(); ! opEnum.hasMoreElements();) { ! OPT_Operand op = opEnum.next(); ! size += operandCost(op, false); ! } ! return size; } ! } } private static int operandCost(OPT_Operand op, boolean shortFormImmediate) { if (op instanceof OPT_MemoryOperand) { OPT_MemoryOperand mop = (OPT_MemoryOperand)op; ! // If it's a 2byte mem location, we're going to need an override prefix ! int prefix = mop.size == 2 ? 1 : 0; ! ! // Deal with EBP wierdness ! if (mop.base != null && mop.base.register == EBP) { ! if (mop.index != null) { ! // forced into SIB + 32 bit displacement no matter what disp is ! return prefix + 5; ! } if (fits(mop.disp,8)) { ! return prefix + 1; } else { ! return prefix + 4; } } ! if (mop.index != null && mop.index.register == EBP) { ! // forced into SIB + 32 bit displacement no matter what disp is ! return prefix + 5; ! } ! ! // Deal with ESP wierdness -- requires SIB byte even when index is null ! if (mop.base != null && mop.base.register == ESP) { ! if (fits(mop.disp,8)) { ! return prefix + 2; ! } else { ! return prefix + 5; ! } ! } ! ! if (mop.index == null) { ! // just displacement to worry about ! if (mop.disp.isZero()) { ! return prefix + 0; ! } else if (fits(mop.disp,8)) { ! return prefix + 1; ! } else { ! return prefix + 4; ! } ! } else { ! // have a SIB ! if (mop.base == null && mop.scale != 0) { ! // forced to 32 bit displacement even if it would fit in 8 ! return prefix + 5; ! } else { ! if (mop.disp.isZero()) { ! return prefix + 1; ! } else if (fits(mop.disp,8)) { ! return prefix + 2; ! } else { ! return prefix + 5; ! } ! } ! } } else if (op instanceof OPT_IntConstantOperand) { if (shortFormImmediate && fits(((OPT_IntConstantOperand)op).value,8)) { *************** *** 687,727 **** /** ! * generate machine code into ir.machinecode * @param ir the IR to generate * @param shouldPrint should we print the machine code? * @return the number of machinecode instructions generated */ ! public static final int generateCode(OPT_IR ir, boolean shouldPrint) { int count = 0; - - for (OPT_Instruction p = ir.firstInstructionInCodeOrder(); - p != null; p = p.nextInstructionInCodeOrder()) - { - p.setmcOffset( - ++count); - } - OPT_Assembler asm = new OPT_Assembler(count, shouldPrint); ! for (OPT_Instruction p = ir.firstInstructionInCodeOrder(); ! p != null; p = p.nextInstructionInCodeOrder()) ! { ! int start = asm.getMachineCodeIndex(); ! int estimate = estimateSize(p); ! try { asm.doInst(p); - } catch (RuntimeException e) { - System.err.println("Failed while assembling "+p.toString()); - ir.printInstructions(); int end = asm.getMachineCodeIndex(); ! if (start-end > estimate) { ! VM.sysWriteln("Bad estimate: "+(start-end)+" "+estimate+" "+p); } ! VM._assert(false); ! } ! int end = asm.getMachineCodeIndex(); ! if (start-end > estimate) { ! VM.sysWriteln("Bad estimate: "+(start-end)+" "+estimate+" "+p); } } ir.MIRInfo.machinecode = asm.getMachineCodes(); --- 768,812 ---- /** ! * generate machine code into ir.machinecode. ! * Synchronized to make the EBP hack thread safe...ugh. * @param ir the IR to generate * @param shouldPrint should we print the machine code? * @return the number of machinecode instructions generated */ ! public static synchronized int generateCode(OPT_IR ir, boolean shouldPrint) { int count = 0; OPT_Assembler asm = new OPT_Assembler(count, shouldPrint); ! for (OPT_Instruction p = ir.firstInstructionInCodeOrder(); ! p != null; p = p.nextInstructionInCodeOrder()) { ! p.setmcOffset( - ++count); ! } ! ! ! try { ! EBP = ir.regpool.getPhysicalRegisterSet().getEBP(); ! ESP = ir.regpool.getPhysicalRegisterSet().getESP(); ! ! for (OPT_Instruction p = ir.firstInstructionInCodeOrder(); ! p != null; p = p.nextInstructionInCodeOrder()) { ! if (DEBUG_ESTIMATE) { ! int start = asm.getMachineCodeIndex(); ! int estimate = estimateSize(p); asm.doInst(p); int end = asm.getMachineCodeIndex(); ! if (end-start > estimate) { ! VM.sysWriteln("Bad estimate: "+(end-start)+" "+estimate+" "+p); ! VM.sysWrite("\tMachine code: "); ! asm.writeLastInstruction(start); ! VM.sysWriteln(); } ! } else { ! asm.doInst(p); } } + } finally { + EBP = null; + ESP = null; + } ir.MIRInfo.machinecode = asm.getMachineCodes(); |