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.ir.ia32;
014
015 import org.jikesrvm.VM;
016 import org.jikesrvm.classloader.TypeReference;
017 import org.jikesrvm.compilers.opt.OptimizingCompilerException;
018 import org.jikesrvm.compilers.opt.ir.Empty;
019 import org.jikesrvm.compilers.opt.ir.MIR_CondBranch;
020 import org.jikesrvm.compilers.opt.ir.MIR_CondBranch2;
021 import org.jikesrvm.compilers.opt.ir.MIR_Move;
022 import org.jikesrvm.compilers.opt.ir.BasicBlock;
023 import org.jikesrvm.compilers.opt.ir.BasicBlockEnumeration;
024 import org.jikesrvm.compilers.opt.ir.IR;
025 import org.jikesrvm.compilers.opt.ir.Instruction;
026 import org.jikesrvm.compilers.opt.ir.InstructionEnumeration;
027 import org.jikesrvm.compilers.opt.ir.MachineSpecificIR;
028 import org.jikesrvm.compilers.opt.ir.OperandEnumeration;
029 import org.jikesrvm.compilers.opt.ir.Operator;
030 import static org.jikesrvm.compilers.opt.ir.Operators.ADVISE_ESP;
031 import static org.jikesrvm.compilers.opt.ir.Operators.DUMMY_DEF;
032 import static org.jikesrvm.compilers.opt.ir.Operators.DUMMY_USE;
033 import static org.jikesrvm.compilers.opt.ir.Operators.GET_CURRENT_PROCESSOR_opcode;
034 import static org.jikesrvm.compilers.opt.ir.Operators.IA32_FCLEAR;
035 import static org.jikesrvm.compilers.opt.ir.Operators.IA32_FMOV;
036 import static org.jikesrvm.compilers.opt.ir.Operators.IA32_FMOV_ENDING_LIVE_RANGE;
037 import static org.jikesrvm.compilers.opt.ir.Operators.IA32_FNINIT;
038 import static org.jikesrvm.compilers.opt.ir.Operators.IA32_JCC;
039 import static org.jikesrvm.compilers.opt.ir.Operators.LONG_2ADDR_opcode;
040 import static org.jikesrvm.compilers.opt.ir.Operators.LONG_ADD_opcode;
041 import static org.jikesrvm.compilers.opt.ir.Operators.LONG_AND_opcode;
042 import static org.jikesrvm.compilers.opt.ir.Operators.LONG_MOVE_opcode;
043 import static org.jikesrvm.compilers.opt.ir.Operators.LONG_NEG_opcode;
044 import static org.jikesrvm.compilers.opt.ir.Operators.LONG_OR_opcode;
045 import static org.jikesrvm.compilers.opt.ir.Operators.LONG_SHL_opcode;
046 import static org.jikesrvm.compilers.opt.ir.Operators.LONG_SHR_opcode;
047 import static org.jikesrvm.compilers.opt.ir.Operators.LONG_SUB_opcode;
048 import static org.jikesrvm.compilers.opt.ir.Operators.LONG_USHR_opcode;
049 import static org.jikesrvm.compilers.opt.ir.Operators.LONG_XOR_opcode;
050 import static org.jikesrvm.compilers.opt.ir.Operators.NOP;
051 import static org.jikesrvm.compilers.opt.ir.Operators.PREFETCH_opcode;
052 import org.jikesrvm.compilers.opt.ir.Register;
053 import org.jikesrvm.compilers.opt.ir.operand.Operand;
054 import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand;
055 import org.jikesrvm.compilers.opt.ir.operand.ia32.BURSManagedFPROperand;
056 import org.jikesrvm.compilers.opt.ir.operand.ia32.IA32ConditionOperand;
057 import org.jikesrvm.compilers.opt.regalloc.LiveIntervalElement;
058
059 /**
060 * Wrappers around IA32-specific IR common to both 32 & 64 bit
061 */
062 public abstract class MachineSpecificIRIA extends MachineSpecificIR {
063
064 /**
065 * Wrappers around IA32-specific IR (32-bit specific)
066 */
067 public static final class IA32 extends MachineSpecificIRIA {
068 public static final IA32 singleton = new IA32();
069
070 /* common to all ISAs */
071 @Override
072 public boolean mayEscapeThread(Instruction instruction) {
073 switch (instruction.getOpcode()) {
074 case PREFETCH_opcode:
075 return false;
076 case GET_CURRENT_PROCESSOR_opcode:
077 return true;
078 default:
079 throw new OptimizingCompilerException("SimpleEscape: Unexpected " + instruction);
080 }
081 }
082
083 @Override
084 public boolean mayEscapeMethod(Instruction instruction) {
085 return mayEscapeThread(instruction); // at this stage we're no more specific
086 }
087 }
088
089 /**
090 * Wrappers around EMT64-specific IR (64-bit specific)
091 */
092 public static final class EM64T extends MachineSpecificIRIA {
093 public static final EM64T singleton = new EM64T();
094
095 /* common to all ISAs */
096 @Override
097 public boolean mayEscapeThread(Instruction instruction) {
098 switch (instruction.getOpcode()) {
099 case PREFETCH_opcode:
100 return false;
101 case GET_CURRENT_PROCESSOR_opcode:
102 case LONG_OR_opcode:
103 case LONG_AND_opcode:
104 case LONG_XOR_opcode:
105 case LONG_SUB_opcode:
106 case LONG_SHL_opcode:
107 case LONG_ADD_opcode:
108 case LONG_SHR_opcode:
109 case LONG_USHR_opcode:
110 case LONG_NEG_opcode:
111 case LONG_MOVE_opcode:
112 case LONG_2ADDR_opcode:
113 return true;
114 default:
115 throw new OptimizingCompilerException("SimpleEscapge: Unexpected " + instruction);
116 }
117 }
118
119 @Override
120 public boolean mayEscapeMethod(Instruction instruction) {
121 return mayEscapeThread(instruction); // at this stage we're no more specific
122 }
123 }
124
125 /*
126 * Generic (32/64 neutral) IA support
127 */
128
129 /* common to all ISAs */
130
131 @Override
132 public boolean isConditionOperand(Operand operand) {
133 return operand instanceof IA32ConditionOperand;
134 }
135
136 @Override
137 public void mutateMIRCondBranch(Instruction cb) {
138 MIR_CondBranch.mutate(cb,
139 IA32_JCC,
140 MIR_CondBranch2.getCond1(cb),
141 MIR_CondBranch2.getTarget1(cb),
142 MIR_CondBranch2.getBranchProfile1(cb));
143 }
144
145 @Override
146 public boolean isHandledByRegisterUnknown(char opcode) {
147 return (opcode == PREFETCH_opcode);
148 }
149
150 /* unique to IA */
151 @Override
152 public boolean isAdviseESP(Operator operator) {
153 return operator == ADVISE_ESP;
154 }
155
156 @Override
157 public boolean isFClear(Operator operator) {
158 return operator == IA32_FCLEAR;
159 }
160
161 @Override
162 public boolean isFNInit(Operator operator) {
163 return operator == IA32_FNINIT;
164 }
165
166 @Override
167 public boolean isBURSManagedFPROperand(Operand operand) {
168 return operand instanceof BURSManagedFPROperand;
169 }
170
171 @Override
172 public int getBURSManagedFPRValue(Operand operand) {
173 return ((BURSManagedFPROperand) operand).regNum;
174 }
175
176 /**
177 * Mutate FMOVs that end live ranges
178 *
179 * @param live The live interval for a basic block/reg pair
180 * @param register The register for this live interval
181 * @param dfnbegin The (adjusted) begin for this interval
182 * @param dfnend The (adjusted) end for this interval
183 */
184 @Override
185 public boolean mutateFMOVs(LiveIntervalElement live, Register register, int dfnbegin, int dfnend) {
186 Instruction end = live.getEnd();
187 if (end != null && end.operator == IA32_FMOV) {
188 if (dfnend == dfnbegin) {
189 // if end, an FMOV, both begins and ends the live range,
190 // then end is dead. Change it to a NOP and return null.
191 Empty.mutate(end, NOP);
192 return false;
193 } else {
194 if (!end.isPEI()) {
195 if (VM.VerifyAssertions) {
196 Operand value = MIR_Move.getValue(end);
197 VM._assert(value.isRegister());
198 VM._assert(MIR_Move.getValue(end).asRegister().getRegister() == register);
199 }
200 end.operator = IA32_FMOV_ENDING_LIVE_RANGE;
201 }
202 }
203 }
204 return true;
205 }
206
207 /**
208 * Rewrite floating point registers to reflect changes in stack
209 * height induced by BURS.
210 *
211 * Side effect: update the fpStackHeight in MIRInfo
212 */
213 public void rewriteFPStack(IR ir) {
214 PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet();
215 for (BasicBlockEnumeration b = ir.getBasicBlocks(); b.hasMoreElements();) {
216 BasicBlock bb = b.nextElement();
217
218 // The following holds the floating point stack offset from its
219 // 'normal' position.
220 int fpStackOffset = 0;
221
222 for (InstructionEnumeration inst = bb.forwardInstrEnumerator(); inst.hasMoreElements();) {
223 Instruction s = inst.next();
224 for (OperandEnumeration ops = s.getOperands(); ops.hasMoreElements();) {
225 Operand op = ops.next();
226 if (op.isRegister()) {
227 RegisterOperand rop = op.asRegister();
228 Register r = rop.getRegister();
229
230 // Update MIR state for every physical FPR we see
231 if (r.isPhysical() && r.isFloatingPoint() && s.operator() != DUMMY_DEF && s.operator() != DUMMY_USE) {
232 int n = PhysicalRegisterSet.getFPRIndex(r);
233 if (fpStackOffset != 0) {
234 n += fpStackOffset;
235 rop.setRegister(phys.getFPR(n));
236 }
237 ir.MIRInfo.fpStackHeight = Math.max(ir.MIRInfo.fpStackHeight, n + 1);
238 }
239 } else if (op instanceof BURSManagedFPROperand) {
240 int regNum = ((BURSManagedFPROperand) op).regNum;
241 s.replaceOperand(op, new RegisterOperand(phys.getFPR(regNum), TypeReference.Double));
242 }
243 }
244 // account for any effect s has on the floating point stack
245 // position.
246 if (s.operator().isFpPop()) {
247 fpStackOffset--;
248 } else if (s.operator().isFpPush()) {
249 fpStackOffset++;
250 }
251 if (VM.VerifyAssertions) VM._assert(fpStackOffset >= 0);
252 }
253 }
254 }
255 }