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

Side by Side Diff: src/IceInstARM32.cpp

Issue 1535233002: Refactor PUSH/POP in ARM assemblers. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Remove "#if 0' Created 5 years 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
OLDNEW
1 //===- subzero/src/IceInstARM32.cpp - ARM32 instruction implementation ----===// 1 //===- subzero/src/IceInstARM32.cpp - ARM32 instruction implementation ----===//
2 // 2 //
3 // The Subzero Code Generator 3 // The Subzero Code Generator
4 // 4 //
5 // This file is distributed under the University of Illinois Open Source 5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details. 6 // License. See LICENSE.TXT for details.
7 // 7 //
8 //===----------------------------------------------------------------------===// 8 //===----------------------------------------------------------------------===//
9 /// 9 ///
10 /// \file 10 /// \file
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
80 80
81 void InstARM32Pred::dumpOpcodePred(Ostream &Str, const char *Opcode, 81 void InstARM32Pred::dumpOpcodePred(Ostream &Str, const char *Opcode,
82 Type Ty) const { 82 Type Ty) const {
83 Str << Opcode << getPredicate() << "." << Ty; 83 Str << Opcode << getPredicate() << "." << Ty;
84 } 84 }
85 85
86 CondARM32::Cond InstARM32::getOppositeCondition(CondARM32::Cond Cond) { 86 CondARM32::Cond InstARM32::getOppositeCondition(CondARM32::Cond Cond) {
87 return InstARM32CondAttributes[Cond].Opposite; 87 return InstARM32CondAttributes[Cond].Opposite;
88 } 88 }
89 89
90 template <>
91 void InstARM32::startNextAsmInst<TextualAssembly>(const Cfg *Func) const {
92 startNextInst(Func);
93 Func->getContext()->getStrEmit() << "\n";
94 }
95
96 template <>
97 void InstARM32::startNextAsmInst<BinaryAssembly>(const Cfg *Func) const {
98 (void)Func;
99 }
100
90 void InstARM32::startNextInst(const Cfg *Func) const { 101 void InstARM32::startNextInst(const Cfg *Func) const {
91 if (auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>()) 102 if (auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>())
92 Asm->incEmitTextSize(InstSize); 103 Asm->incEmitTextSize(InstSize);
93 } 104 }
94 105
95 void InstARM32::emitUsingTextFixup(const Cfg *Func) const { 106 void InstARM32::emitUsingTextFixup(const Cfg *Func) const {
96 if (!BuildDefs::dump()) 107 if (!BuildDefs::dump())
97 return; 108 return;
98 GlobalContext *Ctx = Func->getContext(); 109 GlobalContext *Ctx = Func->getContext();
99 if (Ctx->getFlags().getDisableHybridAssembly()) { 110 if (Ctx->getFlags().getDisableHybridAssembly()) {
(...skipping 1216 matching lines...) Expand 10 before | Expand all | Expand 10 after
1316 1327
1317 bool isAssignedConsecutiveRegisters(const Variable *Before, 1328 bool isAssignedConsecutiveRegisters(const Variable *Before,
1318 const Variable *After) { 1329 const Variable *After) {
1319 assert(Before->hasReg()); 1330 assert(Before->hasReg());
1320 assert(After->hasReg()); 1331 assert(After->hasReg());
1321 return Before->getRegNum() + 1 == After->getRegNum(); 1332 return Before->getRegNum() + 1 == After->getRegNum();
1322 } 1333 }
1323 1334
1324 } // end of anonymous namespace 1335 } // end of anonymous namespace
1325 1336
1326 void InstARM32Pop::emit(const Cfg *Func) const { 1337 template <AssemblyOutputForm Form>
1327 if (!BuildDefs::dump()) 1338 void InstARM32Pop::assemble(const Cfg *Func) const {
1339 if (Form == TextualAssembly && !BuildDefs::dump())
1328 return; 1340 return;
1329
1330 const SizeT DestSize = Dests.size();
1331 if (DestSize == 0) {
1332 assert(false && "Empty pop list");
1333 return;
1334 }
1335
1336 Ostream &Str = Func->getContext()->getStrEmit();
1337
1338 Variable *Reg = Dests[0];
1339 if (isScalarIntegerType(Reg->getType())) {
1340 // GPR push.
1341 Str << "\t"
1342 "pop"
1343 "\t{";
1344 Reg->emit(Func);
1345 for (SizeT i = 1; i < DestSize; ++i) {
1346 Str << ", ";
1347 Reg = Dests[i];
1348 Reg->emit(Func);
1349 }
1350 Str << "}";
1351 return;
1352 }
1353
1354 // VFP "s" reg push.
1355 SizeT End = DestSize - 1;
1356 SizeT Start = DestSize - 1;
1357 Reg = Dests[DestSize - 1];
1358 Str << "\t"
1359 "vpop"
1360 "\t{";
1361 for (SizeT i = 2; i <= DestSize; ++i) {
1362 Variable *PreviousReg = Dests[DestSize - i];
1363 if (!isAssignedConsecutiveRegisters(PreviousReg, Reg)) {
1364 Dests[Start]->emit(Func);
1365 for (SizeT j = Start + 1; j <= End; ++j) {
1366 Str << ", ";
1367 Dests[j]->emit(Func);
1368 }
1369 startNextInst(Func);
1370 Str << "}\n\t"
1371 "vpop"
1372 "\t{";
1373 End = DestSize - i;
1374 }
1375 Reg = PreviousReg;
1376 Start = DestSize - i;
1377 }
1378 Dests[Start]->emit(Func);
1379 for (SizeT j = Start + 1; j <= End; ++j) {
1380 Str << ", ";
1381 Dests[j]->emit(Func);
1382 }
1383 Str << "}";
1384 }
1385
1386 void InstARM32Pop::emitIAS(const Cfg *Func) const {
1387 // Pop can't be emitted if there are no registers to load. This should never 1341 // Pop can't be emitted if there are no registers to load. This should never
1388 // happen, but if it does, we don't need to bring Subzero down -- we just skip 1342 // happen, but if it does, we don't need to bring Subzero down -- we just skip
1389 // emitting the pop instruction (and maybe emit a nop?) The assert() is here 1343 // emitting the pop instruction (and maybe emit a nop?) The assert() is here
1390 // so that we can detect this error during development. 1344 // so that we can detect this error during development.
1391 const SizeT DestSize = Dests.size(); 1345 const SizeT DestSize = Dests.size();
1392 if (DestSize == 0) { 1346 if (DestSize == 0) {
1393 assert(false && "Empty pop list"); 1347 assert(false && "Empty pop list");
1394 return; 1348 return;
1395 } 1349 }
1396
1397 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); 1350 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1398 const auto *Reg = llvm::cast<Variable>(Dests[0]); 1351 const auto *Reg = llvm::cast<Variable>(Dests[0]);
1399 if (isScalarIntegerType(Reg->getType())) { 1352 if (isScalarIntegerType(Reg->getType())) {
1400 // Pop GPR registers. 1353 // Pop GPR registers.
1401 SizeT IntegerCount = 0; 1354 SizeT IntegerCount = 0;
1402 ARM32::IValueT GPRegisters = 0; 1355 ARM32::IValueT GPRegisters = 0;
1403 const Variable *LastDest = nullptr; 1356 const Variable *LastDest = nullptr;
1404 for (const Variable *Var : Dests) { 1357 for (const Variable *Var : Dests) {
1405 assert(Var->hasReg() && "pop only applies to registers"); 1358 assert(Var->hasReg() && "pop only applies to registers");
1406 int32_t Reg = RegARM32::getEncodedGPR(Var->getRegNum()); 1359 int32_t Reg = RegARM32::getEncodedGPR(Var->getRegNum());
1407 LastDest = Var; 1360 LastDest = Var;
1408 GPRegisters |= (1 << Reg); 1361 GPRegisters |= (1 << Reg);
1409 ++IntegerCount; 1362 ++IntegerCount;
1410 } 1363 }
1411 switch (IntegerCount) { 1364 switch (IntegerCount) {
1412 case 0: 1365 case 0:
1413 return; 1366 return;
1414 case 1: 1367 case 1:
1415 // Note: Can only apply pop register if single register is not sp. 1368 // Note: Can only apply pop register if single register is not sp.
1416 assert((RegARM32::Encoded_Reg_sp != LastDest->getRegNum()) && 1369 assert((RegARM32::Encoded_Reg_sp != LastDest->getRegNum()) &&
1417 "Effects of pop register SP is undefined!"); 1370 "Effects of pop register SP is undefined!");
1418 Asm->pop(LastDest, CondARM32::AL); 1371 Asm->pop<Form>(Func, LastDest, CondARM32::AL);
1419 break; 1372 break;
1420 default: 1373 default:
1421 Asm->popList(GPRegisters, CondARM32::AL); 1374 Asm->popList<Form>(Func, GPRegisters, CondARM32::AL);
1422 break; 1375 break;
1423 } 1376 }
1424 } else { 1377 } else {
1425 // Pop vector/floating point registers. 1378 // Pop vector/floating point registers.
1426 const Variable *BaseReg = nullptr; 1379 const Variable *BaseReg = nullptr;
1427 SizeT RegCount = 0; 1380 SizeT RegCount = 0;
1428 for (const Variable *NextReg : Dests) { 1381 for (const Variable *NextReg : Dests) {
1429 if (BaseReg == nullptr) { 1382 if (BaseReg == nullptr) {
1430 BaseReg = NextReg; 1383 BaseReg = NextReg;
1431 RegCount = 1; 1384 RegCount = 1;
1432 } else if (RegCount < VpushVpopMaxConsecRegs && 1385 } else if (RegCount < VpushVpopMaxConsecRegs &&
1433 isAssignedConsecutiveRegisters(Reg, NextReg)) { 1386 isAssignedConsecutiveRegisters(Reg, NextReg)) {
1434 ++RegCount; 1387 ++RegCount;
1435 } else { 1388 } else {
1436 Asm->vpop(BaseReg, RegCount, CondARM32::AL); 1389 Asm->vpop<Form>(Func, BaseReg, RegCount, CondARM32::AL);
1390 this->startNextAsmInst<Form>(Func);
1437 BaseReg = NextReg; 1391 BaseReg = NextReg;
1438 RegCount = 1; 1392 RegCount = 1;
1439 } 1393 }
1440 Reg = NextReg; 1394 Reg = NextReg;
1441 } 1395 }
1442 if (RegCount) 1396 if (RegCount)
1443 Asm->vpop(BaseReg, RegCount, CondARM32::AL); 1397 Asm->vpop<Form>(Func, BaseReg, RegCount, CondARM32::AL);
1444 } 1398 }
1445 if (Asm->needsTextFixup()) 1399 if (Form == TextualAssembly && Asm->needsTextFixup())
1446 emitUsingTextFixup(Func); 1400 emitUsingTextFixup(Func);
1447 } 1401 }
1448 1402
1449 void InstARM32Pop::dump(const Cfg *Func) const { 1403 void InstARM32Pop::dump(const Cfg *Func) const {
1450 if (!BuildDefs::dump()) 1404 if (!BuildDefs::dump())
1451 return; 1405 return;
1452 Ostream &Str = Func->getContext()->getStrDump(); 1406 Ostream &Str = Func->getContext()->getStrDump();
1453 Str << "pop" 1407 Str << "pop"
1454 << " "; 1408 << " ";
1455 for (SizeT I = 0; I < Dests.size(); ++I) { 1409 for (SizeT I = 0; I < Dests.size(); ++I) {
1456 if (I > 0) 1410 if (I > 0)
1457 Str << ", "; 1411 Str << ", ";
1458 Dests[I]->dump(Func); 1412 Dests[I]->dump(Func);
1459 } 1413 }
1460 } 1414 }
1461 1415
1462 void InstARM32Push::emit(const Cfg *Func) const { 1416 template <AssemblyOutputForm Form>
1463 if (!BuildDefs::dump()) 1417 void InstARM32Push::assemble(const Cfg *Func) const {
1418 if (Form == TextualAssembly && !BuildDefs::dump())
1464 return; 1419 return;
1465
1466 // Push can't be emitted if there are no registers to save. This should never 1420 // Push can't be emitted if there are no registers to save. This should never
1467 // happen, but if it does, we don't need to bring Subzero down -- we just skip 1421 // happen, but if it does, we don't need to bring Subzero down -- we just skip
1468 // emitting the push instruction (and maybe emit a nop?) The assert() is here 1422 // emitting the push instruction (and maybe emit a nop?) The assert() is here
1469 // so that we can detect this error during development.
1470 const SizeT SrcSize = getSrcSize();
1471 if (SrcSize == 0) {
1472 assert(false && "Empty push list");
1473 return;
1474 }
1475
1476 Ostream &Str = Func->getContext()->getStrEmit();
1477
1478 const auto *Reg = llvm::cast<Variable>(getSrc(0));
1479 if (isScalarIntegerType(Reg->getType())) {
1480 // GPR push.
1481 Str << "\t"
1482 "push"
1483 "\t{";
1484 Reg->emit(Func);
1485 for (SizeT i = 1; i < SrcSize; ++i) {
1486 Str << ", ";
1487 getSrc(i)->emit(Func);
1488 }
1489 Str << "}";
1490 return;
1491 }
1492
1493 // VFP "s" reg push.
1494 Str << "\t"
1495 "vpush"
1496 "\t{";
1497 Reg->emit(Func);
1498 SizeT RegCount = 1;
1499 for (SizeT i = 1; i < SrcSize; ++i) {
1500 const auto *NextReg = llvm::cast<Variable>(getSrc(i));
1501 if (RegCount < VpushVpopMaxConsecRegs &&
1502 isAssignedConsecutiveRegisters(Reg, NextReg)) {
1503 ++RegCount;
1504 Str << ", ";
1505 } else {
1506 startNextInst(Func);
1507 RegCount = 1;
1508 Str << "}\n\t"
1509 "vpush"
1510 "\t{";
1511 }
1512 Reg = NextReg;
1513 Reg->emit(Func);
1514 }
1515 Str << "}";
1516 }
1517
1518 void InstARM32Push::emitIAS(const Cfg *Func) const {
1519 // Push can't be emitted if there are no registers to save. This should never
1520 // happen, but if it does, we don't need to bring Subzero down -- we just skip
1521 // emitting the push instruction (and maybe emit a nop?) The assert() is here
1522 // so that we can detect this error during development. 1423 // so that we can detect this error during development.
1523 const SizeT SrcSize = getSrcSize(); 1424 const SizeT SrcSize = getSrcSize();
1524 if (SrcSize == 0) { 1425 if (SrcSize == 0) {
1525 assert(false && "Empty push list"); 1426 assert(false && "Empty push list");
1526 return; 1427 return;
1527 } 1428 }
1528 1429
1529 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); 1430 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1530 const auto *Reg = llvm::cast<Variable>(getSrc(0)); 1431 const auto *Reg = llvm::cast<Variable>(getSrc(0));
1531 if (isScalarIntegerType(Reg->getType())) { 1432 if (isScalarIntegerType(Reg->getType())) {
1532 // Push GPR registers. 1433 // Push GPR registers.
1533 SizeT IntegerCount = 0; 1434 SizeT IntegerCount = 0;
1534 ARM32::IValueT GPRegisters = 0; 1435 ARM32::IValueT GPRegisters = 0;
1535 const Variable *LastSrc = nullptr; 1436 const Variable *LastSrc = nullptr;
1536 for (SizeT Index = 0; Index < getSrcSize(); ++Index) { 1437 for (SizeT Index = 0; Index < getSrcSize(); ++Index) {
1537 const auto *Var = llvm::cast<Variable>(getSrc(Index)); 1438 const auto *Var = llvm::cast<Variable>(getSrc(Index));
1538 int32_t Reg = RegARM32::getEncodedGPR(Var->getRegNum()); 1439 int32_t Reg = RegARM32::getEncodedGPR(Var->getRegNum());
1539 assert(Reg != RegARM32::Encoded_Not_GPR); 1440 assert(Reg != RegARM32::Encoded_Not_GPR);
1540 LastSrc = Var; 1441 LastSrc = Var;
1541 GPRegisters |= (1 << Reg); 1442 GPRegisters |= (1 << Reg);
1542 ++IntegerCount; 1443 ++IntegerCount;
1543 } 1444 }
1544 switch (IntegerCount) { 1445 switch (IntegerCount) {
1545 case 0: 1446 case 0:
1546 return; 1447 return;
1547 case 1: { 1448 case 1: {
1548 // Note: Can only apply push register if single register is not sp. 1449 // Note: Can only apply push register if single register is not sp.
1549 assert((RegARM32::Encoded_Reg_sp != LastSrc->getRegNum()) && 1450 assert((RegARM32::Encoded_Reg_sp != LastSrc->getRegNum()) &&
1550 "Effects of push register SP is undefined!"); 1451 "Effects of push register SP is undefined!");
1551 Asm->push(LastSrc, CondARM32::AL); 1452 Asm->push<Form>(Func, LastSrc, CondARM32::AL);
1552 break; 1453 break;
1553 } 1454 }
1554 default: 1455 default:
1555 Asm->pushList(GPRegisters, CondARM32::AL); 1456 Asm->pushList<Form>(Func, GPRegisters, CondARM32::AL);
1556 break; 1457 break;
1557 } 1458 }
1558 } else { 1459 } else {
1559 // Push vector/Floating point registers. 1460 // Push vector/Floating point registers.
1560 const Variable *BaseReg = Reg; 1461 const Variable *BaseReg = Reg;
1561 SizeT RegCount = 1; 1462 SizeT RegCount = 1;
1562 for (SizeT i = 1; i < SrcSize; ++i) { 1463 for (SizeT i = 1; i < SrcSize; ++i) {
1563 const auto *NextReg = llvm::cast<Variable>(getSrc(i)); 1464 const auto *NextReg = llvm::cast<Variable>(getSrc(i));
1564 if (RegCount < VpushVpopMaxConsecRegs && 1465 if (RegCount < VpushVpopMaxConsecRegs &&
1565 isAssignedConsecutiveRegisters(Reg, NextReg)) { 1466 isAssignedConsecutiveRegisters(Reg, NextReg)) {
1566 ++RegCount; 1467 ++RegCount;
1567 } else { 1468 } else {
1568 Asm->vpush(BaseReg, RegCount, CondARM32::AL); 1469 Asm->vpush<Form>(Func, BaseReg, RegCount, CondARM32::AL);
1569 BaseReg = NextReg; 1470 BaseReg = NextReg;
1570 RegCount = 1; 1471 RegCount = 1;
1571 } 1472 }
1572 Reg = NextReg; 1473 Reg = NextReg;
1573 } 1474 }
1574 Asm->vpush(BaseReg, RegCount, CondARM32::AL); 1475 Asm->vpush<Form>(Func, BaseReg, RegCount, CondARM32::AL);
1575 } 1476 }
1576 if (Asm->needsTextFixup()) 1477 if (Form == TextualAssembly && Asm->needsTextFixup())
1577 emitUsingTextFixup(Func); 1478 emitUsingTextFixup(Func);
1578 } 1479 }
1579 1480
1580 void InstARM32Push::dump(const Cfg *Func) const { 1481 void InstARM32Push::dump(const Cfg *Func) const {
1581 if (!BuildDefs::dump()) 1482 if (!BuildDefs::dump())
1582 return; 1483 return;
1583 Ostream &Str = Func->getContext()->getStrDump(); 1484 Ostream &Str = Func->getContext()->getStrDump();
1584 Str << "push" 1485 Str << "push"
1585 << " "; 1486 << " ";
1586 dumpSources(Func); 1487 dumpSources(Func);
(...skipping 558 matching lines...) Expand 10 before | Expand all | Expand 10 after
2145 template class InstARM32UnaryopFP<InstARM32::Vsqrt>; 2046 template class InstARM32UnaryopFP<InstARM32::Vsqrt>;
2146 2047
2147 template class InstARM32FourAddrGPR<InstARM32::Mla>; 2048 template class InstARM32FourAddrGPR<InstARM32::Mla>;
2148 template class InstARM32FourAddrGPR<InstARM32::Mls>; 2049 template class InstARM32FourAddrGPR<InstARM32::Mls>;
2149 2050
2150 template class InstARM32CmpLike<InstARM32::Cmn>; 2051 template class InstARM32CmpLike<InstARM32::Cmn>;
2151 template class InstARM32CmpLike<InstARM32::Cmp>; 2052 template class InstARM32CmpLike<InstARM32::Cmp>;
2152 template class InstARM32CmpLike<InstARM32::Tst>; 2053 template class InstARM32CmpLike<InstARM32::Tst>;
2153 2054
2154 } // end of namespace Ice 2055 } // end of namespace Ice
OLDNEW
« src/IceAssemblerARM32.h ('K') | « src/IceInstARM32.h ('k') | src/IceRegistersARM32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698