Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(653)

Side by Side Diff: runtime/vm/flow_graph_compiler_x64.cc

Issue 10875030: Add support for XMM registers in SSA code generation pipeline. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64.
6 #if defined(TARGET_ARCH_X64) 6 #if defined(TARGET_ARCH_X64)
7 7
8 #include "vm/flow_graph_compiler.h" 8 #include "vm/flow_graph_compiler.h"
9 9
10 #include "lib/error.h" 10 #include "lib/error.h"
(...skipping 852 matching lines...) Expand 10 before | Expand all | Expand 10 after
863 __ testq(RAX, Immediate(kSmiTagMask)); 863 __ testq(RAX, Immediate(kSmiTagMask));
864 __ j(ZERO, &smi_to_double); 864 __ j(ZERO, &smi_to_double);
865 __ CompareClassId(RAX, kDoubleCid); 865 __ CompareClassId(RAX, kDoubleCid);
866 __ j(NOT_EQUAL, &call_method); 866 __ j(NOT_EQUAL, &call_method);
867 __ movsd(XMM1, FieldAddress(RAX, Double::value_offset())); 867 __ movsd(XMM1, FieldAddress(RAX, Double::value_offset()));
868 __ Bind(&double_op); 868 __ Bind(&double_op);
869 __ sqrtsd(XMM0, XMM1); 869 __ sqrtsd(XMM0, XMM1);
870 AssemblerMacros::TryAllocate(assembler_, 870 AssemblerMacros::TryAllocate(assembler_,
871 double_class_, 871 double_class_,
872 &call_method, 872 &call_method,
873 Assembler::kNearJump,
873 RAX); // Result register. 874 RAX); // Result register.
874 __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0); 875 __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0);
875 __ Drop(1); 876 __ Drop(1);
876 __ jmp(done); 877 __ jmp(done);
877 __ Bind(&smi_to_double); 878 __ Bind(&smi_to_double);
878 __ SmiUntag(RAX); 879 __ SmiUntag(RAX);
879 __ cvtsi2sd(XMM1, RAX); 880 __ cvtsi2sd(XMM1, RAX);
880 __ jmp(&double_op); 881 __ jmp(&double_op);
881 __ Bind(&call_method); 882 __ Bind(&call_method);
882 } 883 }
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
1087 __ movsd(result, FieldAddress(reg, Double::value_offset())); 1088 __ movsd(result, FieldAddress(reg, Double::value_offset()));
1088 __ jmp(&done); 1089 __ jmp(&done);
1089 __ Bind(&is_smi); 1090 __ Bind(&is_smi);
1090 __ movq(temp, reg); 1091 __ movq(temp, reg);
1091 __ SmiUntag(temp); 1092 __ SmiUntag(temp);
1092 __ cvtsi2sd(result, temp); 1093 __ cvtsi2sd(result, temp);
1093 __ Bind(&done); 1094 __ Bind(&done);
1094 } 1095 }
1095 1096
1096 1097
1098 void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) {
1099 // TODO(vegorov): consider saving only caller save (volatile) registers.
1100 const intptr_t xmm_regs_count = locs->live_registers()->xmm_regs_count();
1101 if (xmm_regs_count > 0) {
1102 // Pointer maps don't support pushed untagged values so we reserve spill
1103 // slots at the top of the spill slot area for live XMM registers.
1104 intptr_t stack_offs = (StackSize() + 1) * kWordSize;
1105 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) {
1106 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx);
1107 if (locs->live_registers()->ContainsXmmRegister(xmm_reg)) {
1108 __ movsd(Address(RBP, -stack_offs), xmm_reg);
1109 stack_offs += kDoubleSize;
1110 }
1111 }
1112 }
1113
1114 for (intptr_t reg_idx = 0; reg_idx < kNumberOfCpuRegisters; ++reg_idx) {
1115 Register reg = static_cast<Register>(reg_idx);
1116 if (locs->live_registers()->ContainsRegister(reg)) {
1117 __ pushq(reg);
1118 }
1119 }
1120 }
1121
1122
1123 void FlowGraphCompiler::RestoreLiveRegisters(LocationSummary* locs) {
1124 for (intptr_t reg_idx = kNumberOfCpuRegisters - 1; reg_idx >= 0; --reg_idx) {
1125 Register reg = static_cast<Register>(reg_idx);
1126 if (locs->live_registers()->ContainsRegister(reg)) {
1127 __ popq(reg);
1128 }
1129 }
1130
1131 const intptr_t xmm_regs_count = locs->live_registers()->xmm_regs_count();
1132 if (xmm_regs_count > 0) {
1133 // Pointer maps don't support pushed untagged values so we reserve spill
1134 // slots at the top of the spill slot area for live XMM registers.
1135 intptr_t stack_offs = (StackSize() + 1) * kWordSize;
1136 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) {
1137 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx);
1138 if (locs->live_registers()->ContainsXmmRegister(xmm_reg)) {
1139 __ movsd(xmm_reg, Address(RBP, -stack_offs));
1140 stack_offs += kDoubleSize;
1141 }
1142 }
1143 }
1144 }
1145
1146
1097 #undef __ 1147 #undef __
1098 #define __ compiler_->assembler()-> 1148 #define __ compiler_->assembler()->
1099 1149
1100 1150
1101 static Address ToStackSlotAddress(Location loc) { 1151 static Address ToStackSlotAddress(Location loc) {
1102 ASSERT(loc.IsStackSlot());
1103 const intptr_t index = loc.stack_index(); 1152 const intptr_t index = loc.stack_index();
1104 if (index < 0) { 1153 if (index < 0) {
1105 const intptr_t offset = (1 - index) * kWordSize; 1154 const intptr_t offset = (1 - index) * kWordSize;
1106 return Address(RBP, offset); 1155 return Address(RBP, offset);
1107 } else { 1156 } else {
1108 const intptr_t offset = 1157 const intptr_t offset =
1109 (ParsedFunction::kFirstLocalSlotIndex - index) * kWordSize; 1158 (ParsedFunction::kFirstLocalSlotIndex - index) * kWordSize;
1110 return Address(RBP, offset); 1159 return Address(RBP, offset);
1111 } 1160 }
1112 } 1161 }
(...skipping 12 matching lines...) Expand all
1125 __ movq(ToStackSlotAddress(destination), source.reg()); 1174 __ movq(ToStackSlotAddress(destination), source.reg());
1126 } 1175 }
1127 } else if (source.IsStackSlot()) { 1176 } else if (source.IsStackSlot()) {
1128 if (destination.IsRegister()) { 1177 if (destination.IsRegister()) {
1129 __ movq(destination.reg(), ToStackSlotAddress(source)); 1178 __ movq(destination.reg(), ToStackSlotAddress(source));
1130 } else { 1179 } else {
1131 ASSERT(destination.IsStackSlot()); 1180 ASSERT(destination.IsStackSlot());
1132 MoveMemoryToMemory(ToStackSlotAddress(destination), 1181 MoveMemoryToMemory(ToStackSlotAddress(destination),
1133 ToStackSlotAddress(source)); 1182 ToStackSlotAddress(source));
1134 } 1183 }
1184 } else if (source.IsXmmRegister()) {
1185 if (destination.IsXmmRegister()) {
1186 // Optimization manual recommends using MOVAPS for register
1187 // to register moves.
1188 __ movaps(destination.xmm_reg(), source.xmm_reg());
1189 } else {
1190 ASSERT(destination.IsDoubleStackSlot());
1191 __ movsd(ToStackSlotAddress(destination), source.xmm_reg());
1192 }
1193 } else if (source.IsDoubleStackSlot()) {
1194 if (destination.IsXmmRegister()) {
1195 __ movsd(destination.xmm_reg(), ToStackSlotAddress(source));
1196 } else {
1197 ASSERT(destination.IsDoubleStackSlot());
1198 __ movsd(XMM0, ToStackSlotAddress(source));
1199 __ movsd(ToStackSlotAddress(destination), XMM0);
1200 }
1135 } else { 1201 } else {
1136 ASSERT(source.IsConstant()); 1202 ASSERT(source.IsConstant());
1137 if (destination.IsRegister()) { 1203 if (destination.IsRegister()) {
1138 __ LoadObject(destination.reg(), source.constant()); 1204 __ LoadObject(destination.reg(), source.constant());
1139 } else { 1205 } else {
1140 ASSERT(destination.IsStackSlot()); 1206 ASSERT(destination.IsStackSlot());
1141 StoreObject(ToStackSlotAddress(destination), source.constant()); 1207 StoreObject(ToStackSlotAddress(destination), source.constant());
1142 } 1208 }
1143 } 1209 }
1144 1210
1145 move->Eliminate(); 1211 move->Eliminate();
1146 } 1212 }
1147 1213
1148 1214
1149 void ParallelMoveResolver::EmitSwap(int index) { 1215 void ParallelMoveResolver::EmitSwap(int index) {
1150 MoveOperands* move = moves_[index]; 1216 MoveOperands* move = moves_[index];
1151 const Location source = move->src(); 1217 const Location source = move->src();
1152 const Location destination = move->dest(); 1218 const Location destination = move->dest();
1153 1219
1154 if (source.IsRegister() && destination.IsRegister()) { 1220 if (source.IsRegister() && destination.IsRegister()) {
1155 __ xchgq(destination.reg(), source.reg()); 1221 __ xchgq(destination.reg(), source.reg());
1156 } else if (source.IsRegister() && destination.IsStackSlot()) { 1222 } else if (source.IsRegister() && destination.IsStackSlot()) {
1157 Exchange(source.reg(), ToStackSlotAddress(destination)); 1223 Exchange(source.reg(), ToStackSlotAddress(destination));
1158 } else if (source.IsStackSlot() && destination.IsRegister()) { 1224 } else if (source.IsStackSlot() && destination.IsRegister()) {
1159 Exchange(destination.reg(), ToStackSlotAddress(source)); 1225 Exchange(destination.reg(), ToStackSlotAddress(source));
1160 } else if (source.IsStackSlot() && destination.IsStackSlot()) { 1226 } else if (source.IsStackSlot() && destination.IsStackSlot()) {
1161 Exchange(ToStackSlotAddress(destination), ToStackSlotAddress(source)); 1227 Exchange(ToStackSlotAddress(destination), ToStackSlotAddress(source));
1228 } else if (source.IsXmmRegister() && destination.IsXmmRegister()) {
1229 __ movaps(XMM0, source.xmm_reg());
1230 __ movaps(source.xmm_reg(), destination.xmm_reg());
1231 __ movaps(destination.xmm_reg(), XMM0);
1232 } else if (source.IsXmmRegister() || destination.IsXmmRegister()) {
1233 ASSERT(destination.IsDoubleStackSlot() || source.IsDoubleStackSlot());
1234 XmmRegister reg = source.IsXmmRegister() ? source.xmm_reg()
1235 : destination.xmm_reg();
1236 Address slot_address =
1237 ToStackSlotAddress(source.IsXmmRegister() ? destination : source);
1238
1239 __ movsd(XMM0, slot_address);
1240 __ movsd(slot_address, reg);
1241 __ movaps(reg, XMM0);
1162 } else { 1242 } else {
1163 UNREACHABLE(); 1243 UNREACHABLE();
1164 } 1244 }
1165 1245
1166 // The swap of source and destination has executed a move from source to 1246 // The swap of source and destination has executed a move from source to
1167 // destination. 1247 // destination.
1168 move->Eliminate(); 1248 move->Eliminate();
1169 1249
1170 // Any unperformed (including pending) move with a source of either 1250 // Any unperformed (including pending) move with a source of either
1171 // this move's source or destination needs to have their source 1251 // this move's source or destination needs to have their source
(...skipping 28 matching lines...) Expand all
1200 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) { 1280 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) {
1201 __ Exchange(mem1, mem2); 1281 __ Exchange(mem1, mem2);
1202 } 1282 }
1203 1283
1204 1284
1205 #undef __ 1285 #undef __
1206 1286
1207 } // namespace dart 1287 } // namespace dart
1208 1288
1209 #endif // defined TARGET_ARCH_X64 1289 #endif // defined TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698