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    }