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

Side by Side Diff: src/arm/assembler-arm.cc

Issue 2004006: ARM: new patterns to optimize LDR, STR,PUSH/POP on different regs, with/without using REG COPY (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 7 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
« no previous file with comments | « src/arm/assembler-arm.h ('k') | src/flag-definitions.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 1994-2006 Sun Microsystems Inc. 1 // Copyright (c) 1994-2006 Sun Microsystems Inc.
2 // All Rights Reserved. 2 // All Rights Reserved.
3 // 3 //
4 // Redistribution and use in source and binary forms, with or without 4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions 5 // modification, are permitted provided that the following conditions
6 // are met: 6 // are met:
7 // 7 //
8 // - Redistributions of source code must retain the above copyright notice, 8 // - Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer. 9 // this list of conditions and the following disclaimer.
10 // 10 //
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 // mov lr, pc 261 // mov lr, pc
262 const Instr kMovLrPc = al | 13*B21 | pc.code() | lr.code() * B12; 262 const Instr kMovLrPc = al | 13*B21 | pc.code() | lr.code() * B12;
263 // ldr rd, [pc, #offset] 263 // ldr rd, [pc, #offset]
264 const Instr kLdrPCMask = CondMask | 15 * B24 | 7 * B20 | 15 * B16; 264 const Instr kLdrPCMask = CondMask | 15 * B24 | 7 * B20 | 15 * B16;
265 const Instr kLdrPCPattern = al | 5 * B24 | L | pc.code() * B16; 265 const Instr kLdrPCPattern = al | 5 * B24 | L | pc.code() * B16;
266 // blxcc rm 266 // blxcc rm
267 const Instr kBlxRegMask = 267 const Instr kBlxRegMask =
268 15 * B24 | 15 * B20 | 15 * B16 | 15 * B12 | 15 * B8 | 15 * B4; 268 15 * B24 | 15 * B20 | 15 * B16 | 15 * B12 | 15 * B8 | 15 * B4;
269 const Instr kBlxRegPattern = 269 const Instr kBlxRegPattern =
270 B24 | B21 | 15 * B16 | 15 * B12 | 15 * B8 | 3 * B4; 270 B24 | B21 | 15 * B16 | 15 * B12 | 15 * B8 | 3 * B4;
271 // A mask for the Rd register for push, pop, ldr, str instructions.
272 const Instr kRdMask = 0x0000f000;
273 static const Instr kLdrRegFpOffsetPattern =
274 al | B26 | L | Offset | fp.code() * B16;
275 static const Instr kStrRegFpOffsetPattern =
276 al | B26 | Offset | fp.code() * B16;
277 static const Instr kLdrRegFpNegOffsetPattern =
278 al | B26 | L | NegOffset | fp.code() * B16;
279 static const Instr kStrRegFpNegOffsetPattern =
280 al | B26 | NegOffset | fp.code() * B16;
281 static const Instr kLdrStrInstrTypeMask = 0xffff0000;
282 static const Instr kLdrStrInstrArgumentMask = 0x0000ffff;
283 static const Instr kLdrStrOffsetMask = 0x00000fff;
284 static const int kRdShift = 12;
271 285
272 // Spare buffer. 286 // Spare buffer.
273 static const int kMinimalBufferSize = 4*KB; 287 static const int kMinimalBufferSize = 4*KB;
274 static byte* spare_buffer_ = NULL; 288 static byte* spare_buffer_ = NULL;
275 289
276 Assembler::Assembler(void* buffer, int buffer_size) { 290 Assembler::Assembler(void* buffer, int buffer_size) {
277 if (buffer == NULL) { 291 if (buffer == NULL) {
278 // Do our own buffer management. 292 // Do our own buffer management.
279 if (buffer_size <= kMinimalBufferSize) { 293 if (buffer_size <= kMinimalBufferSize) {
280 buffer_size = kMinimalBufferSize; 294 buffer_size = kMinimalBufferSize;
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
388 bool positive = offset >= 0; 402 bool positive = offset >= 0;
389 if (!positive) offset = -offset; 403 if (!positive) offset = -offset;
390 ASSERT(is_uint12(offset)); 404 ASSERT(is_uint12(offset));
391 // Set bit indicating whether the offset should be added. 405 // Set bit indicating whether the offset should be added.
392 instr = (instr & ~B23) | (positive ? B23 : 0); 406 instr = (instr & ~B23) | (positive ? B23 : 0);
393 // Set the actual offset. 407 // Set the actual offset.
394 return (instr & ~Off12Mask) | offset; 408 return (instr & ~Off12Mask) | offset;
395 } 409 }
396 410
397 411
412 Register Assembler::GetRd(Instr instr) {
413 Register reg;
414 reg.code_ = ((instr & kRdMask) >> kRdShift);
415 return reg;
416 }
417
418
419 bool Assembler::IsPush(Instr instr) {
420 return ((instr & ~kRdMask) == kPushRegPattern);
421 }
422
423
424 bool Assembler::IsPop(Instr instr) {
425 return ((instr & ~kRdMask) == kPopRegPattern);
426 }
427
428
429 bool Assembler::IsStrRegFpOffset(Instr instr) {
430 return ((instr & kLdrStrInstrTypeMask) == kStrRegFpOffsetPattern);
431 }
432
433
434 bool Assembler::IsLdrRegFpOffset(Instr instr) {
435 return ((instr & kLdrStrInstrTypeMask) == kLdrRegFpOffsetPattern);
436 }
437
438
439 bool Assembler::IsStrRegFpNegOffset(Instr instr) {
440 return ((instr & kLdrStrInstrTypeMask) == kStrRegFpNegOffsetPattern);
441 }
442
443
444 bool Assembler::IsLdrRegFpNegOffset(Instr instr) {
445 return ((instr & kLdrStrInstrTypeMask) == kLdrRegFpNegOffsetPattern);
446 }
447
448
398 // Labels refer to positions in the (to be) generated code. 449 // Labels refer to positions in the (to be) generated code.
399 // There are bound, linked, and unused labels. 450 // There are bound, linked, and unused labels.
400 // 451 //
401 // Bound labels refer to known positions in the already 452 // Bound labels refer to known positions in the already
402 // generated code. pos() is the position the label refers to. 453 // generated code. pos() is the position the label refers to.
403 // 454 //
404 // Linked labels refer to unknown positions in the code 455 // Linked labels refer to unknown positions in the code
405 // to be generated; pos() is the position of the last 456 // to be generated; pos() is the position of the last
406 // instruction using the label. 457 // instruction using the label.
407 458
(...skipping 671 matching lines...) Expand 10 before | Expand all | Expand 10 after
1079 } 1130 }
1080 1131
1081 1132
1082 // Load/Store instructions. 1133 // Load/Store instructions.
1083 void Assembler::ldr(Register dst, const MemOperand& src, Condition cond) { 1134 void Assembler::ldr(Register dst, const MemOperand& src, Condition cond) {
1084 if (dst.is(pc)) { 1135 if (dst.is(pc)) {
1085 WriteRecordedPositions(); 1136 WriteRecordedPositions();
1086 } 1137 }
1087 addrmod2(cond | B26 | L, dst, src); 1138 addrmod2(cond | B26 | L, dst, src);
1088 1139
1089 // Eliminate pattern: push(r), pop(r) 1140 // Eliminate pattern: push(ry), pop(rx)
1090 // str(r, MemOperand(sp, 4, NegPreIndex), al) 1141 // str(ry, MemOperand(sp, 4, NegPreIndex), al)
1091 // ldr(r, MemOperand(sp, 4, PostIndex), al) 1142 // ldr(rx, MemOperand(sp, 4, PostIndex), al)
1092 // Both instructions can be eliminated. 1143 // Both instructions can be eliminated if ry = rx.
1144 // If ry != rx, a register copy from ry to rx is inserted
1145 // after eliminating the push and the pop instructions.
1093 int pattern_size = 2 * kInstrSize; 1146 int pattern_size = 2 * kInstrSize;
1147 Instr push_instr = instr_at(pc_ - 2 * kInstrSize);
1148 Instr pop_instr = instr_at(pc_ - 1 * kInstrSize);
1149
1094 if (FLAG_push_pop_elimination && 1150 if (FLAG_push_pop_elimination &&
1151 last_bound_pos_ <= (pc_offset() - pattern_size) &&
1152 reloc_info_writer.last_pc() <= (pc_ - pattern_size) &&
1153 IsPush(push_instr) &&
1154 IsPop(pop_instr)) {
1155 if ((pop_instr & kRdMask) != (push_instr & kRdMask)) {
1156 // For consecutive push and pop on different registers,
1157 // we delete both the push & pop and insert a register move.
1158 // push ry, pop rx --> mov rx, ry
1159 Register reg_pushed, reg_popped;
1160 reg_pushed = GetRd(push_instr);
1161 reg_popped = GetRd(pop_instr);
1162 pc_ -= 2 * kInstrSize;
1163 // Insert a mov instruction, which is better than a pair of push & pop
1164 mov(reg_popped, reg_pushed);
1165 if (FLAG_print_push_pop_elimination) {
1166 PrintF("%x push/pop (diff reg) replaced by a reg move\n", pc_offset());
1167 }
1168 } else {
1169 // For consecutive push and pop on the same register,
1170 // both the push and the pop can be deleted.
1171 pc_ -= 2 * kInstrSize;
1172 if (FLAG_print_push_pop_elimination) {
1173 PrintF("%x push/pop (same reg) eliminated\n", pc_offset());
1174 }
1175 }
1176 }
1177
1178 pattern_size = 2 * kInstrSize;
1179 if (FLAG_peephole_optimization &&
1095 last_bound_pos_ <= (pc_offset() - pattern_size) && 1180 last_bound_pos_ <= (pc_offset() - pattern_size) &&
1096 reloc_info_writer.last_pc() <= (pc_ - pattern_size) && 1181 reloc_info_writer.last_pc() <= (pc_ - pattern_size)) {
1097 // Pattern. 1182 Instr str_instr = instr_at(pc_ - 2 * kInstrSize);
1098 instr_at(pc_ - 1 * kInstrSize) == (kPopRegPattern | dst.code() * B12) && 1183 Instr ldr_instr = instr_at(pc_ - 1 * kInstrSize);
1099 instr_at(pc_ - 2 * kInstrSize) == (kPushRegPattern | dst.code() * B12)) { 1184
1100 pc_ -= 2 * kInstrSize; 1185 if ((IsStrRegFpOffset(str_instr) &&
1101 if (FLAG_print_push_pop_elimination) { 1186 IsLdrRegFpOffset(ldr_instr)) ||
1102 PrintF("%x push/pop (same reg) eliminated\n", pc_offset()); 1187 (IsStrRegFpNegOffset(str_instr) &&
1188 IsLdrRegFpNegOffset(ldr_instr))) {
1189 if ((ldr_instr & kLdrStrInstrArgumentMask) ==
1190 (str_instr & kLdrStrInstrArgumentMask)) {
1191 // Pattern: Ldr/str same fp+offset, same register.
1192 //
1193 // The following:
1194 // str rx, [fp, #-12]
1195 // ldr rx, [fp, #-12]
1196 //
1197 // Becomes:
1198 // str rx, [fp, #-12]
1199
1200 pc_ -= 1 * kInstrSize;
1201 if (FLAG_print_peephole_optimization) {
1202 PrintF("%x str/ldr (fp + same offset), same reg\n", pc_offset());
1203 }
1204 } else if ((ldr_instr & kLdrStrOffsetMask) ==
1205 (str_instr & kLdrStrOffsetMask)) {
1206 // Pattern: Ldr/str same fp+offset, different register.
1207 //
1208 // The following:
1209 // str rx, [fp, #-12]
1210 // ldr ry, [fp, #-12]
1211 //
1212 // Becomes:
1213 // str rx, [fp, #-12]
1214 // mov ry, rx
1215
1216 Register reg_stored, reg_loaded;
1217 reg_stored = GetRd(str_instr);
1218 reg_loaded = GetRd(ldr_instr);
1219 pc_ -= 1 * kInstrSize;
1220 // Insert a mov instruction, which is better than ldr.
1221 mov(reg_loaded, reg_stored);
1222 if (FLAG_print_peephole_optimization) {
1223 PrintF("%x str/ldr (fp + same offset), diff reg \n", pc_offset());
1224 }
1225 }
1226 }
1227 }
1228
1229 pattern_size = 3 * kInstrSize;
1230 if (FLAG_push_pop_elimination &&
1231 last_bound_pos_ <= (pc_offset() - pattern_size) &&
1232 reloc_info_writer.last_pc() <= (pc_ - pattern_size)) {
1233 Instr mem_write_instr = instr_at(pc_ - 3 * kInstrSize);
1234 Instr ldr_instr = instr_at(pc_ - 2 * kInstrSize);
1235 Instr mem_read_instr = instr_at(pc_ - 1 * kInstrSize);
1236 if (IsPush(mem_write_instr) &&
1237 IsPop(mem_read_instr)) {
1238 if ((IsLdrRegFpOffset(ldr_instr) ||
1239 IsLdrRegFpNegOffset(ldr_instr))) {
1240 if ((mem_write_instr & kRdMask) ==
1241 (mem_read_instr & kRdMask)) {
1242 // Pattern: push & pop from/to same register,
1243 // with a fp+offset ldr in between
1244 //
1245 // The following:
1246 // str rx, [sp, #-4]!
1247 // ldr rz, [fp, #-24]
1248 // ldr rx, [sp], #+4
1249 //
1250 // Becomes:
1251 // if(rx == rz)
1252 // delete all
1253 // else
1254 // ldr rz, [fp, #-24]
1255
1256 if ((mem_write_instr & kRdMask) == (ldr_instr & kRdMask)) {
1257 pc_ -= 3 * kInstrSize;
1258 } else {
1259 pc_ -= 3 * kInstrSize;
1260 // Reinsert back the ldr rz.
1261 emit(ldr_instr);
1262 }
1263 if (FLAG_print_push_pop_elimination) {
1264 PrintF("%x push/pop -dead ldr fp+offset in middle\n", pc_offset());
1265 }
1266 } else {
1267 // Pattern: push & pop from/to different registers
1268 // with a fp+offset ldr in between
1269 //
1270 // The following:
1271 // str rx, [sp, #-4]!
1272 // ldr rz, [fp, #-24]
1273 // ldr ry, [sp], #+4
1274 //
1275 // Becomes:
1276 // if(ry == rz)
1277 // mov ry, rx;
1278 // else if(rx != rz)
1279 // ldr rz, [fp, #-24]
1280 // mov ry, rx
1281 // else if((ry != rz) || (rx == rz)) becomes:
1282 // mov ry, rx
1283 // ldr rz, [fp, #-24]
1284
1285 Register reg_pushed, reg_popped;
1286 if ((mem_read_instr & kRdMask) == (ldr_instr & kRdMask)) {
1287 reg_pushed = GetRd(mem_write_instr);
1288 reg_popped = GetRd(mem_read_instr);
1289 pc_ -= 3 * kInstrSize;
1290 mov(reg_popped, reg_pushed);
1291 } else if ((mem_write_instr & kRdMask)
1292 != (ldr_instr & kRdMask)) {
1293 reg_pushed = GetRd(mem_write_instr);
1294 reg_popped = GetRd(mem_read_instr);
1295 pc_ -= 3 * kInstrSize;
1296 emit(ldr_instr);
1297 mov(reg_popped, reg_pushed);
1298 } else if (((mem_read_instr & kRdMask)
1299 != (ldr_instr & kRdMask)) ||
1300 ((mem_write_instr & kRdMask)
1301 == (ldr_instr & kRdMask)) ) {
1302 reg_pushed = GetRd(mem_write_instr);
1303 reg_popped = GetRd(mem_read_instr);
1304 pc_ -= 3 * kInstrSize;
1305 mov(reg_popped, reg_pushed);
1306 emit(ldr_instr);
1307 }
1308 if (FLAG_print_push_pop_elimination) {
1309 PrintF("%x push/pop (ldr fp+off in middle)\n", pc_offset());
1310 }
1311 }
1312 }
1103 } 1313 }
1104 } 1314 }
1105 } 1315 }
1106 1316
1107 1317
1108 void Assembler::str(Register src, const MemOperand& dst, Condition cond) { 1318 void Assembler::str(Register src, const MemOperand& dst, Condition cond) {
1109 addrmod2(cond | B26, src, dst); 1319 addrmod2(cond | B26, src, dst);
1110 1320
1111 // Eliminate pattern: pop(), push(r) 1321 // Eliminate pattern: pop(), push(r)
1112 // add sp, sp, #4 LeaveCC, al; str r, [sp, #-4], al 1322 // add sp, sp, #4 LeaveCC, al; str r, [sp, #-4], al
(...skipping 942 matching lines...) Expand 10 before | Expand all | Expand 10 after
2055 bind(&after_pool); 2265 bind(&after_pool);
2056 } 2266 }
2057 2267
2058 // Since a constant pool was just emitted, move the check offset forward by 2268 // Since a constant pool was just emitted, move the check offset forward by
2059 // the standard interval. 2269 // the standard interval.
2060 next_buffer_check_ = pc_offset() + kCheckConstInterval; 2270 next_buffer_check_ = pc_offset() + kCheckConstInterval;
2061 } 2271 }
2062 2272
2063 2273
2064 } } // namespace v8::internal 2274 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/arm/assembler-arm.h ('k') | src/flag-definitions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698