Mercurial > hg > graal-jvmci-8
comparison graal/GraalCompiler/src/com/sun/c1x/gen/LIRGenerator.java @ 2521:2f271a85d104
Removed intrinsic-related instructions
author | Thomas Wuerthinger <thomas@wuerthinger.net> |
---|---|
date | Wed, 27 Apr 2011 16:40:09 +0200 |
parents | f6125fb5bfbc |
children | 58c05e4c51e2 |
comparison
equal
deleted
inserted
replaced
2520:99307021e3f5 | 2521:2f271a85d104 |
---|---|
36 import com.sun.c1x.asm.*; | 36 import com.sun.c1x.asm.*; |
37 import com.sun.c1x.debug.*; | 37 import com.sun.c1x.debug.*; |
38 import com.sun.c1x.globalstub.*; | 38 import com.sun.c1x.globalstub.*; |
39 import com.sun.c1x.graph.*; | 39 import com.sun.c1x.graph.*; |
40 import com.sun.c1x.ir.*; | 40 import com.sun.c1x.ir.*; |
41 import com.sun.c1x.ir.Value.Flag; | |
42 import com.sun.c1x.lir.*; | 41 import com.sun.c1x.lir.*; |
43 import com.sun.c1x.opt.*; | 42 import com.sun.c1x.opt.*; |
44 import com.sun.c1x.util.*; | 43 import com.sun.c1x.util.*; |
45 import com.sun.c1x.value.*; | 44 import com.sun.c1x.value.*; |
46 import com.sun.c1x.value.FrameState.PhiProcedure; | 45 import com.sun.c1x.value.FrameState.PhiProcedure; |
221 public DeoptimizationStub(FrameState state) { | 220 public DeoptimizationStub(FrameState state) { |
222 info = new LIRDebugInfo(state, null); | 221 info = new LIRDebugInfo(state, null); |
223 } | 222 } |
224 } | 223 } |
225 | 224 |
226 public final void emitGuard(Guard x) { | |
227 FrameState state = x.stateBefore(); | |
228 assert state != null : "deoptimize instruction always needs a state"; | |
229 | |
230 if (deoptimizationStubs == null) { | |
231 deoptimizationStubs = new ArrayList<DeoptimizationStub>(); | |
232 } | |
233 | |
234 // (tw) TODO: Try to reuse an existing stub if possible. | |
235 // It is only allowed if there are no LIR instructions in between that can modify registers. | |
236 | |
237 DeoptimizationStub stub = new DeoptimizationStub(state); | |
238 deoptimizationStubs.add(stub); | |
239 lir.branch(x.condition.negate(), stub.label, stub.info); | |
240 } | |
241 | |
242 public void doBlock(BlockBegin block) { | 225 public void doBlock(BlockBegin block) { |
243 blockDoProlog(block); | 226 blockDoProlog(block); |
244 this.currentBlock = block; | 227 this.currentBlock = block; |
245 | 228 |
246 for (Instruction instr = block; instr != null; instr = instr.next()) { | 229 for (Instruction instr = block; instr != null; instr = instr.next()) { |
429 | 412 |
430 @Override | 413 @Override |
431 public void visitGoto(Goto x) { | 414 public void visitGoto(Goto x) { |
432 setNoResult(x); | 415 setNoResult(x); |
433 | 416 |
434 if (currentBlock.next() instanceof OsrEntry) { | |
435 // need to free up storage used for OSR entry point | |
436 CiValue osrBuffer = currentBlock.next().operand(); | |
437 callRuntime(CiRuntimeCall.OSRMigrationEnd, null, osrBuffer); | |
438 emitXir(xir.genSafepoint(site(x)), x, stateFor(x, x.stateAfter()), null, false); | |
439 } | |
440 | |
441 // emit phi-instruction moves after safepoint since this simplifies | 417 // emit phi-instruction moves after safepoint since this simplifies |
442 // describing the state at the safepoint. | 418 // describing the state at the safepoint. |
443 moveToPhi(x.stateAfter()); | 419 moveToPhi(x.stateAfter()); |
444 | 420 |
445 lir.jump(x.defaultSuccessor()); | 421 lir.jump(x.defaultSuccessor()); |
646 if (x.canTrap()) { | 622 if (x.canTrap()) { |
647 LIRDebugInfo info = stateFor(x); | 623 LIRDebugInfo info = stateFor(x); |
648 lir.nullCheck(value, info); | 624 lir.nullCheck(value, info); |
649 } | 625 } |
650 x.setOperand(value); | 626 x.setOperand(value); |
651 } | |
652 | |
653 @Override | |
654 public void visitOsrEntry(OsrEntry x) { | |
655 // construct our frame and model the production of incoming pointer | |
656 // to the OSR buffer. | |
657 lir.osrEntry(osrBufferPointer()); | |
658 CiValue result = createResultVariable(x); | |
659 lir.move(osrBufferPointer(), result); | |
660 } | 627 } |
661 | 628 |
662 @Override | 629 @Override |
663 public void visitPhi(Phi i) { | 630 public void visitPhi(Phi i) { |
664 Util.shouldNotReachHere(); | 631 Util.shouldNotReachHere(); |
955 if (unwind) { | 922 if (unwind) { |
956 lir.unwindException(exceptionPcOpr(), exceptionOpr, info); | 923 lir.unwindException(exceptionPcOpr(), exceptionOpr, info); |
957 } else { | 924 } else { |
958 lir.throwException(exceptionPcOpr(), argumentOperand, info); | 925 lir.throwException(exceptionPcOpr(), argumentOperand, info); |
959 } | 926 } |
960 } | |
961 | |
962 @Override | |
963 public void visitUnsafeGetObject(UnsafeGetObject x) { | |
964 CiKind kind = x.unsafeOpKind; | |
965 | |
966 CiValue off = load(x.offset()); | |
967 CiValue src = load(x.object()); | |
968 | |
969 CiValue reg = createResultVariable(x); | |
970 | |
971 if (x.isVolatile()) { | |
972 vma.preVolatileRead(); | |
973 } | |
974 genGetObjectUnsafe(reg, src, off, kind, x.isVolatile()); | |
975 if (x.isVolatile()) { | |
976 vma.postVolatileRead(); | |
977 } | |
978 } | |
979 | |
980 @Override | |
981 public void visitUnsafeGetRaw(UnsafeGetRaw x) { | |
982 LIRItem idx = new LIRItem(this); | |
983 CiValue base = load(x.base()); | |
984 if (x.hasIndex()) { | |
985 idx.setInstruction(x.index()); | |
986 idx.loadNonconstant(); | |
987 } | |
988 | |
989 CiValue reg = createResultVariable(x); | |
990 | |
991 int log2scale = 0; | |
992 if (x.hasIndex()) { | |
993 assert x.index().kind.isInt() : "should not find non-int index"; | |
994 log2scale = x.log2Scale(); | |
995 } | |
996 | |
997 assert !x.hasIndex() || idx.instruction == x.index() : "should match"; | |
998 | |
999 CiKind dstKind = x.unsafeOpKind; | |
1000 CiValue indexOp = idx.result(); | |
1001 | |
1002 CiAddress addr = null; | |
1003 if (indexOp.isConstant()) { | |
1004 assert log2scale == 0 : "must not have a scale"; | |
1005 CiConstant constantIndexOp = (CiConstant) indexOp; | |
1006 addr = new CiAddress(dstKind, base, constantIndexOp.asInt()); | |
1007 } else { | |
1008 | |
1009 if (compilation.target.arch.isX86()) { | |
1010 addr = new CiAddress(dstKind, base, indexOp, CiAddress.Scale.fromInt(2 ^ log2scale), 0); | |
1011 | |
1012 } else if (compilation.target.arch.isSPARC()) { | |
1013 if (indexOp.isIllegal() || log2scale == 0) { | |
1014 addr = new CiAddress(dstKind, base, indexOp); | |
1015 } else { | |
1016 CiValue tmp = newVariable(CiKind.Int); | |
1017 lir.shiftLeft(indexOp, log2scale, tmp); | |
1018 addr = new CiAddress(dstKind, base, tmp); | |
1019 } | |
1020 | |
1021 } else { | |
1022 Util.shouldNotReachHere(); | |
1023 } | |
1024 } | |
1025 | |
1026 if (x.mayBeUnaligned() && (dstKind == CiKind.Long || dstKind == CiKind.Double)) { | |
1027 lir.unalignedMove(addr, reg); | |
1028 } else { | |
1029 lir.move(addr, reg); | |
1030 } | |
1031 } | |
1032 | |
1033 @Override | |
1034 public void visitUnsafePrefetchRead(UnsafePrefetchRead x) { | |
1035 visitUnsafePrefetch(x, false); | |
1036 } | |
1037 | |
1038 @Override | |
1039 public void visitUnsafePrefetchWrite(UnsafePrefetchWrite x) { | |
1040 visitUnsafePrefetch(x, true); | |
1041 } | |
1042 | |
1043 @Override | |
1044 public void visitUnsafePutObject(UnsafePutObject x) { | |
1045 CiKind kind = x.unsafeOpKind; | |
1046 LIRItem data = new LIRItem(x.value(), this); | |
1047 | |
1048 CiValue src = load(x.object()); | |
1049 data.loadItem(kind); | |
1050 CiValue off = load(x.offset()); | |
1051 | |
1052 setNoResult(x); | |
1053 | |
1054 if (x.isVolatile()) { | |
1055 vma.preVolatileWrite(); | |
1056 } | |
1057 genPutObjectUnsafe(src, off, data.result(), kind, x.isVolatile()); | |
1058 if (x.isVolatile()) { | |
1059 vma.postVolatileWrite(); | |
1060 } | |
1061 } | |
1062 | |
1063 @Override | |
1064 public void visitUnsafePutRaw(UnsafePutRaw x) { | |
1065 int log2scale = 0; | |
1066 CiKind kind = x.unsafeOpKind; | |
1067 | |
1068 if (x.hasIndex()) { | |
1069 assert x.index().kind.isInt() : "should not find non-int index"; | |
1070 log2scale = x.log2scale(); | |
1071 } | |
1072 | |
1073 LIRItem value = new LIRItem(x.value(), this); | |
1074 LIRItem idx = new LIRItem(this); | |
1075 | |
1076 CiValue base = load(x.base()); | |
1077 if (x.hasIndex()) { | |
1078 idx.setInstruction(x.index()); | |
1079 idx.loadItem(); | |
1080 } | |
1081 | |
1082 value.loadItem(kind); | |
1083 | |
1084 setNoResult(x); | |
1085 | |
1086 CiValue indexOp = idx.result(); | |
1087 if (log2scale != 0) { | |
1088 // temporary fix (platform dependent code without shift on Intel would be better) | |
1089 indexOp = newVariable(CiKind.Int); | |
1090 lir.move(idx.result(), indexOp); | |
1091 lir.shiftLeft(indexOp, log2scale, indexOp); | |
1092 } | |
1093 | |
1094 CiValue addr = new CiAddress(x.unsafeOpKind, base, indexOp); | |
1095 lir.move(value.result(), addr); | |
1096 } | 927 } |
1097 | 928 |
1098 private void blockDoEpilog(BlockBegin block) { | 929 private void blockDoEpilog(BlockBegin block) { |
1099 if (C1XOptions.PrintIRWithLIR) { | 930 if (C1XOptions.PrintIRWithLIR) { |
1100 TTY.println(); | 931 TTY.println(); |
1213 lir.branch(Condition.LE, CiKind.Int, dest); | 1044 lir.branch(Condition.LE, CiKind.Int, dest); |
1214 lir.branchDestination(l); | 1045 lir.branchDestination(l); |
1215 } | 1046 } |
1216 } | 1047 } |
1217 lir.jump(defaultSux); | 1048 lir.jump(defaultSux); |
1218 } | |
1219 | |
1220 private void visitUnsafePrefetch(UnsafePrefetch x, boolean isStore) { | |
1221 LIRItem src = new LIRItem(x.object(), this); | |
1222 LIRItem off = new LIRItem(x.offset(), this); | |
1223 | |
1224 src.loadItem(); | |
1225 if (!(off.result().isConstant() && canInlineAsConstant(x.offset()))) { | |
1226 off.loadItem(); | |
1227 } | |
1228 | |
1229 setNoResult(x); | |
1230 | |
1231 CiAddress addr = genAddress(src.result(), off.result(), 0, 0, CiKind.Byte); | |
1232 lir.prefetch(addr, isStore); | |
1233 } | 1049 } |
1234 | 1050 |
1235 protected void arithmeticOpFpu(int code, CiValue result, CiValue left, CiValue right, CiValue tmp) { | 1051 protected void arithmeticOpFpu(int code, CiValue result, CiValue left, CiValue right, CiValue tmp) { |
1236 CiValue leftOp = left; | 1052 CiValue leftOp = left; |
1237 | 1053 |
1848 return "XirSupport<" + current + ">"; | 1664 return "XirSupport<" + current + ">"; |
1849 } | 1665 } |
1850 | 1666 |
1851 } | 1667 } |
1852 | 1668 |
1853 public void arrayCopy(RiType type, ArrayCopy arrayCopy, XirSnippet snippet) { | |
1854 emitXir(snippet, arrayCopy, stateFor(arrayCopy), null, false); | |
1855 } | |
1856 | |
1857 @Override | |
1858 public void visitArrayCopy(ArrayCopy arrayCopy) { | |
1859 Value src = arrayCopy.src(); | |
1860 Value dest = arrayCopy.dest(); | |
1861 Value srcPos = arrayCopy.srcPos(); | |
1862 Value destPos = arrayCopy.destPos(); | |
1863 Value length = arrayCopy.length(); | |
1864 RiType srcType = src.declaredType(); | |
1865 RiType destType = dest.declaredType(); | |
1866 if ((srcType != null && srcType.isArrayClass()) || (destType != null && destType.isArrayClass())) { | |
1867 RiType type = (srcType == null) ? destType : srcType; | |
1868 if ((srcType == null || destType == null || srcType.kind() != destType.kind()) && type.kind() != CiKind.Object) { | |
1869 TypeEqualityCheck typeCheck = new TypeEqualityCheck(src, dest, arrayCopy.stateBefore(), Condition.EQ); | |
1870 visitTypeEqualityCheck(typeCheck); | |
1871 } | |
1872 boolean inputsSame = (src == dest); | |
1873 boolean inputsDifferent = !inputsSame && (src.checkFlag(Flag.ResultIsUnique) || dest.checkFlag(Flag.ResultIsUnique)); | |
1874 boolean needsStoreCheck = type.componentType().kind() == CiKind.Object && destType != srcType; | |
1875 if (!needsStoreCheck) { | |
1876 arrayCopy.setFlag(Flag.NoStoreCheck); | |
1877 } | |
1878 XirSnippet snippet = xir.genArrayCopy(site(arrayCopy), toXirArgument(src), toXirArgument(srcPos), toXirArgument(dest), toXirArgument(destPos), toXirArgument(length), type.componentType(), inputsSame, inputsDifferent); | |
1879 arrayCopy(type, arrayCopy, snippet); | |
1880 return; | |
1881 } | |
1882 arrayCopySlow(arrayCopy); | |
1883 } | |
1884 | |
1885 private void arrayCopySlow(ArrayCopy arrayCopy) { | |
1886 emitInvokeKnown(arrayCopy.arrayCopyMethod, arrayCopy.stateBefore(), arrayCopy.src(), arrayCopy.srcPos(), arrayCopy.dest(), arrayCopy.destPos(), arrayCopy.length()); | |
1887 } | |
1888 | |
1889 private CiValue emitInvokeKnown(RiMethod method, FrameState stateBefore, Value... args) { | 1669 private CiValue emitInvokeKnown(RiMethod method, FrameState stateBefore, Value... args) { |
1890 boolean isStatic = Modifier.isStatic(method.accessFlags()); | 1670 boolean isStatic = Modifier.isStatic(method.accessFlags()); |
1891 Invoke invoke = new Invoke(isStatic ? Bytecodes.INVOKESTATIC : Bytecodes.INVOKESPECIAL, method.signature().returnKind(), args, isStatic, method, null, stateBefore); | 1671 Invoke invoke = new Invoke(isStatic ? Bytecodes.INVOKESTATIC : Bytecodes.INVOKESPECIAL, method.signature().returnKind(), args, isStatic, method, null, stateBefore); |
1892 visitInvoke(invoke); | 1672 visitInvoke(invoke); |
1893 return invoke.operand(); | 1673 return invoke.operand(); |
1894 } | 1674 } |
1895 | |
1896 @Override | |
1897 public void visitTypeEqualityCheck(TypeEqualityCheck typeEqualityCheck) { | |
1898 Value x = typeEqualityCheck.left(); | |
1899 Value y = typeEqualityCheck.right(); | |
1900 | |
1901 CiValue leftValue = emitXir(xir.genGetClass(site(typeEqualityCheck), toXirArgument(x)), typeEqualityCheck, stateFor(typeEqualityCheck), null, false); | |
1902 CiValue rightValue = emitXir(xir.genGetClass(site(typeEqualityCheck), toXirArgument(y)), typeEqualityCheck, stateFor(typeEqualityCheck), null, false); | |
1903 lir.cmp(typeEqualityCheck.condition.negate(), leftValue, rightValue); | |
1904 emitGuard(typeEqualityCheck); | |
1905 } | |
1906 } | 1675 } |