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