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 */ 013package org.jikesrvm.compilers.opt.lir2mir.ia32; 014 015import static org.jikesrvm.compilers.opt.ir.Operators.ADDR_2INT_opcode; 016import static org.jikesrvm.compilers.opt.ir.Operators.ADDR_2LONG_opcode; 017import static org.jikesrvm.compilers.opt.ir.Operators.ATTEMPT_ADDR_opcode; 018import static org.jikesrvm.compilers.opt.ir.Operators.ATTEMPT_INT; 019import static org.jikesrvm.compilers.opt.ir.Operators.ATTEMPT_LONG; 020import static org.jikesrvm.compilers.opt.ir.Operators.BOOLEAN_CMP_ADDR_opcode; 021import static org.jikesrvm.compilers.opt.ir.Operators.BOOLEAN_CMP_INT; 022import static org.jikesrvm.compilers.opt.ir.Operators.BOOLEAN_CMP_LONG; 023import static org.jikesrvm.compilers.opt.ir.Operators.DOUBLE_ADD_opcode; 024import static org.jikesrvm.compilers.opt.ir.Operators.DOUBLE_COND_MOVE_opcode; 025import static org.jikesrvm.compilers.opt.ir.Operators.DOUBLE_DIV_opcode; 026import static org.jikesrvm.compilers.opt.ir.Operators.DOUBLE_MUL_opcode; 027import static org.jikesrvm.compilers.opt.ir.Operators.DOUBLE_NEG_opcode; 028import static org.jikesrvm.compilers.opt.ir.Operators.DOUBLE_REM_opcode; 029import static org.jikesrvm.compilers.opt.ir.Operators.DOUBLE_SUB_opcode; 030import static org.jikesrvm.compilers.opt.ir.Operators.FLOAT_ADD_opcode; 031import static org.jikesrvm.compilers.opt.ir.Operators.FLOAT_COND_MOVE_opcode; 032import static org.jikesrvm.compilers.opt.ir.Operators.FLOAT_DIV_opcode; 033import static org.jikesrvm.compilers.opt.ir.Operators.FLOAT_MUL_opcode; 034import static org.jikesrvm.compilers.opt.ir.Operators.FLOAT_NEG_opcode; 035import static org.jikesrvm.compilers.opt.ir.Operators.FLOAT_REM_opcode; 036import static org.jikesrvm.compilers.opt.ir.Operators.FLOAT_SUB_opcode; 037import static org.jikesrvm.compilers.opt.ir.Operators.GUARD_COND_MOVE_opcode; 038import static org.jikesrvm.compilers.opt.ir.Operators.INT_2ADDRSigExt_opcode; 039import static org.jikesrvm.compilers.opt.ir.Operators.INT_2ADDRZerExt_opcode; 040import static org.jikesrvm.compilers.opt.ir.Operators.INT_2DOUBLE_opcode; 041import static org.jikesrvm.compilers.opt.ir.Operators.INT_2FLOAT_opcode; 042import static org.jikesrvm.compilers.opt.ir.Operators.INT_2LONG; 043import static org.jikesrvm.compilers.opt.ir.Operators.INT_ADD; 044import static org.jikesrvm.compilers.opt.ir.Operators.INT_ALOAD; 045import static org.jikesrvm.compilers.opt.ir.Operators.INT_AND; 046import static org.jikesrvm.compilers.opt.ir.Operators.INT_ASTORE; 047import static org.jikesrvm.compilers.opt.ir.Operators.INT_COND_MOVE_opcode; 048import static org.jikesrvm.compilers.opt.ir.Operators.INT_IFCMP; 049import static org.jikesrvm.compilers.opt.ir.Operators.INT_LOAD; 050import static org.jikesrvm.compilers.opt.ir.Operators.INT_MOVE; 051import static org.jikesrvm.compilers.opt.ir.Operators.INT_NEG; 052import static org.jikesrvm.compilers.opt.ir.Operators.INT_NOT; 053import static org.jikesrvm.compilers.opt.ir.Operators.INT_OR; 054import static org.jikesrvm.compilers.opt.ir.Operators.INT_SHL; 055import static org.jikesrvm.compilers.opt.ir.Operators.INT_SHR; 056import static org.jikesrvm.compilers.opt.ir.Operators.INT_STORE; 057import static org.jikesrvm.compilers.opt.ir.Operators.INT_SUB; 058import static org.jikesrvm.compilers.opt.ir.Operators.INT_USHR; 059import static org.jikesrvm.compilers.opt.ir.Operators.INT_XOR; 060import static org.jikesrvm.compilers.opt.ir.Operators.LONG_2ADDR_opcode; 061import static org.jikesrvm.compilers.opt.ir.Operators.LONG_2DOUBLE_opcode; 062import static org.jikesrvm.compilers.opt.ir.Operators.LONG_2FLOAT_opcode; 063import static org.jikesrvm.compilers.opt.ir.Operators.LONG_2INT; 064import static org.jikesrvm.compilers.opt.ir.Operators.LONG_ADD; 065import static org.jikesrvm.compilers.opt.ir.Operators.LONG_ALOAD; 066import static org.jikesrvm.compilers.opt.ir.Operators.LONG_AND; 067import static org.jikesrvm.compilers.opt.ir.Operators.LONG_ASTORE; 068import static org.jikesrvm.compilers.opt.ir.Operators.LONG_COND_MOVE_opcode; 069import static org.jikesrvm.compilers.opt.ir.Operators.LONG_IFCMP; 070import static org.jikesrvm.compilers.opt.ir.Operators.LONG_LOAD; 071import static org.jikesrvm.compilers.opt.ir.Operators.LONG_MOVE; 072import static org.jikesrvm.compilers.opt.ir.Operators.LONG_NEG; 073import static org.jikesrvm.compilers.opt.ir.Operators.LONG_NOT; 074import static org.jikesrvm.compilers.opt.ir.Operators.LONG_OR; 075import static org.jikesrvm.compilers.opt.ir.Operators.LONG_SHL; 076import static org.jikesrvm.compilers.opt.ir.Operators.LONG_SHR; 077import static org.jikesrvm.compilers.opt.ir.Operators.LONG_STORE; 078import static org.jikesrvm.compilers.opt.ir.Operators.LONG_SUB; 079import static org.jikesrvm.compilers.opt.ir.Operators.LONG_USHR; 080import static org.jikesrvm.compilers.opt.ir.Operators.LONG_XOR; 081import static org.jikesrvm.compilers.opt.ir.Operators.PREPARE_ADDR_opcode; 082import static org.jikesrvm.compilers.opt.ir.Operators.PREPARE_INT_opcode; 083import static org.jikesrvm.compilers.opt.ir.Operators.PREPARE_LONG_opcode; 084import static org.jikesrvm.compilers.opt.ir.Operators.REF_ADD_opcode; 085import static org.jikesrvm.compilers.opt.ir.Operators.REF_ALOAD_opcode; 086import static org.jikesrvm.compilers.opt.ir.Operators.REF_AND_opcode; 087import static org.jikesrvm.compilers.opt.ir.Operators.REF_ASTORE_opcode; 088import static org.jikesrvm.compilers.opt.ir.Operators.REF_COND_MOVE_opcode; 089import static org.jikesrvm.compilers.opt.ir.Operators.REF_IFCMP_opcode; 090import static org.jikesrvm.compilers.opt.ir.Operators.REF_LOAD_opcode; 091import static org.jikesrvm.compilers.opt.ir.Operators.REF_MOVE_opcode; 092import static org.jikesrvm.compilers.opt.ir.Operators.REF_NEG_opcode; 093import static org.jikesrvm.compilers.opt.ir.Operators.REF_NOT_opcode; 094import static org.jikesrvm.compilers.opt.ir.Operators.REF_OR_opcode; 095import static org.jikesrvm.compilers.opt.ir.Operators.REF_SHL_opcode; 096import static org.jikesrvm.compilers.opt.ir.Operators.REF_SHR_opcode; 097import static org.jikesrvm.compilers.opt.ir.Operators.REF_STORE_opcode; 098import static org.jikesrvm.compilers.opt.ir.Operators.REF_SUB_opcode; 099import static org.jikesrvm.compilers.opt.ir.Operators.REF_USHR_opcode; 100import static org.jikesrvm.compilers.opt.ir.Operators.REF_XOR_opcode; 101import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.CMP_CMOV; 102import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.CMP_FCMOV; 103import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.FCMP_CMOV; 104import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.FCMP_FCMOV; 105import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.FP_ADD; 106import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.FP_DIV; 107import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.FP_MUL; 108import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.FP_NEG; 109import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.FP_REM; 110import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.FP_SUB; 111import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.INT_2FP; 112import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.LCMP_CMOV; 113import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.LONG_2FP; 114import static org.jikesrvm.ia32.ArchConstants.SSE2_FULL; 115 116import java.util.Enumeration; 117 118import org.jikesrvm.VM; 119import org.jikesrvm.compilers.opt.OptimizingCompilerException; 120import org.jikesrvm.compilers.opt.Simplifier; 121import org.jikesrvm.compilers.opt.driver.CompilerPhase; 122import org.jikesrvm.compilers.opt.ir.CondMove; 123import org.jikesrvm.compilers.opt.ir.IR; 124import org.jikesrvm.compilers.opt.ir.Instruction; 125 126/** 127 * Reduce the number of ALU operators considered by BURS 128 */ 129public final class ConvertALUOperators extends CompilerPhase { 130 131 @Override 132 public String getName() { 133 return "ConvertALUOps"; 134 } 135 136 /** 137 * Return this instance of this phase. This phase contains no 138 * per-compilation instance fields. 139 * @param ir not used 140 * @return this 141 */ 142 @Override 143 public CompilerPhase newExecution(IR ir) { 144 return this; 145 } 146 147 @Override 148 public void perform(IR ir) { 149 // Calling Simplifier.simplify ensures that the instruction is 150 // in normalized form. This reduces the number of cases we have to 151 // worry about (and does last minute constant folding on the off 152 // chance we've missed an opportunity...) 153 // BURS assumes that this has been done 154 for (Enumeration<Instruction> instrs = ir.forwardInstrEnumerator(); instrs.hasMoreElements();) { 155 Instruction s = instrs.nextElement(); 156 Simplifier.simplify(false, ir.regpool, ir.options, s); 157 } 158 159 // Pass over instructions 160 for (Enumeration<Instruction> e = ir.forwardInstrEnumerator(); e.hasMoreElements();) { 161 Instruction s = e.nextElement(); 162 163 // BURS doesn't really care, so consolidate to reduce rule space 164 switch (s.getOpcode()) { 165 case REF_ADD_opcode: 166 s.changeOperatorTo(VM.BuildFor32Addr ? INT_ADD : LONG_ADD); 167 break; 168 case REF_SUB_opcode: 169 s.changeOperatorTo(VM.BuildFor32Addr ? INT_SUB : LONG_SUB); 170 break; 171 case REF_NEG_opcode: 172 s.changeOperatorTo(VM.BuildFor32Addr ? INT_NEG : LONG_NEG); 173 break; 174 case REF_NOT_opcode: 175 s.changeOperatorTo(VM.BuildFor32Addr ? INT_NOT : LONG_NOT); 176 break; 177 case REF_AND_opcode: 178 s.changeOperatorTo(VM.BuildFor32Addr ? INT_AND : LONG_AND); 179 break; 180 case REF_OR_opcode: 181 s.changeOperatorTo(VM.BuildFor32Addr ? INT_OR : LONG_OR); 182 break; 183 case REF_XOR_opcode: 184 s.changeOperatorTo(VM.BuildFor32Addr ? INT_XOR : LONG_XOR); 185 break; 186 case REF_SHL_opcode: 187 s.changeOperatorTo(VM.BuildFor32Addr ? INT_SHL : LONG_SHL); 188 break; 189 case REF_SHR_opcode: 190 s.changeOperatorTo(VM.BuildFor32Addr ? INT_SHR : LONG_SHR); 191 break; 192 case REF_USHR_opcode: 193 s.changeOperatorTo(VM.BuildFor32Addr ? INT_USHR : LONG_USHR); 194 break; 195 case REF_LOAD_opcode: 196 s.changeOperatorTo(VM.BuildFor32Addr ? INT_LOAD : LONG_LOAD); 197 break; 198 case REF_STORE_opcode: 199 s.changeOperatorTo(VM.BuildFor32Addr ? INT_STORE : LONG_STORE); 200 break; 201 case REF_ALOAD_opcode: 202 s.changeOperatorTo(VM.BuildFor32Addr ? INT_ALOAD : LONG_ALOAD); 203 break; 204 case REF_ASTORE_opcode: 205 s.changeOperatorTo(VM.BuildFor32Addr ? INT_ASTORE : LONG_ASTORE); 206 break; 207 case REF_MOVE_opcode: 208 s.changeOperatorTo(VM.BuildFor32Addr ? INT_MOVE : LONG_MOVE); 209 break; 210 case REF_IFCMP_opcode: 211 s.changeOperatorTo(VM.BuildFor32Addr ? INT_IFCMP : LONG_IFCMP); 212 break; 213 case BOOLEAN_CMP_ADDR_opcode: 214 s.changeOperatorTo(VM.BuildFor32Addr ? BOOLEAN_CMP_INT : BOOLEAN_CMP_LONG); 215 break; 216 case ATTEMPT_ADDR_opcode: 217 s.changeOperatorTo(VM.BuildFor32Addr ? ATTEMPT_INT : ATTEMPT_LONG); 218 break; 219 case PREPARE_ADDR_opcode: 220 s.changeOperatorTo(VM.BuildFor32Addr ? INT_LOAD : LONG_LOAD); 221 break; 222 case PREPARE_INT_opcode: 223 s.changeOperatorTo(INT_LOAD); 224 break; 225 case PREPARE_LONG_opcode: 226 s.changeOperatorTo(LONG_LOAD); 227 break; 228 case INT_2ADDRSigExt_opcode: 229 s.changeOperatorTo(VM.BuildFor32Addr ? INT_MOVE : INT_2LONG); 230 break; 231 case INT_2ADDRZerExt_opcode: 232 if (VM.BuildFor32Addr) { 233 s.changeOperatorTo(INT_MOVE); 234 } 235 break; 236 case ADDR_2INT_opcode: 237 s.changeOperatorTo(VM.BuildFor32Addr ? INT_MOVE : LONG_2INT); 238 break; 239 case ADDR_2LONG_opcode: 240 // Note that a 32-bit ADDR_2LONG cannot be changed to an INT_2LONG because 241 // INT_2LONG uses the Java conventions for widening by default. Java widening 242 // uses sign extension which is not appropriate for addresses. The unboxed 243 // types that Jikes RVM uses define that the toLong() methods use zero-extension. 244 // For example, for 0xFFFF FFFF (32 bit addresses) the result is supposed to be 245 // 0x0000 0000 FFFF FFFF but with sign extension it would be 246 // 0xFFFF FFFF FFFF FFFF. 247 // Therefore, let BURS rules convert to ADDR_2LONG. The BURS rules can use 248 // methods from BURS_Helpers which provide the possibility to emit code for an 249 // INT_2LONG that uses zero-extension. 250 if (VM.BuildFor64Addr) { 251 s.changeOperatorTo(LONG_MOVE); 252 } 253 break; 254 case LONG_2ADDR_opcode: 255 s.changeOperatorTo(VM.BuildFor32Addr ? LONG_2INT : LONG_MOVE); 256 break; 257 258 case FLOAT_ADD_opcode: 259 if (!SSE2_FULL) 260 s.changeOperatorTo(FP_ADD); 261 break; 262 case DOUBLE_ADD_opcode: 263 if (!SSE2_FULL) 264 s.changeOperatorTo(FP_ADD); 265 break; 266 case FLOAT_SUB_opcode: 267 if (!SSE2_FULL) 268 s.changeOperatorTo(FP_SUB); 269 break; 270 case DOUBLE_SUB_opcode: 271 if (!SSE2_FULL) 272 s.changeOperatorTo(FP_SUB); 273 break; 274 case FLOAT_MUL_opcode: 275 if (!SSE2_FULL) 276 s.changeOperatorTo(FP_MUL); 277 break; 278 case DOUBLE_MUL_opcode: 279 if (!SSE2_FULL) 280 s.changeOperatorTo(FP_MUL); 281 break; 282 case FLOAT_DIV_opcode: 283 if (!SSE2_FULL) 284 s.changeOperatorTo(FP_DIV); 285 break; 286 case DOUBLE_DIV_opcode: 287 if (!SSE2_FULL) 288 s.changeOperatorTo(FP_DIV); 289 break; 290 case FLOAT_REM_opcode: 291 if (!SSE2_FULL) 292 s.changeOperatorTo(FP_REM); 293 break; 294 case DOUBLE_REM_opcode: 295 if (!SSE2_FULL) 296 s.changeOperatorTo(FP_REM); 297 break; 298 case FLOAT_NEG_opcode: 299 if (!SSE2_FULL) 300 s.changeOperatorTo(FP_NEG); 301 break; 302 case DOUBLE_NEG_opcode: 303 if (!SSE2_FULL) 304 s.changeOperatorTo(FP_NEG); 305 break; 306 307 case INT_COND_MOVE_opcode: 308 case REF_COND_MOVE_opcode: 309 s.changeOperatorTo(CondMove.getCond(s).isFLOATINGPOINT() ? FCMP_CMOV : (CondMove.getVal1(s).isLong() ? LCMP_CMOV : CMP_CMOV)); 310 break; 311 case FLOAT_COND_MOVE_opcode: 312 case DOUBLE_COND_MOVE_opcode: 313 s.changeOperatorTo(CondMove.getCond(s).isFLOATINGPOINT() ? FCMP_FCMOV : CMP_FCMOV); 314 break; 315 316 case GUARD_COND_MOVE_opcode: 317 case LONG_COND_MOVE_opcode: 318 OptimizingCompilerException.TODO("Unimplemented conversion" + s); 319 break; 320 321 case INT_2FLOAT_opcode: 322 if (!SSE2_FULL) 323 s.changeOperatorTo(INT_2FP); 324 break; 325 case INT_2DOUBLE_opcode: 326 if (!SSE2_FULL) 327 s.changeOperatorTo(INT_2FP); 328 break; 329 case LONG_2FLOAT_opcode: 330 if (!SSE2_FULL) 331 s.changeOperatorTo(LONG_2FP); 332 break; 333 case LONG_2DOUBLE_opcode: 334 if (!SSE2_FULL) 335 s.changeOperatorTo(LONG_2FP); 336 break; 337 } 338 } 339 } 340}