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 org.jikesrvm.VM;
016 import org.jikesrvm.compilers.opt.OptOptions;
017 import org.jikesrvm.compilers.opt.driver.CompilerPhase;
018 import org.jikesrvm.compilers.opt.ir.BasicBlock;
019 import org.jikesrvm.compilers.opt.ir.BasicBlockEnumeration;
020 import org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock;
021 import org.jikesrvm.compilers.opt.ir.IR;
022 import org.jikesrvm.compilers.opt.ir.IRTools;
023 import org.jikesrvm.compilers.opt.ir.Instruction;
024 import org.jikesrvm.compilers.opt.ir.InstructionEnumeration;
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 public CompilerPhase newExecution(IR ir) {
081 return this;
082 }
083
084 public boolean printingEnabled(OptOptions options, boolean before) {
085 return options.PRINT_CALLING_CONVENTIONS && !before;
086 }
087
088 public String getName() {
089 return "Expand Calling Convention";
090 }
091
092 /**
093 * Insert the needed dummy defs and uses.
094 */
095 public void perform(IR ir) {
096 if (ArchConstants.SSE2_FULL) {
097 return;
098 }
099 PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet();
100
101 for (BasicBlockEnumeration b = ir.getBasicBlocks(); b.hasMoreElements();) {
102 BasicBlock bb = b.nextElement();
103
104 if (bb instanceof ExceptionHandlerBasicBlock) {
105 // clear all floating-point state at the entry to a catch block
106 for (int i = 0; i < NUM_ALLOCATABLE_FPR; i++) {
107 Register fpr = phys.getFPR(i);
108 bb.prependInstruction(MIR_UnaryNoRes.create(DUMMY_USE, IRTools.D(fpr)));
109 bb.prependInstruction(MIR_Nullary.create(DUMMY_DEF, IRTools.D(fpr)));
110 }
111 }
112
113 // The following holds the floating point stack offset from its
114 // 'normal' position.
115 int fpStackOffset = 0;
116
117 for (InstructionEnumeration inst = bb.forwardInstrEnumerator(); inst.hasMoreElements();) {
118 Instruction s = inst.nextElement();
119 if (s.operator().isFpPop()) {
120 // A pop instruction 'ends' a dummy live range.
121 Register fpr = phys.getFPR(NUM_ALLOCATABLE_FPR - fpStackOffset);
122 s.insertAfter(MIR_UnaryNoRes.create(DUMMY_USE, IRTools.D(fpr)));
123 fpStackOffset--;
124 } else if (s.operator().isFpPush()) {
125 fpStackOffset++;
126 Register fpr = phys.getFPR(NUM_ALLOCATABLE_FPR - fpStackOffset);
127 s.insertBefore(MIR_Nullary.create(DUMMY_DEF, IRTools.D(fpr)));
128 }
129 if (VM.VerifyAssertions) VM._assert(fpStackOffset >= 0);
130 if (VM.VerifyAssertions) {
131 VM._assert(fpStackOffset < NUM_ALLOCATABLE_FPR);
132 }
133 }
134 }
135 }
136 }