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    }