001 /* 002 * This file is part of the Jikes RVM project (http://jikesrvm.org). 003 * 004 * This file is licensed to You under the Eclipse Public License (EPL); 005 * You may not use this file except in compliance with the License. You 006 * may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/eclipse-1.0.php 009 * 010 * See the COPYRIGHT.txt file distributed with this work for information 011 * regarding copyright ownership. 012 */ 013 package org.jikesrvm.compilers.opt.lir2mir; 014 015 import static org.jikesrvm.SizeConstants.LOG_BYTES_IN_ADDRESS; 016 import static org.jikesrvm.compilers.opt.ir.Operators.ARRAYLENGTH_opcode; 017 import static org.jikesrvm.compilers.opt.ir.Operators.DOUBLE_2LONG_opcode; 018 import static org.jikesrvm.compilers.opt.ir.Operators.DOUBLE_REM_opcode; 019 import static org.jikesrvm.compilers.opt.ir.Operators.FLOAT_2LONG_opcode; 020 import static org.jikesrvm.compilers.opt.ir.Operators.FLOAT_REM_opcode; 021 import static org.jikesrvm.compilers.opt.ir.Operators.GET_ARRAY_ELEMENT_TIB_FROM_TIB_opcode; 022 import static org.jikesrvm.compilers.opt.ir.Operators.GET_CLASS_TIB_opcode; 023 import static org.jikesrvm.compilers.opt.ir.Operators.GET_DOES_IMPLEMENT_FROM_TIB_opcode; 024 import static org.jikesrvm.compilers.opt.ir.Operators.GET_OBJ_TIB_opcode; 025 import static org.jikesrvm.compilers.opt.ir.Operators.GET_SUPERCLASS_IDS_FROM_TIB_opcode; 026 import static org.jikesrvm.compilers.opt.ir.Operators.GET_TYPE_FROM_TIB_opcode; 027 import static org.jikesrvm.compilers.opt.ir.Operators.INT_LOAD; 028 import static org.jikesrvm.compilers.opt.ir.Operators.LONG_2DOUBLE_opcode; 029 import static org.jikesrvm.compilers.opt.ir.Operators.LONG_2FLOAT_opcode; 030 import static org.jikesrvm.compilers.opt.ir.Operators.LONG_DIV_opcode; 031 import static org.jikesrvm.compilers.opt.ir.Operators.LONG_REM_opcode; 032 import static org.jikesrvm.compilers.opt.ir.Operators.REF_LOAD; 033 import static org.jikesrvm.compilers.opt.ir.Operators.SYSCALL; 034 import static org.jikesrvm.compilers.opt.ir.Operators.SYSCALL_opcode; 035 import static org.jikesrvm.objectmodel.TIBLayoutConstants.TIB_ARRAY_ELEMENT_TIB_INDEX; 036 import static org.jikesrvm.objectmodel.TIBLayoutConstants.TIB_DOES_IMPLEMENT_INDEX; 037 import static org.jikesrvm.objectmodel.TIBLayoutConstants.TIB_SUPERCLASS_IDS_INDEX; 038 import static org.jikesrvm.objectmodel.TIBLayoutConstants.TIB_TYPE_INDEX; 039 040 import org.jikesrvm.VM; 041 import org.jikesrvm.ArchitectureSpecificOpt.CallingConvention; 042 import org.jikesrvm.ArchitectureSpecificOpt.ComplexLIR2MIRExpansion; 043 import org.jikesrvm.ArchitectureSpecificOpt.ConvertALUOperators; 044 import org.jikesrvm.ArchitectureSpecificOpt.NormalizeConstants; 045 import org.jikesrvm.classloader.RVMType; 046 import org.jikesrvm.compilers.opt.DefUse; 047 import org.jikesrvm.compilers.opt.NullCheckCombining; 048 import org.jikesrvm.compilers.opt.OptOptions; 049 import org.jikesrvm.compilers.opt.OptimizingCompilerException; 050 import org.jikesrvm.compilers.opt.depgraph.DepGraph; 051 import org.jikesrvm.compilers.opt.driver.CompilerPhase; 052 import org.jikesrvm.compilers.opt.driver.OptimizationPlanAtomicElement; 053 import org.jikesrvm.compilers.opt.driver.OptimizationPlanCompositeElement; 054 import org.jikesrvm.compilers.opt.driver.OptimizationPlanElement; 055 import org.jikesrvm.compilers.opt.driver.OptimizingCompiler; 056 import org.jikesrvm.compilers.opt.hir2lir.ConvertToLowLevelIR; 057 import org.jikesrvm.compilers.opt.ir.BasicBlock; 058 import org.jikesrvm.compilers.opt.ir.Binary; 059 import org.jikesrvm.compilers.opt.ir.Call; 060 import org.jikesrvm.compilers.opt.ir.GuardedBinary; 061 import org.jikesrvm.compilers.opt.ir.GuardedUnary; 062 import org.jikesrvm.compilers.opt.ir.IR; 063 import org.jikesrvm.compilers.opt.ir.IRTools; 064 import org.jikesrvm.compilers.opt.ir.Instruction; 065 import org.jikesrvm.compilers.opt.ir.Load; 066 import org.jikesrvm.compilers.opt.ir.MIRInfo; 067 import org.jikesrvm.compilers.opt.ir.Operators; 068 import org.jikesrvm.compilers.opt.ir.Unary; 069 import org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand; 070 import org.jikesrvm.compilers.opt.ir.operand.LocationOperand; 071 import org.jikesrvm.compilers.opt.ir.operand.MethodOperand; 072 import org.jikesrvm.compilers.opt.ir.operand.Operand; 073 import org.jikesrvm.compilers.opt.ir.operand.TypeOperand; 074 import org.jikesrvm.compilers.opt.liveness.LiveAnalysis; 075 import org.jikesrvm.objectmodel.JavaHeader; 076 import org.jikesrvm.objectmodel.ObjectModel; 077 import org.jikesrvm.runtime.Entrypoints; 078 import org.vmmagic.unboxed.Offset; 079 080 /** 081 * Convert an IR object from LIR to MIR via BURS 082 */ 083 public final class ConvertLIRtoMIR extends OptimizationPlanCompositeElement { 084 085 /** 086 * Create this phase element as a composite of other elements 087 */ 088 public ConvertLIRtoMIR() { 089 super("Instruction Selection", new OptimizationPlanElement[]{ 090 // Stage 1: Reduce the LIR operator set to a core set of operators. 091 new OptimizationPlanAtomicElement(new ReduceOperators()), 092 093 // Stage 2: Convert ALU operators 094 new OptimizationPlanAtomicElement(new ConvertALUOperators()), 095 096 // Stage 3: Normalize usage of constants to simplify Stage 3. 097 new OptimizationPlanAtomicElement(new NormalizeConstantsPhase()), 098 099 // Stage 4a: Compute liveness information for DepGraph 100 new OptimizationPlanAtomicElement(new DoLiveness()), 101 102 // Stage 4b: Block by block build DepGraph and do 103 // BURS based instruction selection. 104 new OptimizationPlanAtomicElement(new DoBURS()), 105 106 // Stage 5: Handle complex operators 107 // (those that expand to multiple basic blocks of MIR). 108 new OptimizationPlanAtomicElement(new ComplexOperators()), 109 110 // Stage 6: Use validation operands to do null check combining, 111 // and then finish the removal off all validation 112 // operands (they are not present in the MIR). 113 new OptimizationPlanAtomicElement(new NullCheckCombining() { 114 @Override 115 public void perform(IR ir) { 116 super.perform(ir); 117 // ir now contains well formed MIR. 118 ir.IRStage = IR.MIR; 119 ir.MIRInfo = new MIRInfo(ir); 120 } 121 })}); 122 } 123 124 /** 125 * Stage 1: Reduce the LIR operator set to a core set of operators. 126 */ 127 private static final class ReduceOperators extends CompilerPhase { 128 129 @Override 130 public String getName() { 131 return "Reduce Operators"; 132 } 133 134 @Override 135 public CompilerPhase newExecution(IR ir) { 136 return this; 137 } 138 139 @Override 140 public void perform(IR ir) { 141 for (Instruction s = ir.firstInstructionInCodeOrder(); s != null; s = s.nextInstructionInCodeOrder()) { 142 switch (s.getOpcode()) { 143 case ARRAYLENGTH_opcode: { 144 // array_ref[ObjectModel.getArrayLengthOffset()] contains the length 145 Load.mutate(s, 146 INT_LOAD, 147 GuardedUnary.getClearResult(s), 148 GuardedUnary.getClearVal(s), 149 IRTools.AC(ObjectModel.getArrayLengthOffset()), 150 new LocationOperand(), 151 GuardedUnary.getClearGuard(s)); 152 } 153 break; 154 155 case GET_OBJ_TIB_opcode: 156 // TODO: valid location operand. 157 Operand address = GuardedUnary.getClearVal(s); 158 Load.mutate(s, 159 Operators.REF_LOAD, 160 GuardedUnary.getClearResult(s), 161 address, 162 new AddressConstantOperand(JavaHeader.getTibOffset()), 163 null, 164 GuardedUnary.getClearGuard(s)); 165 break; 166 167 case GET_CLASS_TIB_opcode: { 168 RVMType type = ((TypeOperand) Unary.getVal(s)).getVMType(); 169 Offset offset = type.getTibOffset(); 170 Load.mutate(s, 171 REF_LOAD, 172 Unary.getClearResult(s), 173 ir.regpool.makeJTOCOp(ir, s), 174 IRTools.AC(offset), 175 new LocationOperand(offset)); 176 } 177 break; 178 179 case GET_TYPE_FROM_TIB_opcode: { 180 // TODO: Valid location operand? 181 Load.mutate(s, 182 REF_LOAD, 183 Unary.getClearResult(s), 184 Unary.getClearVal(s), 185 IRTools.AC(Offset.fromIntZeroExtend(TIB_TYPE_INDEX << LOG_BYTES_IN_ADDRESS)), 186 null); 187 } 188 break; 189 190 case GET_SUPERCLASS_IDS_FROM_TIB_opcode: { 191 // TODO: Valid location operand? 192 Load.mutate(s, 193 REF_LOAD, 194 Unary.getClearResult(s), 195 Unary.getClearVal(s), 196 IRTools.AC(Offset.fromIntZeroExtend(TIB_SUPERCLASS_IDS_INDEX << LOG_BYTES_IN_ADDRESS)), 197 null); 198 } 199 break; 200 201 case GET_DOES_IMPLEMENT_FROM_TIB_opcode: { 202 // TODO: Valid location operand? 203 Load.mutate(s, 204 REF_LOAD, 205 Unary.getClearResult(s), 206 Unary.getClearVal(s), 207 IRTools.AC(Offset.fromIntZeroExtend(TIB_DOES_IMPLEMENT_INDEX << LOG_BYTES_IN_ADDRESS)), 208 null); 209 } 210 break; 211 212 case GET_ARRAY_ELEMENT_TIB_FROM_TIB_opcode: { 213 // TODO: Valid location operand? 214 Load.mutate(s, 215 REF_LOAD, 216 Unary.getClearResult(s), 217 Unary.getClearVal(s), 218 IRTools.AC(Offset.fromIntZeroExtend(TIB_ARRAY_ELEMENT_TIB_INDEX << LOG_BYTES_IN_ADDRESS)), 219 null); 220 } 221 break; 222 223 case LONG_DIV_opcode: { 224 if (VM.BuildForPowerPC && VM.BuildFor64Addr) break; // don't reduce operator -- leave for BURS 225 Call.mutate2(s, 226 SYSCALL, 227 GuardedBinary.getClearResult(s), 228 null, 229 MethodOperand.STATIC(Entrypoints.sysLongDivideIPField), 230 GuardedBinary.getClearVal1(s), 231 GuardedBinary.getClearVal2(s)); 232 ConvertToLowLevelIR.expandSysCallTarget(s, ir); 233 CallingConvention.expandSysCall(s, ir); 234 } 235 break; 236 237 case LONG_REM_opcode: { 238 if (VM.BuildForPowerPC && VM.BuildFor64Addr) break; // don't reduce operator -- leave for BURS 239 Call.mutate2(s, 240 SYSCALL, 241 GuardedBinary.getClearResult(s), 242 null, 243 MethodOperand.STATIC(Entrypoints.sysLongRemainderIPField), 244 GuardedBinary.getClearVal1(s), 245 GuardedBinary.getClearVal2(s)); 246 ConvertToLowLevelIR.expandSysCallTarget(s, ir); 247 CallingConvention.expandSysCall(s, ir); 248 } 249 break; 250 251 case FLOAT_REM_opcode: 252 case DOUBLE_REM_opcode: { 253 if (VM.BuildForPowerPC) { 254 Call.mutate2(s, 255 SYSCALL, 256 Binary.getClearResult(s), 257 null, 258 MethodOperand.STATIC(Entrypoints.sysDoubleRemainderIPField), 259 Binary.getClearVal1(s), 260 Binary.getClearVal2(s)); 261 ConvertToLowLevelIR.expandSysCallTarget(s, ir); 262 CallingConvention.expandSysCall(s, ir); 263 } 264 } 265 break; 266 267 case LONG_2FLOAT_opcode: { 268 if (VM.BuildForPowerPC) { 269 Call.mutate1(s, 270 SYSCALL, 271 Unary.getClearResult(s), 272 null, 273 MethodOperand.STATIC(Entrypoints.sysLongToFloatIPField), 274 Unary.getClearVal(s)); 275 ConvertToLowLevelIR.expandSysCallTarget(s, ir); 276 CallingConvention.expandSysCall(s, ir); 277 } 278 } 279 break; 280 281 case LONG_2DOUBLE_opcode: { 282 if (VM.BuildForPowerPC) { 283 Call.mutate1(s, 284 SYSCALL, 285 Unary.getClearResult(s), 286 null, 287 MethodOperand.STATIC(Entrypoints.sysLongToDoubleIPField), 288 Unary.getClearVal(s)); 289 ConvertToLowLevelIR.expandSysCallTarget(s, ir); 290 CallingConvention.expandSysCall(s, ir); 291 } 292 } 293 break; 294 295 case FLOAT_2LONG_opcode: { 296 if (VM.BuildForPowerPC && VM.BuildFor64Addr || VM.BuildForSSE2Full) break; // don't reduce operator -- leave for BURS 297 Call.mutate1(s, 298 SYSCALL, 299 Unary.getClearResult(s), 300 null, 301 MethodOperand.STATIC(Entrypoints.sysFloatToLongIPField), 302 Unary.getClearVal(s)); 303 ConvertToLowLevelIR.expandSysCallTarget(s, ir); 304 CallingConvention.expandSysCall(s, ir); 305 } 306 break; 307 308 case DOUBLE_2LONG_opcode: { 309 if (VM.BuildForPowerPC && VM.BuildFor64Addr || VM.BuildForSSE2Full) break; // don't reduce operator -- leave for BURS 310 Call.mutate1(s, 311 SYSCALL, 312 Unary.getClearResult(s), 313 null, 314 MethodOperand.STATIC(Entrypoints.sysDoubleToLongIPField), 315 Unary.getClearVal(s)); 316 ConvertToLowLevelIR.expandSysCallTarget(s, ir); 317 CallingConvention.expandSysCall(s, ir); 318 } 319 break; 320 case SYSCALL_opcode: 321 CallingConvention.expandSysCall(s, ir); 322 break; 323 default: 324 break; 325 } 326 } 327 } 328 } 329 330 /** 331 * Stage 2: Normalize usage of int constants to make less work in Stage 3. 332 */ 333 private static final class NormalizeConstantsPhase extends CompilerPhase { 334 335 @Override 336 public String getName() { 337 return "Normalize Constants"; 338 } 339 340 @Override 341 public CompilerPhase newExecution(IR ir) { 342 return this; 343 } 344 345 @Override 346 public void perform(IR ir) { 347 NormalizeConstants.perform(ir); 348 } 349 } 350 351 private static final class DoLiveness extends CompilerPhase { 352 353 @Override 354 public String getName() { 355 return "Live Handlers"; 356 } 357 358 @Override 359 public CompilerPhase newExecution(IR ir) { 360 return this; 361 } 362 363 @Override 364 public void perform(IR ir) { 365 if (ir.options.L2M_HANDLER_LIVENESS) { 366 new LiveAnalysis(false, false, true).perform(ir); 367 } else { 368 ir.setHandlerLivenessComputed(false); 369 } 370 } 371 } 372 373 /** 374 * Stage 3: Block by block build DepGraph and do BURS based 375 * instruction selection. 376 */ 377 private static final class DoBURS extends CompilerPhase { 378 379 @Override 380 public String getName() { 381 return "DepGraph & BURS"; 382 } 383 384 @Override 385 public CompilerPhase newExecution(IR ir) { 386 return this; 387 } 388 389 @Override 390 public void reportAdditionalStats() { 391 VM.sysWrite(" "); 392 VM.sysWrite(container.counter1 / container.counter2 * 100, 2); 393 VM.sysWrite("% Infrequent BBs"); 394 } 395 396 // IR is inconsistent state between DoBURS and ComplexOperators. 397 // It isn't verifiable again until after ComplexOperators completes. 398 @Override 399 public void verify(IR ir) { } 400 401 @Override 402 public void perform(IR ir) { 403 OptOptions options = ir.options; 404 DefUse.recomputeSpansBasicBlock(ir); 405 MinimalBURS mburs = new MinimalBURS(ir); 406 NormalBURS burs = new NormalBURS(ir); 407 for (BasicBlock bb = ir.firstBasicBlockInCodeOrder(); bb != null; bb = bb.nextBasicBlockInCodeOrder()) { 408 if (bb.isEmpty()) continue; 409 container.counter2++; 410 if (bb.getInfrequent()) { 411 container.counter1++; 412 if (options.FREQ_FOCUS_EFFORT) { 413 // Basic block is infrequent -- use quick and dirty instruction selection 414 mburs.prepareForBlock(bb); 415 mburs.invoke(bb); 416 mburs.finalizeBlock(bb); 417 continue; 418 } 419 } 420 // Use Normal instruction selection. 421 burs.prepareForBlock(bb); 422 // I. Build Dependence graph for the basic block 423 DepGraph dgraph = new DepGraph(ir, bb.firstRealInstruction(), bb.lastRealInstruction(), bb); 424 if (options.PRINT_DG_BURS) { 425 // print dependence graph. 426 OptimizingCompiler.header("DepGraph", ir.method); 427 dgraph.printDepGraph(); 428 OptimizingCompiler.bottom("DepGraph", ir.method); 429 } 430 // II. Invoke BURS and rewrite block from LIR to MIR 431 try { 432 burs.invoke(dgraph); 433 } catch (OptimizingCompilerException e) { 434 System.err.println("Exception occurred in ConvertLIRtoMIR"); 435 e.printStackTrace(); 436 ir.printInstructions(); 437 throw e; 438 } 439 burs.finalizeBlock(bb); 440 } 441 } 442 } 443 444 /** 445 * Stage 4: Handle complex operators 446 * (those that expand to multiple basic blocks). 447 */ 448 private static final class ComplexOperators extends CompilerPhase { 449 450 @Override 451 public String getName() { 452 return "Complex Operators"; 453 } 454 455 @Override 456 public CompilerPhase newExecution(IR ir) { 457 return this; 458 } 459 460 @Override 461 public void perform(IR ir) { 462 ComplexLIR2MIRExpansion.convert(ir); 463 } 464 } 465 }