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 */ 013package org.jikesrvm.compilers.opt.regalloc.ia32; 014 015import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.DUMMY_DEF; 016import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.DUMMY_USE; 017import static org.jikesrvm.ia32.ArchConstants.SSE2_FULL; 018 019import java.util.Enumeration; 020 021import org.jikesrvm.VM; 022import org.jikesrvm.compilers.opt.OptOptions; 023import org.jikesrvm.compilers.opt.driver.CompilerPhase; 024import org.jikesrvm.compilers.opt.ir.BasicBlock; 025import org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock; 026import org.jikesrvm.compilers.opt.ir.IR; 027import org.jikesrvm.compilers.opt.ir.IRTools; 028import org.jikesrvm.compilers.opt.ir.Instruction; 029import org.jikesrvm.compilers.opt.ir.Register; 030import org.jikesrvm.compilers.opt.ir.ia32.MIR_Nullary; 031import org.jikesrvm.compilers.opt.ir.ia32.MIR_UnaryNoRes; 032import org.jikesrvm.compilers.opt.ir.ia32.PhysicalRegisterSet; 033 034/** 035 * At the beginning of each basic block, the register allocator expects 036 * all floating-point stack locations to be available, and named 037 * FPi, 0 < i < 7 038 * 039 * <p>However, BURS may consume FP stack locations by inserting instructions 040 * that push or pop the floating-point stack. This phase inserts dummy 041 * definitions and uses to indicate when symbolic FP registers are not 042 * available for register allocation since BURS has consumed a stack slot. 043 * 044 * For example, 045 * <pre> 046 * FLD t1 047 * ... 048 * FSTP M, t1 049 * </pre> 050 * 051 * will be modified by this phase to indicate that FP6 is not available 052 * for allocation in the interval: 053 * 054 * <pre> 055 * DUMMY_DEF FP6 056 * FLD t1 057 * ..... 058 * FSTP M, t1 059 * DUMMY_USE FP6 060 * </pre> 061 * 062 * <p> Additionally, by convention, we will always clear the 063 * floating-point stack when delivering an exception. To model this, we 064 * insert dummy defs and uses for each floating-point register at the 065 * beginning of each catch block. 066 */ 067 068public final class ExpandFPRStackConvention extends CompilerPhase { 069 070 /** 071 * The number of FPRs available for allocation. 072 * Normally 7: we reserve one for final MIR expansion. 073 */ 074 private static final int NUM_ALLOCATABLE_FPR = 7; 075 076 /** 077 * Return this instance of this phase. This phase contains no 078 * per-compilation instance fields. 079 * @param ir not used 080 * @return this 081 */ 082 @Override 083 public CompilerPhase newExecution(IR ir) { 084 return this; 085 } 086 087 @Override 088 public boolean printingEnabled(OptOptions options, boolean before) { 089 return options.PRINT_CALLING_CONVENTIONS && !before; 090 } 091 092 @Override 093 public String getName() { 094 return "Expand Calling Convention"; 095 } 096 097 /** 098 * Insert the needed dummy defs and uses. 099 */ 100 @Override 101 public void perform(IR ir) { 102 if (SSE2_FULL) { 103 return; 104 } 105 PhysicalRegisterSet phys = (PhysicalRegisterSet)ir.regpool.getPhysicalRegisterSet(); 106 107 for (Enumeration<BasicBlock> b = ir.getBasicBlocks(); b.hasMoreElements();) { 108 BasicBlock bb = b.nextElement(); 109 110 if (bb instanceof ExceptionHandlerBasicBlock) { 111 // clear all floating-point state at the entry to a catch block 112 for (int i = 0; i < NUM_ALLOCATABLE_FPR; i++) { 113 Register fpr = phys.getFPR(i); 114 bb.prependInstruction(MIR_UnaryNoRes.create(DUMMY_USE, IRTools.D(fpr))); 115 bb.prependInstruction(MIR_Nullary.create(DUMMY_DEF, IRTools.D(fpr))); 116 } 117 } 118 119 // The following holds the floating point stack offset from its 120 // 'normal' position. 121 int fpStackOffset = 0; 122 123 for (Enumeration<Instruction> inst = bb.forwardInstrEnumerator(); inst.hasMoreElements();) { 124 Instruction s = inst.nextElement(); 125 if (s.operator().isFpPop()) { 126 // A pop instruction 'ends' a dummy live range. 127 Register fpr = phys.getFPR(NUM_ALLOCATABLE_FPR - fpStackOffset); 128 s.insertAfter(MIR_UnaryNoRes.create(DUMMY_USE, IRTools.D(fpr))); 129 fpStackOffset--; 130 } else if (s.operator().isFpPush()) { 131 fpStackOffset++; 132 Register fpr = phys.getFPR(NUM_ALLOCATABLE_FPR - fpStackOffset); 133 s.insertBefore(MIR_Nullary.create(DUMMY_DEF, IRTools.D(fpr))); 134 } 135 if (VM.VerifyAssertions) VM._assert(fpStackOffset >= 0); 136 if (VM.VerifyAssertions) { 137 VM._assert(fpStackOffset < NUM_ALLOCATABLE_FPR); 138 } 139 } 140 } 141 } 142}