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.lir2mir.ia32;
014    
015    import java.util.Enumeration;
016    
017    import org.jikesrvm.compilers.opt.OptimizingCompilerException;
018    import org.jikesrvm.compilers.opt.Simplifier;
019    import org.jikesrvm.compilers.opt.driver.CompilerPhase;
020    import org.jikesrvm.compilers.opt.ir.CondMove;
021    import org.jikesrvm.compilers.opt.ir.IR;
022    import org.jikesrvm.compilers.opt.ir.Instruction;
023    import org.jikesrvm.compilers.opt.ir.Operators;
024    import org.jikesrvm.ia32.ArchConstants;
025    
026    /**
027     * Reduce the number of ALU operators considered by BURS
028     */
029    public class ConvertALUOperators extends CompilerPhase implements Operators, ArchConstants {
030    
031      @Override
032      public final String getName() { return "ConvertALUOps"; }
033    
034      /**
035       * Return this instance of this phase. This phase contains no
036       * per-compilation instance fields.
037       * @param ir not used
038       * @return this
039       */
040      @Override
041      public CompilerPhase newExecution(IR ir) {
042        return this;
043      }
044    
045      @Override
046      public final void perform(IR ir) {
047        // Calling Simplifier.simplify ensures that the instruction is
048        // in normalized form. This reduces the number of cases we have to
049        // worry about (and does last minute constant folding on the off
050        // chance we've missed an opportunity...)
051        // BURS assumes that this has been done
052        for (Enumeration<Instruction> instrs = ir.forwardInstrEnumerator(); instrs.hasMoreElements();) {
053          Instruction s = instrs.nextElement();
054          Simplifier.simplify(false, ir.regpool, ir.options, s);
055        }
056    
057        // Pass over instructions
058        for (Enumeration<Instruction> e = ir.forwardInstrEnumerator(); e.hasMoreElements();) {
059          Instruction s = e.nextElement();
060    
061          switch (s.getOpcode()) {
062          case REF_ADD_opcode:
063            s.operator = INT_ADD;
064            break;
065          case REF_SUB_opcode:
066            s.operator = INT_SUB;
067            break;
068          case REF_NEG_opcode:
069            s.operator = INT_NEG;
070            break;
071          case REF_NOT_opcode:
072            s.operator = INT_NOT;
073            break;
074          case REF_AND_opcode:
075            s.operator = INT_AND;
076            break;
077          case REF_OR_opcode:
078            s.operator = INT_OR;
079            break;
080          case REF_XOR_opcode:
081            s.operator = INT_XOR;
082            break;
083          case REF_SHL_opcode:
084            s.operator = INT_SHL;
085            break;
086          case REF_SHR_opcode:
087            s.operator = INT_SHR;
088            break;
089          case REF_USHR_opcode:
090            s.operator = INT_USHR;
091            break;
092    
093          // BURS doesn't really care, so consolidate to reduce rule space
094          case BOOLEAN_CMP_ADDR_opcode:
095            s.operator = BOOLEAN_CMP_INT;
096            break;
097    
098          // BURS doesn't really care, so consolidate to reduce rule space
099          case FLOAT_ADD_opcode:
100            if (!SSE2_FULL)
101              s.operator = FP_ADD;
102            break;
103          case DOUBLE_ADD_opcode:
104            if (!SSE2_FULL)
105              s.operator = FP_ADD;
106            break;
107          case FLOAT_SUB_opcode:
108            if (!SSE2_FULL)
109              s.operator = FP_SUB;
110            break;
111          case DOUBLE_SUB_opcode:
112            if (!SSE2_FULL)
113              s.operator = FP_SUB;
114            break;
115          case FLOAT_MUL_opcode:
116            if (!SSE2_FULL)
117              s.operator = FP_MUL;
118            break;
119          case DOUBLE_MUL_opcode:
120            if (!SSE2_FULL)
121              s.operator = FP_MUL;
122            break;
123          case FLOAT_DIV_opcode:
124            if (!SSE2_FULL)
125              s.operator = FP_DIV;
126            break;
127          case DOUBLE_DIV_opcode:
128            if (!SSE2_FULL)
129              s.operator = FP_DIV;
130            break;
131          case FLOAT_REM_opcode:
132            if (!SSE2_FULL)
133              s.operator = FP_REM;
134            break;
135          case DOUBLE_REM_opcode:
136            if (!SSE2_FULL)
137              s.operator = FP_REM;
138            break;
139          case FLOAT_NEG_opcode:
140            if (!SSE2_FULL)
141              s.operator = FP_NEG;
142            break;
143          case DOUBLE_NEG_opcode:
144            if (!SSE2_FULL)
145              s.operator = FP_NEG;
146            break;
147    
148          // BURS doesn't really care, so consolidate to reduce rule space
149          case INT_COND_MOVE_opcode:
150          case REF_COND_MOVE_opcode:
151            s.operator = CondMove.getCond(s).isFLOATINGPOINT() ? FCMP_CMOV : (CondMove.getVal1(s).isLong() ? LCMP_CMOV : CMP_CMOV);
152            break;
153          case FLOAT_COND_MOVE_opcode:
154          case DOUBLE_COND_MOVE_opcode:
155            s.operator = CondMove.getCond(s).isFLOATINGPOINT() ? FCMP_FCMOV : CMP_FCMOV;
156            break;
157    
158          case GUARD_COND_MOVE_opcode:
159          case LONG_COND_MOVE_opcode:
160            OptimizingCompilerException.TODO("Unimplemented conversion" + s);
161            break;
162    
163          // BURS doesn't really care, so consolidate to reduce rule space
164          case INT_2FLOAT_opcode:
165            if (!SSE2_FULL)
166              s.operator = INT_2FP;
167            break;
168          case INT_2DOUBLE_opcode:
169            if (!SSE2_FULL)
170              s.operator = INT_2FP;
171            break;
172          case LONG_2FLOAT_opcode:
173            if (!SSE2_FULL)
174              s.operator = LONG_2FP;
175            break;
176          case LONG_2DOUBLE_opcode:
177            if (!SSE2_FULL)
178              s.operator = LONG_2FP;
179            break;
180    
181          // BURS doesn't really care, so consolidate to reduce rule space
182          case REF_LOAD_opcode:
183            s.operator = INT_LOAD;
184            break;
185          case REF_STORE_opcode:
186            s.operator = INT_STORE;
187            break;
188          case REF_ALOAD_opcode:
189            s.operator = INT_ALOAD;
190            break;
191          case REF_ASTORE_opcode:
192            s.operator = INT_ASTORE;
193            break;
194          case REF_MOVE_opcode:
195            s.operator = INT_MOVE;
196            break;
197          case REF_IFCMP_opcode:
198            s.operator = INT_IFCMP;
199            break;
200          case ATTEMPT_ADDR_opcode:
201            s.operator = ATTEMPT_INT;
202            break;
203          case PREPARE_ADDR_opcode:
204            s.operator = PREPARE_INT;
205            break;
206          case INT_2ADDRSigExt_opcode:
207            s.operator = INT_MOVE;
208            break;
209          case INT_2ADDRZerExt_opcode:
210            s.operator = INT_MOVE;
211            break;
212          case ADDR_2INT_opcode:
213            s.operator = INT_MOVE;
214            break;
215          case LONG_2ADDR_opcode:
216            s.operator = LONG_2INT;
217            break;
218          }
219        }
220      }
221    }