Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 81 | 81 |
| 82 void InstARM32Pred::dumpOpcodePred(Ostream &Str, const char *Opcode, | 82 void InstARM32Pred::dumpOpcodePred(Ostream &Str, const char *Opcode, |
| 83 Type Ty) const { | 83 Type Ty) const { |
| 84 Str << Opcode << getPredicate() << "." << Ty; | 84 Str << Opcode << getPredicate() << "." << Ty; |
| 85 } | 85 } |
| 86 | 86 |
| 87 CondARM32::Cond InstARM32::getOppositeCondition(CondARM32::Cond Cond) { | 87 CondARM32::Cond InstARM32::getOppositeCondition(CondARM32::Cond Cond) { |
| 88 return InstARM32CondAttributes[Cond].Opposite; | 88 return InstARM32CondAttributes[Cond].Opposite; |
| 89 } | 89 } |
| 90 | 90 |
| 91 template <> | |
| 92 void InstARM32::startNextAsmInst<InstARM32::TextualOutput>( | |
| 93 const Cfg *Func) const { | |
| 94 startNextInst(Func); | |
| 95 Func->getContext()->getStrEmit() << "\n"; | |
| 96 } | |
| 97 | |
| 98 template <> | |
| 99 void InstARM32::startNextAsmInst<InstARM32::BinaryOutput>( | |
|
John
2016/01/06 16:10:21
The fact that this does nothing tells me this meth
Karl
2016/01/06 23:21:58
Removed.
| |
| 100 const Cfg *Func) const { | |
| 101 (void)Func; | |
| 102 } | |
| 103 | |
| 91 void InstARM32::startNextInst(const Cfg *Func) const { | 104 void InstARM32::startNextInst(const Cfg *Func) const { |
| 92 if (auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>()) | 105 if (auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>()) |
| 93 Asm->incEmitTextSize(InstSize); | 106 Asm->incEmitTextSize(InstSize); |
| 94 } | 107 } |
| 95 | 108 |
| 96 void InstARM32::emitUsingTextFixup(const Cfg *Func) const { | 109 void InstARM32::emitUsingTextFixup(const Cfg *Func) const { |
| 97 if (!BuildDefs::dump()) | 110 if (!BuildDefs::dump()) |
| 98 return; | 111 return; |
| 99 GlobalContext *Ctx = Func->getContext(); | 112 GlobalContext *Ctx = Func->getContext(); |
| 100 if (Ctx->getFlags().getDisableHybridAssembly()) { | 113 if (Ctx->getFlags().getDisableHybridAssembly()) { |
| (...skipping 1216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1317 | 1330 |
| 1318 bool isAssignedConsecutiveRegisters(const Variable *Before, | 1331 bool isAssignedConsecutiveRegisters(const Variable *Before, |
| 1319 const Variable *After) { | 1332 const Variable *After) { |
| 1320 assert(Before->hasReg()); | 1333 assert(Before->hasReg()); |
| 1321 assert(After->hasReg()); | 1334 assert(After->hasReg()); |
| 1322 return Before->getRegNum() + 1 == After->getRegNum(); | 1335 return Before->getRegNum() + 1 == After->getRegNum(); |
| 1323 } | 1336 } |
| 1324 | 1337 |
| 1325 } // end of anonymous namespace | 1338 } // end of anonymous namespace |
| 1326 | 1339 |
| 1327 void InstARM32Pop::emit(const Cfg *Func) const { | 1340 void InstARM32Pop::emitPop(const Cfg *Func) const { |
| 1328 if (!BuildDefs::dump()) | 1341 if (!BuildDefs::dump()) |
| 1329 return; | 1342 return; |
| 1330 | 1343 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1344 Str << "\t" | |
| 1345 << "pop" | |
| 1346 << "\t{"; | |
| 1347 Dests[0]->emit(Func); | |
| 1331 const SizeT DestSize = Dests.size(); | 1348 const SizeT DestSize = Dests.size(); |
| 1332 if (DestSize == 0) { | 1349 for (SizeT i = 1; i < DestSize; ++i) { |
| 1333 assert(false && "Empty pop list"); | |
| 1334 return; | |
| 1335 } | |
| 1336 | |
| 1337 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 1338 | |
| 1339 Variable *Reg = Dests[0]; | |
| 1340 if (isScalarIntegerType(Reg->getType())) { | |
| 1341 // GPR push. | |
| 1342 Str << "\t" | |
| 1343 "pop" | |
| 1344 "\t{"; | |
| 1345 Reg->emit(Func); | |
| 1346 for (SizeT i = 1; i < DestSize; ++i) { | |
| 1347 Str << ", "; | |
| 1348 Reg = Dests[i]; | |
| 1349 Reg->emit(Func); | |
| 1350 } | |
| 1351 Str << "}"; | |
| 1352 return; | |
| 1353 } | |
| 1354 | |
| 1355 // VFP "s" reg push. | |
| 1356 SizeT End = DestSize - 1; | |
| 1357 SizeT Start = DestSize - 1; | |
| 1358 Reg = Dests[DestSize - 1]; | |
| 1359 Str << "\t" | |
| 1360 "vpop" | |
| 1361 "\t{"; | |
| 1362 for (SizeT i = 2; i <= DestSize; ++i) { | |
| 1363 Variable *PreviousReg = Dests[DestSize - i]; | |
| 1364 if (!isAssignedConsecutiveRegisters(PreviousReg, Reg)) { | |
| 1365 Dests[Start]->emit(Func); | |
| 1366 for (SizeT j = Start + 1; j <= End; ++j) { | |
| 1367 Str << ", "; | |
| 1368 Dests[j]->emit(Func); | |
| 1369 } | |
| 1370 startNextInst(Func); | |
| 1371 Str << "}\n\t" | |
| 1372 "vpop" | |
| 1373 "\t{"; | |
| 1374 End = DestSize - i; | |
| 1375 } | |
| 1376 Reg = PreviousReg; | |
| 1377 Start = DestSize - i; | |
| 1378 } | |
| 1379 Dests[Start]->emit(Func); | |
| 1380 for (SizeT j = Start + 1; j <= End; ++j) { | |
| 1381 Str << ", "; | 1350 Str << ", "; |
| 1382 Dests[j]->emit(Func); | 1351 Dests[i]->emit(Func); |
| 1383 } | 1352 } |
| 1384 Str << "}"; | 1353 Str << "}"; |
| 1385 } | 1354 } |
| 1386 | 1355 |
| 1387 void InstARM32Pop::emitIAS(const Cfg *Func) const { | 1356 template <> |
| 1357 void InstARM32Pop::emitPop<InstARM32::TextualOutput>( | |
| 1358 const Cfg *Func, const Variable *Reg) const { | |
| 1359 (void)Reg; | |
| 1360 this->emitPop(Func); | |
| 1361 } | |
| 1362 | |
| 1363 template <> | |
| 1364 void InstARM32Pop::emitPop<InstARM32::BinaryOutput>(const Cfg *Func, | |
| 1365 const Variable *Reg) const { | |
| 1366 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); | |
| 1367 Asm->pop(Reg, CondARM32::AL); | |
| 1368 } | |
| 1369 | |
| 1370 template <> | |
| 1371 void InstARM32Pop::emitPopList<InstARM32::TextualOutput>( | |
| 1372 const Cfg *Func, ARM32::IValueT Registers) const { | |
| 1373 (void)Registers; | |
| 1374 emitPop(Func); | |
| 1375 } | |
| 1376 | |
| 1377 template <> | |
| 1378 void InstARM32Pop::emitPopList<InstARM32::BinaryOutput>( | |
| 1379 const Cfg *Func, ARM32::IValueT Registers) const { | |
| 1380 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); | |
| 1381 Asm->popList(Registers, CondARM32::AL); | |
| 1382 } | |
| 1383 | |
| 1384 template <> | |
| 1385 void InstARM32Pop::emitVpop<InstARM32::TextualOutput>(const Cfg *Func, | |
| 1386 const Variable *BaseReg, | |
| 1387 SizeT RegCount) const { | |
| 1388 if (!BuildDefs::dump()) | |
| 1389 return; | |
| 1390 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 1391 Str << "\t" | |
| 1392 << "vpop" | |
| 1393 << "\t{"; | |
| 1394 bool IsFirst = true; | |
| 1395 IValueT Base = AssemblerARM32::getEncodedSRegNum(BaseReg); | |
|
John
2016/01/06 16:10:21
Why using this method? RegARM32::getEncodedSReg()
Karl
2016/01/06 23:21:58
Fixed.
| |
| 1396 for (SizeT i = 0; i < RegCount; ++i) { | |
| 1397 if (IsFirst) | |
| 1398 IsFirst = false; | |
| 1399 else | |
| 1400 Str << ", "; | |
| 1401 Str << RegARM32::getSRegName(Base + i); | |
| 1402 } | |
| 1403 Str << "}"; | |
| 1404 } | |
| 1405 | |
| 1406 template <> | |
| 1407 void InstARM32Pop::emitVpop<InstARM32::BinaryOutput>(const Cfg *Func, | |
| 1408 const Variable *BaseReg, | |
| 1409 SizeT RegCount) const { | |
| 1410 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); | |
| 1411 Asm->vpop(BaseReg, RegCount, CondARM32::AL); | |
| 1412 } | |
| 1413 | |
| 1414 template <InstARM32::OutputForm Form> | |
| 1415 void InstARM32Pop::assemble(const Cfg *Func) const { | |
| 1416 if (!BuildDefs::dump() && Form == TextualOutput) | |
| 1417 return; | |
| 1388 // Pop can't be emitted if there are no registers to load. This should never | 1418 // Pop can't be emitted if there are no registers to load. This should never |
| 1389 // happen, but if it does, we don't need to bring Subzero down -- we just skip | 1419 // happen, but if it does, we don't need to bring Subzero down -- we just skip |
| 1390 // emitting the pop instruction (and maybe emit a nop?) The assert() is here | 1420 // emitting the pop instruction (and maybe emit a nop?) The assert() is here |
| 1391 // so that we can detect this error during development. | 1421 // so that we can detect this error during development. |
| 1392 const SizeT DestSize = Dests.size(); | 1422 const SizeT DestSize = Dests.size(); |
| 1393 if (DestSize == 0) { | 1423 if (DestSize == 0) { |
| 1394 assert(false && "Empty pop list"); | 1424 assert(false && "Empty pop list"); |
| 1395 return; | 1425 return; |
| 1396 } | 1426 } |
| 1397 | 1427 |
| 1398 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); | |
| 1399 const auto *Reg = llvm::cast<Variable>(Dests[0]); | 1428 const auto *Reg = llvm::cast<Variable>(Dests[0]); |
| 1400 if (isScalarIntegerType(Reg->getType())) { | 1429 if (isScalarIntegerType(Reg->getType())) { |
| 1401 // Pop GPR registers. | 1430 // Pop GPR registers. |
| 1402 SizeT IntegerCount = 0; | 1431 SizeT IntegerCount = 0; |
| 1403 ARM32::IValueT GPRegisters = 0; | 1432 ARM32::IValueT GPRegisters = 0; |
| 1404 const Variable *LastDest = nullptr; | 1433 const Variable *LastDest = nullptr; |
| 1405 for (const Variable *Var : Dests) { | 1434 for (const Variable *Var : Dests) { |
| 1406 assert(Var->hasReg() && "pop only applies to registers"); | 1435 assert(Var->hasReg() && "pop only applies to registers"); |
| 1407 int32_t Reg = RegARM32::getEncodedGPR(Var->getRegNum()); | 1436 int32_t Reg = RegARM32::getEncodedGPR(Var->getRegNum()); |
| 1408 LastDest = Var; | 1437 LastDest = Var; |
| 1409 GPRegisters |= (1 << Reg); | 1438 GPRegisters |= (1 << Reg); |
| 1410 ++IntegerCount; | 1439 ++IntegerCount; |
| 1411 } | 1440 } |
| 1412 switch (IntegerCount) { | 1441 switch (IntegerCount) { |
| 1413 case 0: | 1442 case 0: |
| 1414 return; | 1443 return; |
| 1415 case 1: | 1444 case 1: |
| 1416 // Note: Can only apply pop register if single register is not sp. | 1445 // Note: Can only apply pop register if single register is not sp. |
| 1417 assert((RegARM32::Encoded_Reg_sp != LastDest->getRegNum()) && | 1446 assert((RegARM32::Encoded_Reg_sp != LastDest->getRegNum()) && |
| 1418 "Effects of pop register SP is undefined!"); | 1447 "Effects of pop register SP is undefined!"); |
| 1419 Asm->pop(LastDest, CondARM32::AL); | 1448 emitPop<Form>(Func, LastDest); |
| 1420 break; | 1449 break; |
| 1421 default: | 1450 default: |
| 1422 Asm->popList(GPRegisters, CondARM32::AL); | 1451 emitPopList<Form>(Func, GPRegisters); |
| 1423 break; | 1452 break; |
| 1424 } | 1453 } |
| 1425 } else { | 1454 } else { |
| 1426 // Pop vector/floating point registers. | 1455 // Pop vector/floating point registers. |
| 1427 const Variable *BaseReg = nullptr; | 1456 const Variable *BaseReg = nullptr; |
| 1428 SizeT RegCount = 0; | 1457 SizeT RegCount = 0; |
| 1429 for (const Variable *NextReg : Dests) { | 1458 for (const Variable *NextReg : Dests) { |
| 1430 if (BaseReg == nullptr) { | 1459 if (BaseReg == nullptr) { |
| 1431 BaseReg = NextReg; | 1460 BaseReg = NextReg; |
| 1432 RegCount = 1; | 1461 RegCount = 1; |
| 1433 } else if (RegCount < VpushVpopMaxConsecRegs && | 1462 } else if (RegCount < VpushVpopMaxConsecRegs && |
| 1434 isAssignedConsecutiveRegisters(Reg, NextReg)) { | 1463 isAssignedConsecutiveRegisters(Reg, NextReg)) { |
| 1435 ++RegCount; | 1464 ++RegCount; |
| 1436 } else { | 1465 } else { |
| 1437 Asm->vpop(BaseReg, RegCount, CondARM32::AL); | 1466 emitVpop<Form>(Func, BaseReg, RegCount); |
| 1467 this->startNextAsmInst<Form>(Func); | |
| 1438 BaseReg = NextReg; | 1468 BaseReg = NextReg; |
| 1439 RegCount = 1; | 1469 RegCount = 1; |
| 1440 } | 1470 } |
| 1441 Reg = NextReg; | 1471 Reg = NextReg; |
| 1442 } | 1472 } |
| 1443 if (RegCount) | 1473 if (RegCount) { |
| 1444 Asm->vpop(BaseReg, RegCount, CondARM32::AL); | 1474 emitVpop<Form>(Func, BaseReg, RegCount); |
| 1475 } | |
| 1445 } | 1476 } |
| 1446 if (Asm->needsTextFixup()) | 1477 assert(!Func->getAssembler<ARM32::AssemblerARM32>()->needsTextFixup()); |
| 1447 emitUsingTextFixup(Func); | |
| 1448 } | 1478 } |
| 1449 | 1479 |
| 1450 void InstARM32Pop::dump(const Cfg *Func) const { | 1480 void InstARM32Pop::dump(const Cfg *Func) const { |
| 1451 if (!BuildDefs::dump()) | 1481 if (!BuildDefs::dump()) |
| 1452 return; | 1482 return; |
| 1453 Ostream &Str = Func->getContext()->getStrDump(); | 1483 Ostream &Str = Func->getContext()->getStrDump(); |
| 1454 Str << "pop" | 1484 Str << "pop" |
| 1455 << " "; | 1485 << " "; |
| 1456 for (SizeT I = 0; I < Dests.size(); ++I) { | 1486 for (SizeT I = 0; I < Dests.size(); ++I) { |
| 1457 if (I > 0) | 1487 if (I > 0) |
| 1458 Str << ", "; | 1488 Str << ", "; |
| 1459 Dests[I]->dump(Func); | 1489 Dests[I]->dump(Func); |
| 1460 } | 1490 } |
| 1461 } | 1491 } |
| 1462 | 1492 |
| 1463 void InstARM32Push::emit(const Cfg *Func) const { | 1493 void InstARM32Pop::emit(const Cfg *Func) const { |
| 1494 assemble<TextualOutput>(Func); | |
|
John
2016/01/06 16:10:21
I would rather have the
if (!BuildDefs::dump()) {
Karl
2016/01/06 23:21:58
Done.
| |
| 1495 } | |
| 1496 | |
| 1497 void InstARM32Pop::emitIAS(const Cfg *Func) const { | |
| 1498 assemble<BinaryOutput>(Func); | |
| 1499 } | |
| 1500 | |
| 1501 void InstARM32Push::emitPush(const Cfg *Func) const { | |
| 1464 if (!BuildDefs::dump()) | 1502 if (!BuildDefs::dump()) |
| 1465 return; | 1503 return; |
| 1466 | 1504 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1467 // Push can't be emitted if there are no registers to save. This should never | 1505 Str << "\t" |
| 1468 // happen, but if it does, we don't need to bring Subzero down -- we just skip | 1506 << "push" |
| 1469 // emitting the push instruction (and maybe emit a nop?) The assert() is here | 1507 << "\t{"; |
| 1470 // so that we can detect this error during development. | 1508 getSrc(0)->emit(Func); |
| 1471 const SizeT SrcSize = getSrcSize(); | 1509 const SizeT SrcSize = getSrcSize(); |
| 1472 if (SrcSize == 0) { | |
| 1473 assert(false && "Empty push list"); | |
| 1474 return; | |
| 1475 } | |
| 1476 | |
| 1477 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 1478 | |
| 1479 const auto *Reg = llvm::cast<Variable>(getSrc(0)); | |
| 1480 if (isScalarIntegerType(Reg->getType())) { | |
| 1481 // GPR push. | |
| 1482 Str << "\t" | |
| 1483 "push" | |
| 1484 "\t{"; | |
| 1485 Reg->emit(Func); | |
| 1486 for (SizeT i = 1; i < SrcSize; ++i) { | |
| 1487 Str << ", "; | |
| 1488 getSrc(i)->emit(Func); | |
| 1489 } | |
| 1490 Str << "}"; | |
| 1491 return; | |
| 1492 } | |
| 1493 | |
| 1494 // VFP "s" reg push. | |
| 1495 Str << "\t" | |
| 1496 "vpush" | |
| 1497 "\t{"; | |
| 1498 Reg->emit(Func); | |
| 1499 SizeT RegCount = 1; | |
| 1500 for (SizeT i = 1; i < SrcSize; ++i) { | 1510 for (SizeT i = 1; i < SrcSize; ++i) { |
| 1501 const auto *NextReg = llvm::cast<Variable>(getSrc(i)); | 1511 Str << ", "; |
| 1502 if (RegCount < VpushVpopMaxConsecRegs && | 1512 getSrc(i)->emit(Func); |
| 1503 isAssignedConsecutiveRegisters(Reg, NextReg)) { | |
| 1504 ++RegCount; | |
| 1505 Str << ", "; | |
| 1506 } else { | |
| 1507 startNextInst(Func); | |
| 1508 RegCount = 1; | |
| 1509 Str << "}\n\t" | |
| 1510 "vpush" | |
| 1511 "\t{"; | |
| 1512 } | |
| 1513 Reg = NextReg; | |
| 1514 Reg->emit(Func); | |
| 1515 } | 1513 } |
| 1516 Str << "}"; | 1514 Str << "}"; |
| 1517 } | 1515 } |
| 1518 | 1516 |
| 1519 void InstARM32Push::emitIAS(const Cfg *Func) const { | 1517 template <> |
| 1518 void InstARM32Push::emitPush<InstARM32::TextualOutput>( | |
| 1519 const Cfg *Func, const Variable *Reg) const { | |
| 1520 (void)Reg; | |
| 1521 this->emitPush(Func); | |
|
John
2016/01/06 16:10:21
do you need the
this->
?
Karl
2016/01/06 23:21:58
Removed.
| |
| 1522 } | |
| 1523 | |
| 1524 template <> | |
| 1525 void InstARM32Push::emitPush<InstARM32::BinaryOutput>( | |
| 1526 const Cfg *Func, const Variable *Reg) const { | |
| 1527 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); | |
| 1528 Asm->push(Reg, CondARM32::AL); | |
| 1529 } | |
| 1530 | |
| 1531 template <> | |
| 1532 void InstARM32Push::emitPushList<InstARM32::TextualOutput>( | |
| 1533 const Cfg *Func, ARM32::IValueT Registers) const { | |
| 1534 (void)Registers; | |
| 1535 emitPush(Func); | |
| 1536 } | |
| 1537 | |
| 1538 template <> | |
| 1539 void InstARM32Push::emitPushList<InstARM32::BinaryOutput>( | |
| 1540 const Cfg *Func, ARM32::IValueT Registers) const { | |
| 1541 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); | |
| 1542 Asm->pushList(Registers, CondARM32::AL); | |
| 1543 } | |
| 1544 | |
| 1545 template <> | |
| 1546 void InstARM32Push::emitVPush<InstARM32::TextualOutput>(const Cfg *Func, | |
| 1547 const Variable *BaseReg, | |
| 1548 SizeT RegCount) const { | |
| 1549 if (!BuildDefs::dump()) | |
| 1550 return; | |
| 1551 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 1552 Str << "\t" | |
| 1553 << "vpush" | |
| 1554 << "\t{"; | |
| 1555 bool IsFirst = true; | |
| 1556 IValueT Base = AssemblerARM32::getEncodedSRegNum(BaseReg); | |
|
John
2016/01/06 16:10:21
ditto.
Karl
2016/01/06 23:21:58
Done.
| |
| 1557 for (SizeT i = 0; i < RegCount; ++i) { | |
| 1558 if (IsFirst) | |
| 1559 IsFirst = false; | |
| 1560 else | |
| 1561 Str << ", "; | |
| 1562 Str << RegARM32::getSRegName(Base + i); | |
| 1563 } | |
| 1564 Str << "}"; | |
| 1565 } | |
| 1566 | |
| 1567 template <> | |
| 1568 void InstARM32Push::emitVPush<InstARM32::BinaryOutput>(const Cfg *Func, | |
| 1569 const Variable *BaseReg, | |
| 1570 SizeT RegCount) const { | |
| 1571 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); | |
| 1572 Asm->vpush(BaseReg, RegCount, CondARM32::AL); | |
| 1573 } | |
| 1574 | |
| 1575 template <InstARM32::OutputForm Form> | |
| 1576 void InstARM32Push::assemble(const Cfg *Func) const { | |
|
John
2016/01/06 16:10:21
assemble is not really meaningful for textual outp
Karl
2016/01/06 23:21:58
renamed to emitUsingForm().
| |
| 1577 if (!BuildDefs::dump() && Form == TextualOutput) | |
| 1578 return; | |
| 1520 // Push can't be emitted if there are no registers to save. This should never | 1579 // Push can't be emitted if there are no registers to save. This should never |
| 1521 // happen, but if it does, we don't need to bring Subzero down -- we just skip | 1580 // happen, but if it does, we don't need to bring Subzero down -- we just skip |
| 1522 // emitting the push instruction (and maybe emit a nop?) The assert() is here | 1581 // emitting the push instruction (and maybe emit a nop?) The assert() is here |
| 1523 // so that we can detect this error during development. | 1582 // so that we can detect this error during development. |
| 1524 const SizeT SrcSize = getSrcSize(); | 1583 const SizeT SrcSize = getSrcSize(); |
| 1525 if (SrcSize == 0) { | 1584 if (SrcSize == 0) { |
| 1526 assert(false && "Empty push list"); | 1585 assert(false && "Empty push list"); |
| 1527 return; | 1586 return; |
| 1528 } | 1587 } |
| 1529 | 1588 |
| 1530 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); | |
| 1531 const auto *Reg = llvm::cast<Variable>(getSrc(0)); | 1589 const auto *Reg = llvm::cast<Variable>(getSrc(0)); |
| 1532 if (isScalarIntegerType(Reg->getType())) { | 1590 if (isScalarIntegerType(Reg->getType())) { |
| 1533 // Push GPR registers. | 1591 // Push GPR registers. |
| 1534 SizeT IntegerCount = 0; | 1592 SizeT IntegerCount = 0; |
| 1535 ARM32::IValueT GPRegisters = 0; | 1593 ARM32::IValueT GPRegisters = 0; |
| 1536 const Variable *LastSrc = nullptr; | 1594 const Variable *LastSrc = nullptr; |
| 1537 for (SizeT Index = 0; Index < getSrcSize(); ++Index) { | 1595 for (SizeT Index = 0; Index < getSrcSize(); ++Index) { |
| 1538 const auto *Var = llvm::cast<Variable>(getSrc(Index)); | 1596 const auto *Var = llvm::cast<Variable>(getSrc(Index)); |
| 1539 int32_t Reg = RegARM32::getEncodedGPR(Var->getRegNum()); | 1597 int32_t Reg = RegARM32::getEncodedGPR(Var->getRegNum()); |
| 1540 assert(Reg != RegARM32::Encoded_Not_GPR); | 1598 assert(Reg != RegARM32::Encoded_Not_GPR); |
| 1541 LastSrc = Var; | 1599 LastSrc = Var; |
| 1542 GPRegisters |= (1 << Reg); | 1600 GPRegisters |= (1 << Reg); |
| 1543 ++IntegerCount; | 1601 ++IntegerCount; |
| 1544 } | 1602 } |
| 1545 switch (IntegerCount) { | 1603 switch (IntegerCount) { |
| 1546 case 0: | 1604 case 0: |
| 1547 return; | 1605 return; |
|
John
2016/01/06 16:10:21
You should llvm::report_fatal_error() here. It is
Karl
2016/01/06 23:21:58
Actually, this case can't happen due to the test "
| |
| 1548 case 1: { | 1606 case 1: { |
| 1549 // Note: Can only apply push register if single register is not sp. | 1607 // Note: Can only apply push register if single register is not sp. |
| 1550 assert((RegARM32::Encoded_Reg_sp != LastSrc->getRegNum()) && | 1608 assert((RegARM32::Encoded_Reg_sp != LastSrc->getRegNum()) && |
| 1551 "Effects of push register SP is undefined!"); | 1609 "Effects of push register SP is undefined!"); |
| 1552 Asm->push(LastSrc, CondARM32::AL); | 1610 emitPush<Form>(Func, LastSrc); |
| 1553 break; | 1611 break; |
| 1554 } | 1612 } |
| 1555 default: | 1613 default: |
| 1556 Asm->pushList(GPRegisters, CondARM32::AL); | 1614 emitPushList<Form>(Func, GPRegisters); |
| 1557 break; | 1615 break; |
| 1558 } | 1616 } |
| 1559 } else { | 1617 } else { |
| 1560 // Push vector/Floating point registers. | 1618 // Push vector/Floating point registers. |
| 1561 const Variable *BaseReg = Reg; | 1619 const Variable *BaseReg = Reg; |
| 1562 SizeT RegCount = 1; | 1620 SizeT RegCount = 1; |
| 1563 for (SizeT i = 1; i < SrcSize; ++i) { | 1621 for (SizeT i = 1; i < SrcSize; ++i) { |
| 1564 const auto *NextReg = llvm::cast<Variable>(getSrc(i)); | 1622 const auto *NextReg = llvm::cast<Variable>(getSrc(i)); |
| 1565 if (RegCount < VpushVpopMaxConsecRegs && | 1623 if (RegCount < VpushVpopMaxConsecRegs && |
| 1566 isAssignedConsecutiveRegisters(Reg, NextReg)) { | 1624 isAssignedConsecutiveRegisters(Reg, NextReg)) { |
| 1567 ++RegCount; | 1625 ++RegCount; |
| 1568 } else { | 1626 } else { |
| 1569 Asm->vpush(BaseReg, RegCount, CondARM32::AL); | 1627 emitVPush<Form>(Func, BaseReg, RegCount); |
| 1628 this->startNextAsmInst<Form>(Func); | |
| 1570 BaseReg = NextReg; | 1629 BaseReg = NextReg; |
| 1571 RegCount = 1; | 1630 RegCount = 1; |
| 1572 } | 1631 } |
| 1573 Reg = NextReg; | 1632 Reg = NextReg; |
| 1574 } | 1633 } |
| 1575 Asm->vpush(BaseReg, RegCount, CondARM32::AL); | 1634 emitVPush<Form>(Func, BaseReg, RegCount); |
| 1576 } | 1635 } |
| 1577 if (Asm->needsTextFixup()) | 1636 assert(!Func->getAssembler<ARM32::AssemblerARM32>()->needsTextFixup()); |
| 1578 emitUsingTextFixup(Func); | 1637 } |
| 1638 | |
| 1639 void InstARM32Push::emit(const Cfg *Func) const { | |
| 1640 assemble<TextualOutput>(Func); | |
| 1641 } | |
| 1642 | |
| 1643 void InstARM32Push::emitIAS(const Cfg *Func) const { | |
| 1644 assemble<BinaryOutput>(Func); | |
| 1579 } | 1645 } |
| 1580 | 1646 |
| 1581 void InstARM32Push::dump(const Cfg *Func) const { | 1647 void InstARM32Push::dump(const Cfg *Func) const { |
| 1582 if (!BuildDefs::dump()) | 1648 if (!BuildDefs::dump()) |
| 1583 return; | 1649 return; |
| 1584 Ostream &Str = Func->getContext()->getStrDump(); | 1650 Ostream &Str = Func->getContext()->getStrDump(); |
| 1585 Str << "push" | 1651 Str << "push" |
| 1586 << " "; | 1652 << " "; |
| 1587 dumpSources(Func); | 1653 dumpSources(Func); |
| 1588 } | 1654 } |
| (...skipping 558 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2147 | 2213 |
| 2148 template class InstARM32FourAddrGPR<InstARM32::Mla>; | 2214 template class InstARM32FourAddrGPR<InstARM32::Mla>; |
| 2149 template class InstARM32FourAddrGPR<InstARM32::Mls>; | 2215 template class InstARM32FourAddrGPR<InstARM32::Mls>; |
| 2150 | 2216 |
| 2151 template class InstARM32CmpLike<InstARM32::Cmn>; | 2217 template class InstARM32CmpLike<InstARM32::Cmn>; |
| 2152 template class InstARM32CmpLike<InstARM32::Cmp>; | 2218 template class InstARM32CmpLike<InstARM32::Cmp>; |
| 2153 template class InstARM32CmpLike<InstARM32::Tst>; | 2219 template class InstARM32CmpLike<InstARM32::Tst>; |
| 2154 | 2220 |
| 2155 } // end of namespace ARM32 | 2221 } // end of namespace ARM32 |
| 2156 } // end of namespace Ice | 2222 } // end of namespace Ice |
| OLD | NEW |