Changeset 195981 in webkit
- Timestamp:
- Feb 1, 2016 3:19:26 PM (8 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r195956 r195981 1 2016-02-01 Benjamin Poulain <benjamin@webkit.org> 2 3 [JSC] IRC can coalesce the frame pointer with a Tmp that is modified 4 https://bugs.webkit.org/show_bug.cgi?id=153694 5 6 Reviewed by Filip Pizlo. 7 8 Let's say we have: 9 Move(FP, Tmp1) 10 Add64(#1, Tmp1) 11 12 If we were to coalesce the Move, we would modify the frame pointer. 13 Well, that's exactly what was happening with IRC. 14 15 Since the epilogue is not know to Air before IRC, the liveness analysis 16 never discovers that FP is live when Tmp1 is UseDef by Add64. Adding 17 FP would a be a problem anyway for a bunch of reasons. 18 19 I tried two ways to prevent IRC to override IRC: 20 1) Add an interference edge with FP for all non-duplication Defs. 21 2) Let coalesce() know about FP and constraint any coalescing with a re-Def. 22 23 The two are within margin of error for performance. The second one was considerably 24 more complicated. This patch implements the first one. 25 26 Some extra note: 27 -It is very important to not increment the degree of a Tmp when making it interfere 28 with FP. FP is not a valid color, it is not counted in the "K" colors considered 29 for coloring. Increasing the degree with the edge to FP would make every stage 30 pessimistic since there is an extra degree that can never be removed. 31 -I put "interferenceEdges" and "adjacencyList" in an inconsistent state. 32 This is intentional, "interferenceEdges" is used to test the existence of an edge, 33 "adjacencyList" is used to go over all the edges. In this case, we don't want 34 the edge with FP to be considered when pruning the graph. 35 36 * b3/air/AirIteratedRegisterCoalescing.cpp: 37 One branch could be transformed into an assertion: TmpLiveness is type specific now. 38 * b3/testb3.cpp: 39 (JSC::B3::testOverrideFramePointer): 40 (JSC::B3::run): 41 1 42 2016-02-01 Csaba Osztrogonác <ossy@webkit.org> 2 43 -
trunk/Source/JavaScriptCore/b3/air/AirIteratedRegisterCoalescing.cpp
r195788 r195981 892 892 893 893 for (const Tmp& liveTmp : liveTmps) { 894 if (liveTmp.isGP() == (type == Arg::GP)) 895 addEdge(arg, liveTmp); 894 ASSERT(liveTmp.isGP() == (type == Arg::GP)); 895 addEdge(arg, liveTmp); 896 } 897 898 if (type == Arg::GP && !arg.isGPR()) { 899 m_interferenceEdges.add(InterferenceEdge( 900 AbsoluteTmpMapper<type>::absoluteIndex(Tmp(MacroAssembler::framePointerRegister)), 901 AbsoluteTmpMapper<type>::absoluteIndex(arg))); 896 902 } 897 903 }); … … 1069 1075 } 1070 1076 1071 for (const auto& tmp : tmpsWithInterferences) 1072 out.print(" ", tmp.internalValue(), " [label=\"", tmp, " (", m_degrees[AbsoluteTmpMapper<type>::absoluteIndex(tmp)], ")\"];\n"); 1077 for (const auto& tmp : tmpsWithInterferences) { 1078 unsigned tmpIndex = AbsoluteTmpMapper<type>::absoluteIndex(tmp); 1079 if (tmpIndex < m_degrees.size()) 1080 out.print(" ", tmp.internalValue(), " [label=\"", tmp, " (", m_degrees[tmpIndex], ")\"];\n"); 1081 else 1082 out.print(" ", tmp.internalValue(), " [label=\"", tmp, "\"];\n"); 1083 } 1073 1084 1074 1085 for (const auto& edge : m_interferenceEdges) … … 1130 1141 while (true) { 1131 1142 ++m_numIterations; 1143 1144 if (traceDebug) 1145 dataLog("Code at iteration ", m_numIterations, ":\n", m_code); 1132 1146 1133 1147 // FIXME: One way to optimize this code is to remove the recomputation inside the fixpoint. … … 1149 1163 if (!allocator.requiresSpilling()) { 1150 1164 assignRegistersToTmp(allocator); 1165 if (traceDebug) 1166 dataLog("Successfull allocation at iteration ", m_numIterations, ":\n", m_code); 1167 1151 1168 return; 1152 1169 } -
trunk/Source/JavaScriptCore/b3/testb3.cpp
r195906 r195981 4982 4982 CHECK(fp < &proc); 4983 4983 CHECK(fp >= bitwise_cast<char*>(&proc) - 10000); 4984 } 4985 4986 void testOverrideFramePointer() 4987 { 4988 { 4989 Procedure proc; 4990 BasicBlock* root = proc.addBlock(); 4991 4992 // Add a stack slot to make the frame non trivial. 4993 root->appendNew<SlotBaseValue>(proc, Origin(), proc.addStackSlot(8, StackSlotKind::Locked)); 4994 4995 // Sub on x86 UseDef the source. If FP is not protected correctly, it will be overridden since it is the last visible use. 4996 Value* offset = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); 4997 Value* fp = root->appendNew<Value>(proc, FramePointer, Origin()); 4998 Value* result = root->appendNew<Value>(proc, Sub, Origin(), fp, offset); 4999 5000 root->appendNew<ControlValue>(proc, Return, Origin(), result); 5001 CHECK(compileAndRun<int64_t>(proc, 1)); 5002 } 5003 { 5004 Procedure proc; 5005 BasicBlock* root = proc.addBlock(); 5006 5007 root->appendNew<SlotBaseValue>(proc, Origin(), proc.addStackSlot(8, StackSlotKind::Locked)); 5008 5009 Value* offset = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); 5010 Value* fp = root->appendNew<Value>(proc, FramePointer, Origin()); 5011 Value* offsetFP = root->appendNew<Value>(proc, BitAnd, Origin(), offset, fp); 5012 Value* arg = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); 5013 Value* offsetArg = root->appendNew<Value>(proc, Add, Origin(), offset, arg); 5014 Value* result = root->appendNew<Value>(proc, Add, Origin(), offsetArg, offsetFP); 5015 5016 root->appendNew<ControlValue>(proc, Return, Origin(), result); 5017 CHECK(compileAndRun<int64_t>(proc, 1, 2)); 5018 } 4984 5019 } 4985 5020 … … 10767 10802 RUN(testLoadAddrShift(3)); 10768 10803 RUN(testFramePointer()); 10804 RUN(testOverrideFramePointer()); 10769 10805 RUN(testStackSlot()); 10770 10806 RUN(testLoadFromFramePointer());
Note: See TracChangeset
for help on using the changeset viewer.