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

Side by Side Diff: src/IceTargetLoweringARM32.cpp

Issue 1477873002: Subzero. ARM32. Folding rematerializable offsets in address operands. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Reverts lit test change 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/IceTargetLoweringARM32.cpp - ARM32 lowering ------------===// 1 //===- subzero/src/IceTargetLoweringARM32.cpp - ARM32 lowering ------------===//
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 663 matching lines...) Expand 10 before | Expand all | Expand 10 after
674 } 674 }
675 675
676 ForbidTemporaryWithoutReg _(this); 676 ForbidTemporaryWithoutReg _(this);
677 677
678 // Stack frame mapping. 678 // Stack frame mapping.
679 Func->genFrame(); 679 Func->genFrame();
680 if (Func->hasError()) 680 if (Func->hasError())
681 return; 681 return;
682 Func->dump("After stack frame mapping"); 682 Func->dump("After stack frame mapping");
683 683
684 legalizeStackSlots(); 684 postLowerLegalization();
685 if (Func->hasError()) 685 if (Func->hasError())
686 return; 686 return;
687 Func->dump("After legalizeStackSlots"); 687 Func->dump("After postLowerLegalization");
688 688
689 Func->contractEmptyNodes(); 689 Func->contractEmptyNodes();
690 Func->reorderNodes(); 690 Func->reorderNodes();
691 691
692 // Branch optimization. This needs to be done just before code emission. In 692 // Branch optimization. This needs to be done just before code emission. In
693 // particular, no transformations that insert or reorder CfgNodes should be 693 // particular, no transformations that insert or reorder CfgNodes should be
694 // done after branch optimization. We go ahead and do it before nop insertion 694 // done after branch optimization. We go ahead and do it before nop insertion
695 // to reduce the amount of work needed for searching for opportunities. 695 // to reduce the amount of work needed for searching for opportunities.
696 Func->doBranchOpt(); 696 Func->doBranchOpt();
697 Func->dump("After branch optimization"); 697 Func->dump("After branch optimization");
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
739 copyRegAllocFromInfWeightVariable64On32(Func->getVariables()); 739 copyRegAllocFromInfWeightVariable64On32(Func->getVariables());
740 Func->dump("After regalloc of infinite-weight variables"); 740 Func->dump("After regalloc of infinite-weight variables");
741 741
742 ForbidTemporaryWithoutReg _(this); 742 ForbidTemporaryWithoutReg _(this);
743 743
744 Func->genFrame(); 744 Func->genFrame();
745 if (Func->hasError()) 745 if (Func->hasError())
746 return; 746 return;
747 Func->dump("After stack frame mapping"); 747 Func->dump("After stack frame mapping");
748 748
749 legalizeStackSlots(); 749 postLowerLegalization();
750 if (Func->hasError()) 750 if (Func->hasError())
751 return; 751 return;
752 Func->dump("After legalizeStackSlots"); 752 Func->dump("After postLowerLegalization");
753 753
754 // Nop insertion 754 // Nop insertion
755 if (Ctx->getFlags().shouldDoNopInsertion()) { 755 if (Ctx->getFlags().shouldDoNopInsertion()) {
756 Func->doNopInsertion(); 756 Func->doNopInsertion();
757 } 757 }
758 } 758 }
759 759
760 uint32_t TargetARM32::getStackAlignment() const { 760 uint32_t TargetARM32::getStackAlignment() const {
761 return ARM32_STACK_ALIGNMENT_BYTES; 761 return ARM32_STACK_ALIGNMENT_BYTES;
762 } 762 }
(...skipping 566 matching lines...) Expand 10 before | Expand all | Expand 10 after
1329 _ret(LR, RetValue); 1329 _ret(LR, RetValue);
1330 _bundle_unlock(); 1330 _bundle_unlock();
1331 RI->setDeleted(); 1331 RI->setDeleted();
1332 } 1332 }
1333 1333
1334 bool TargetARM32::isLegalMemOffset(Type Ty, int32_t Offset) const { 1334 bool TargetARM32::isLegalMemOffset(Type Ty, int32_t Offset) const {
1335 constexpr bool ZeroExt = false; 1335 constexpr bool ZeroExt = false;
1336 return OperandARM32Mem::canHoldOffset(Ty, ZeroExt, Offset); 1336 return OperandARM32Mem::canHoldOffset(Ty, ZeroExt, Offset);
1337 } 1337 }
1338 1338
1339 Variable *TargetARM32::newBaseRegister(int32_t Offset, Variable *OrigBaseReg) { 1339 Variable *TargetARM32::PostLoweringLegalizer::newBaseRegister(
1340 Variable *Base, int32_t Offset, int32_t ScratchRegNum) {
1340 // Legalize will likely need a movw/movt combination, but if the top bits are 1341 // Legalize will likely need a movw/movt combination, but if the top bits are
1341 // all 0 from negating the offset and subtracting, we could use that instead. 1342 // all 0 from negating the offset and subtracting, we could use that instead.
1342 bool ShouldSub = (-Offset & 0xFFFF0000) == 0; 1343 bool ShouldSub = (-Offset & 0xFFFF0000) == 0;
1343 if (ShouldSub) 1344 if (ShouldSub)
1344 Offset = -Offset; 1345 Offset = -Offset;
1345 Operand *OffsetVal = legalize(Ctx->getConstantInt32(Offset), 1346 Operand *OffsetVal = Target->legalize(Target->Ctx->getConstantInt32(Offset),
1346 Legal_Reg | Legal_Flex, getReservedTmpReg()); 1347 Legal_Reg | Legal_Flex, ScratchRegNum);
1347 Variable *ScratchReg = makeReg(IceType_i32, getReservedTmpReg()); 1348 Variable *ScratchReg = Target->makeReg(IceType_i32, ScratchRegNum);
1348 if (ShouldSub) 1349 if (ShouldSub)
1349 _sub(ScratchReg, OrigBaseReg, OffsetVal); 1350 Target->_sub(ScratchReg, Base, OffsetVal);
1350 else 1351 else
1351 _add(ScratchReg, OrigBaseReg, OffsetVal); 1352 Target->_add(ScratchReg, Base, OffsetVal);
1353
1354 if (ScratchRegNum == Target->getReservedTmpReg()) {
1355 const bool BaseIsStackOrFramePtr =
1356 Base->getRegNum() == static_cast<int32_t>(Target->getFrameOrStackReg());
1357 // There is currently no code path that would trigger this assertion, so we
1358 // leave this assertion here in case it is ever violated. This is not a
1359 // fatal error (thus the use of assert() and not llvm::report_fatal_error)
1360 // as the program compiled by subzero will still work correctly.
1361 assert(BaseIsStackOrFramePtr);
1362 // Side-effect: updates TempBase to reflect the new Temporary.
1363 if (BaseIsStackOrFramePtr) {
1364 TempBaseReg = ScratchReg;
1365 TempBaseOffset = ShouldSub ? -Offset : Offset;
1366 } else {
1367 TempBaseReg = nullptr;
1368 TempBaseOffset = 0;
1369 }
1370 }
1371
1352 return ScratchReg; 1372 return ScratchReg;
1353 } 1373 }
1354 1374
1355 OperandARM32Mem *TargetARM32::createMemOperand(Type Ty, int32_t Offset, 1375 OperandARM32Mem *TargetARM32::PostLoweringLegalizer::createMemOperand(
1356 Variable *OrigBaseReg, 1376 Type Ty, Variable *Base, int32_t Offset, bool AllowOffsets) {
1357 Variable **NewBaseReg, 1377 assert(!Base->isRematerializable());
1358 int32_t *NewBaseOffset) { 1378 if (AllowOffsets && Target->isLegalMemOffset(Ty, Offset)) {
1359 assert(!OrigBaseReg->isRematerializable());
1360 if (isLegalMemOffset(Ty, Offset)) {
1361 return OperandARM32Mem::create( 1379 return OperandARM32Mem::create(
1362 Func, Ty, OrigBaseReg, 1380 Target->Func, Ty, Base,
1363 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(Offset)), 1381 llvm::cast<ConstantInteger32>(Target->Ctx->getConstantInt32(Offset)),
1364 OperandARM32Mem::Offset); 1382 OperandARM32Mem::Offset);
1365 } 1383 }
1366 1384
1367 if (*NewBaseReg == nullptr) { 1385 if (!AllowOffsets || TempBaseReg == nullptr) {
1368 *NewBaseReg = newBaseRegister(Offset, OrigBaseReg); 1386 newBaseRegister(Base, Offset, Target->getReservedTmpReg());
1369 *NewBaseOffset = Offset;
1370 } 1387 }
1371 1388
1372 int32_t OffsetDiff = Offset - *NewBaseOffset; 1389 int32_t OffsetDiff = Offset - TempBaseOffset;
1373 if (!isLegalMemOffset(Ty, OffsetDiff)) { 1390 assert(AllowOffsets || OffsetDiff == 0);
1374 *NewBaseReg = newBaseRegister(Offset, OrigBaseReg); 1391
1375 *NewBaseOffset = Offset; 1392 if (!Target->isLegalMemOffset(Ty, OffsetDiff)) {
1393 newBaseRegister(Base, Offset, Target->getReservedTmpReg());
1376 OffsetDiff = 0; 1394 OffsetDiff = 0;
1377 } 1395 }
1378 1396
1379 assert(!(*NewBaseReg)->isRematerializable()); 1397 assert(!TempBaseReg->isRematerializable());
1380 return OperandARM32Mem::create( 1398 return OperandARM32Mem::create(
1381 Func, Ty, *NewBaseReg, 1399 Target->Func, Ty, TempBaseReg,
1382 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(OffsetDiff)), 1400 llvm::cast<ConstantInteger32>(Target->Ctx->getConstantInt32(OffsetDiff)),
1383 OperandARM32Mem::Offset); 1401 OperandARM32Mem::Offset);
1384 } 1402 }
1385 1403
1386 void TargetARM32::legalizeMov(InstARM32Mov *MovInstr, Variable *OrigBaseReg, 1404 void TargetARM32::PostLoweringLegalizer::resetTempBaseIfClobberedBy(
1387 Variable **NewBaseReg, int32_t *NewBaseOffset) { 1405 const Inst *Instr) {
1406 bool ClobbersTempBase = false;
1407 if (TempBaseReg != nullptr) {
1408 Variable *Dest = Instr->getDest();
1409 if (llvm::isa<InstARM32Call>(Instr)) {
1410 // The following assertion is an invariant, so we remove it from the if
1411 // test. If the invariant is ever broken/invalidated/changed, remember
1412 // to add it back to the if condition.
1413 assert(TempBaseReg->getRegNum() == Target->getReservedTmpReg());
1414 // The linker may need to clobber IP if the call is too far from PC. Thus,
1415 // we assume IP will be overwritten.
1416 ClobbersTempBase = true;
1417 } else if (Dest != nullptr &&
1418 Dest->getRegNum() == TempBaseReg->getRegNum()) {
1419 // Register redefinition.
1420 ClobbersTempBase = true;
1421 }
1422 }
1423
1424 if (ClobbersTempBase) {
1425 TempBaseReg = nullptr;
1426 TempBaseOffset = 0;
1427 }
1428 }
1429
1430 void TargetARM32::PostLoweringLegalizer::legalizeMov(InstARM32Mov *MovInstr) {
1388 Variable *Dest = MovInstr->getDest(); 1431 Variable *Dest = MovInstr->getDest();
1389 assert(Dest != nullptr); 1432 assert(Dest != nullptr);
1390 Type DestTy = Dest->getType(); 1433 Type DestTy = Dest->getType();
1391 assert(DestTy != IceType_i64); 1434 assert(DestTy != IceType_i64);
1392 1435
1393 Operand *Src = MovInstr->getSrc(0); 1436 Operand *Src = MovInstr->getSrc(0);
1394 Type SrcTy = Src->getType(); 1437 Type SrcTy = Src->getType();
1395 (void)SrcTy; 1438 (void)SrcTy;
1396 assert(SrcTy != IceType_i64); 1439 assert(SrcTy != IceType_i64);
1397 1440
1398 if (MovInstr->isMultiDest() || MovInstr->isMultiSource()) 1441 if (MovInstr->isMultiDest() || MovInstr->isMultiSource())
1399 return; 1442 return;
1400 1443
1401 bool Legalized = false; 1444 bool Legalized = false;
1402 if (!Dest->hasReg()) { 1445 if (!Dest->hasReg()) {
1403 auto *SrcR = llvm::cast<Variable>(Src); 1446 auto *SrcR = llvm::cast<Variable>(Src);
1404 assert(SrcR->hasReg()); 1447 assert(SrcR->hasReg());
1405 assert(!SrcR->isRematerializable()); 1448 assert(!SrcR->isRematerializable());
1406 const int32_t Offset = Dest->getStackOffset(); 1449 const int32_t Offset = Dest->getStackOffset();
1407 // This is a _mov(Mem(), Variable), i.e., a store. 1450 // This is a _mov(Mem(), Variable), i.e., a store.
1408 _str(SrcR, createMemOperand(DestTy, Offset, OrigBaseReg, NewBaseReg, 1451 Target->_str(SrcR, createMemOperand(DestTy, StackOrFrameReg, Offset),
1409 NewBaseOffset), 1452 MovInstr->getPredicate());
1410 MovInstr->getPredicate());
1411 // _str() does not have a Dest, so we add a fake-def(Dest). 1453 // _str() does not have a Dest, so we add a fake-def(Dest).
1412 Context.insert(InstFakeDef::create(Func, Dest)); 1454 Target->Context.insert(InstFakeDef::create(Target->Func, Dest));
1413 Legalized = true; 1455 Legalized = true;
1414 } else if (auto *Var = llvm::dyn_cast<Variable>(Src)) { 1456 } else if (auto *Var = llvm::dyn_cast<Variable>(Src)) {
1415 if (Var->isRematerializable()) { 1457 if (Var->isRematerializable()) {
1416 // Rematerialization arithmetic. 1458 // This is equivalent to an x86 _lea(RematOffset(%esp/%ebp), Variable).
1459
1460 // ExtraOffset is only needed for frame-pointer based frames as we have
1461 // to account for spill storage.
1417 const int32_t ExtraOffset = 1462 const int32_t ExtraOffset =
1418 (static_cast<SizeT>(Var->getRegNum()) == getFrameReg()) 1463 (static_cast<SizeT>(Var->getRegNum()) == Target->getFrameReg())
1419 ? getFrameFixedAllocaOffset() 1464 ? Target->getFrameFixedAllocaOffset()
1420 : 0; 1465 : 0;
1421 1466
1422 const int32_t Offset = Var->getStackOffset() + ExtraOffset; 1467 const int32_t Offset = Var->getStackOffset() + ExtraOffset;
1423 Operand *OffsetRF = legalize(Ctx->getConstantInt32(Offset), 1468 Variable *Base = Target->getPhysicalRegister(Var->getRegNum());
1424 Legal_Reg | Legal_Flex, Dest->getRegNum()); 1469 Variable *T = newBaseRegister(Base, Offset, Dest->getRegNum());
1425 _add(Dest, Var, OffsetRF); 1470 Target->_mov(Dest, T);
1426 Legalized = true; 1471 Legalized = true;
1427 } else { 1472 } else {
1428 if (!Var->hasReg()) { 1473 if (!Var->hasReg()) {
1474 // This is a _mov(Variable, Mem()), i.e., a load.
1429 const int32_t Offset = Var->getStackOffset(); 1475 const int32_t Offset = Var->getStackOffset();
1430 _ldr(Dest, createMemOperand(DestTy, Offset, OrigBaseReg, NewBaseReg, 1476 Target->_ldr(Dest, createMemOperand(DestTy, StackOrFrameReg, Offset),
1431 NewBaseOffset), 1477 MovInstr->getPredicate());
1432 MovInstr->getPredicate());
1433 Legalized = true; 1478 Legalized = true;
1434 } 1479 }
1435 } 1480 }
1436 } 1481 }
1437 1482
1438 if (Legalized) { 1483 if (Legalized) {
1439 if (MovInstr->isDestRedefined()) { 1484 if (MovInstr->isDestRedefined()) {
1440 _set_dest_redefined(); 1485 Target->_set_dest_redefined();
1441 } 1486 }
1442 MovInstr->setDeleted(); 1487 MovInstr->setDeleted();
1443 } 1488 }
1444 } 1489 }
1445 1490
1446 void TargetARM32::legalizeStackSlots() { 1491 // ARM32 address modes:
1492 // ld/st i[8|16|32]: [reg], [reg +/- imm12], [pc +/- imm12],
1493 // [reg +/- reg << shamt5]
1494 // ld/st f[32|64] : [reg], [reg +/- imm8] , [pc +/- imm8]
1495 // ld/st vectors : [reg]
1496 //
1497 // For now, we don't handle address modes with Relocatables.
1498 namespace {
1499 // MemTraits contains per-type valid address mode information.
1500 #define X(tag, elementty, int_width, vec_width, sbits, ubits, rraddr, shaddr) \
1501 static_assert(!(shaddr) || rraddr, "Check ICETYPEARM32_TABLE::" #tag);
1502 ICETYPEARM32_TABLE
1503 #undef X
1504
1505 static const struct {
1506 int32_t ValidImmMask;
1507 bool CanHaveImm;
1508 bool CanHaveIndex;
1509 bool CanHaveShiftedIndex;
1510 } MemTraits[] = {
1511 #define X(tag, elementty, int_width, vec_width, sbits, ubits, rraddr, shaddr) \
1512 { (1 << ubits) - 1, (ubits) > 0, rraddr, shaddr, } \
1513 ,
1514 ICETYPEARM32_TABLE
1515 #undef X
1516 };
1517 static constexpr SizeT MemTraitsSize = llvm::array_lengthof(MemTraits);
1518 } // end of anonymous namespace
1519
1520 OperandARM32Mem *
1521 TargetARM32::PostLoweringLegalizer::legalizeMemOperand(OperandARM32Mem *Mem,
1522 bool AllowOffsets) {
1523 assert(!Mem->isRegReg() || !Mem->getIndex()->isRematerializable());
1524 assert(
1525 Mem->isRegReg() ||
1526 Target->isLegalMemOffset(Mem->getType(), Mem->getOffset()->getValue()));
1527
1528 bool Legalized = false;
1529 Variable *Base = Mem->getBase();
1530 int32_t Offset = Mem->isRegReg() ? 0 : Mem->getOffset()->getValue();
1531 if (Base->isRematerializable()) {
1532 const int32_t ExtraOffset =
1533 (static_cast<SizeT>(Base->getRegNum()) == Target->getFrameReg())
1534 ? Target->getFrameFixedAllocaOffset()
1535 : 0;
1536 Offset += Base->getStackOffset() + ExtraOffset;
1537 Base = Target->getPhysicalRegister(Base->getRegNum());
1538 assert(!Base->isRematerializable());
1539 Legalized = true;
1540 }
1541
1542 if (!Legalized) {
1543 return nullptr;
1544 }
1545
1546 if (!Mem->isRegReg()) {
1547 return createMemOperand(Mem->getType(), Base, Offset, AllowOffsets);
1548 }
1549
1550 assert(MemTraits[Mem->getType()].CanHaveIndex);
1551
1552 if (Offset != 0) {
1553 if (TempBaseReg == nullptr) {
1554 Base = newBaseRegister(Base, Offset, Target->getReservedTmpReg());
1555 } else {
1556 uint32_t Imm8, Rotate;
1557 const int32_t OffsetDiff = Offset - TempBaseOffset;
1558 if (OffsetDiff == 0) {
1559 Base = TempBaseReg;
1560 } else if (OperandARM32FlexImm::canHoldImm(OffsetDiff, &Rotate, &Imm8)) {
1561 auto *OffsetDiffF = OperandARM32FlexImm::create(
1562 Target->Func, IceType_i32, Imm8, Rotate);
1563 Target->_add(TempBaseReg, TempBaseReg, OffsetDiffF);
1564 TempBaseOffset += OffsetDiff;
1565 Base = TempBaseReg;
1566 } else if (OperandARM32FlexImm::canHoldImm(-OffsetDiff, &Rotate, &Imm8)) {
1567 auto *OffsetDiffF = OperandARM32FlexImm::create(
1568 Target->Func, IceType_i32, Imm8, Rotate);
1569 Target->_sub(TempBaseReg, TempBaseReg, OffsetDiffF);
1570 TempBaseOffset += OffsetDiff;
1571 Base = TempBaseReg;
1572 } else {
1573 Base = newBaseRegister(Base, Offset, Target->getReservedTmpReg());
1574 }
1575 }
1576 }
1577
1578 return OperandARM32Mem::create(Target->Func, Mem->getType(), Base,
1579 Mem->getIndex(), Mem->getShiftOp(),
1580 Mem->getShiftAmt(), Mem->getAddrMode());
1581 }
1582
1583 void TargetARM32::postLowerLegalization() {
1447 // If a stack variable's frame offset doesn't fit, convert from: 1584 // If a stack variable's frame offset doesn't fit, convert from:
1448 // ldr X, OFF[SP] 1585 // ldr X, OFF[SP]
1449 // to: 1586 // to:
1450 // movw/movt TMP, OFF_PART 1587 // movw/movt TMP, OFF_PART
1451 // add TMP, TMP, SP 1588 // add TMP, TMP, SP
1452 // ldr X, OFF_MORE[TMP] 1589 // ldr X, OFF_MORE[TMP]
1453 // 1590 //
1454 // This is safe because we have reserved TMP, and add for ARM does not 1591 // This is safe because we have reserved TMP, and add for ARM does not
1455 // clobber the flags register. 1592 // clobber the flags register.
1456 Func->dump("Before legalizeStackSlots"); 1593 Func->dump("Before postLowerLegalization");
1457 assert(hasComputedFrame()); 1594 assert(hasComputedFrame());
1458 Variable *OrigBaseReg = getPhysicalRegister(getFrameOrStackReg());
1459 // Do a fairly naive greedy clustering for now. Pick the first stack slot 1595 // Do a fairly naive greedy clustering for now. Pick the first stack slot
1460 // that's out of bounds and make a new base reg using the architecture's temp 1596 // that's out of bounds and make a new base reg using the architecture's temp
1461 // register. If that works for the next slot, then great. Otherwise, create a 1597 // register. If that works for the next slot, then great. Otherwise, create a
1462 // new base register, clobbering the previous base register. Never share a 1598 // new base register, clobbering the previous base register. Never share a
1463 // base reg across different basic blocks. This isn't ideal if local and 1599 // base reg across different basic blocks. This isn't ideal if local and
1464 // multi-block variables are far apart and their references are interspersed. 1600 // multi-block variables are far apart and their references are interspersed.
1465 // It may help to be more coordinated about assign stack slot numbers and may 1601 // It may help to be more coordinated about assign stack slot numbers and may
1466 // help to assign smaller offsets to higher-weight variables so that they 1602 // help to assign smaller offsets to higher-weight variables so that they
1467 // don't depend on this legalization. 1603 // don't depend on this legalization.
1468 for (CfgNode *Node : Func->getNodes()) { 1604 for (CfgNode *Node : Func->getNodes()) {
1469 Context.init(Node); 1605 Context.init(Node);
1470 Variable *NewBaseReg = nullptr; 1606 // One legalizer per basic block, otherwise we would share the Temporary
1471 int32_t NewBaseOffset = 0; 1607 // Base Register between basic blocks.
1608 PostLoweringLegalizer Legalizer(this);
1472 while (!Context.atEnd()) { 1609 while (!Context.atEnd()) {
1473 PostIncrLoweringContext PostIncrement(Context); 1610 PostIncrLoweringContext PostIncrement(Context);
1474 Inst *CurInstr = Context.getCur(); 1611 Inst *CurInstr = Context.getCur();
1475 Variable *Dest = CurInstr->getDest();
1476 1612
1477 // Check if the previous NewBaseReg is clobbered, and reset if needed. 1613 // Check if the previous TempBaseReg is clobbered, and reset if needed.
1478 if ((Dest && NewBaseReg && Dest->hasReg() && 1614 Legalizer.resetTempBaseIfClobberedBy(CurInstr);
1479 Dest->getRegNum() == NewBaseReg->getBaseRegNum()) || 1615
1480 llvm::isa<InstFakeKill>(CurInstr)) { 1616 if (auto *MovInstr = llvm::dyn_cast<InstARM32Mov>(CurInstr)) {
1481 NewBaseReg = nullptr; 1617 Legalizer.legalizeMov(MovInstr);
1482 NewBaseOffset = 0; 1618 } else if (auto *LdrInstr = llvm::dyn_cast<InstARM32Ldr>(CurInstr)) {
1619 if (OperandARM32Mem *LegalMem = Legalizer.legalizeMemOperand(
1620 llvm::cast<OperandARM32Mem>(LdrInstr->getSrc(0)))) {
1621 _ldr(CurInstr->getDest(), LegalMem, LdrInstr->getPredicate());
1622 CurInstr->setDeleted();
1623 }
1624 } else if (auto *LdrexInstr = llvm::dyn_cast<InstARM32Ldrex>(CurInstr)) {
1625 constexpr bool DisallowOffsetsBecauseLdrex = false;
1626 if (OperandARM32Mem *LegalMem = Legalizer.legalizeMemOperand(
1627 llvm::cast<OperandARM32Mem>(LdrexInstr->getSrc(0)),
1628 DisallowOffsetsBecauseLdrex)) {
1629 _ldrex(CurInstr->getDest(), LegalMem, LdrexInstr->getPredicate());
1630 CurInstr->setDeleted();
1631 }
1632 } else if (auto *StrInstr = llvm::dyn_cast<InstARM32Str>(CurInstr)) {
1633 if (OperandARM32Mem *LegalMem = Legalizer.legalizeMemOperand(
1634 llvm::cast<OperandARM32Mem>(StrInstr->getSrc(1)))) {
1635 _str(llvm::cast<Variable>(CurInstr->getSrc(0)), LegalMem,
1636 StrInstr->getPredicate());
1637 CurInstr->setDeleted();
1638 }
1639 } else if (auto *StrexInstr = llvm::dyn_cast<InstARM32Strex>(CurInstr)) {
1640 constexpr bool DisallowOffsetsBecauseStrex = false;
1641 if (OperandARM32Mem *LegalMem = Legalizer.legalizeMemOperand(
1642 llvm::cast<OperandARM32Mem>(StrexInstr->getSrc(1)),
1643 DisallowOffsetsBecauseStrex)) {
1644 _strex(CurInstr->getDest(), llvm::cast<Variable>(CurInstr->getSrc(0)),
1645 LegalMem, StrexInstr->getPredicate());
1646 CurInstr->setDeleted();
1647 }
1483 } 1648 }
1484 1649
1485 if (auto *MovInstr = llvm::dyn_cast<InstARM32Mov>(CurInstr)) { 1650 // Sanity-check: the Legalizer will either have no Temp, or it will be
1486 legalizeMov(MovInstr, OrigBaseReg, &NewBaseReg, &NewBaseOffset); 1651 // bound to IP.
1487 } 1652 Legalizer.assertNoTempOrAssignedToIP();
1488 } 1653 }
1489 } 1654 }
1490 } 1655 }
1491 1656
1492 Operand *TargetARM32::loOperand(Operand *Operand) { 1657 Operand *TargetARM32::loOperand(Operand *Operand) {
1493 assert(Operand->getType() == IceType_i64); 1658 assert(Operand->getType() == IceType_i64);
1494 if (Operand->getType() != IceType_i64) 1659 if (Operand->getType() != IceType_i64)
1495 return Operand; 1660 return Operand;
1496 if (auto *Var64On32 = llvm::dyn_cast<Variable64On32>(Operand)) 1661 if (auto *Var64On32 = llvm::dyn_cast<Variable64On32>(Operand))
1497 return Var64On32->getLo(); 1662 return Var64On32->getLo();
1498 if (auto *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) 1663 if (auto *Const = llvm::dyn_cast<ConstantInteger64>(Operand))
1499 return Ctx->getConstantInt32(static_cast<uint32_t>(Const->getValue())); 1664 return Ctx->getConstantInt32(static_cast<uint32_t>(Const->getValue()));
1500 if (auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Operand)) { 1665 if (auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Operand)) {
1501 // Conservatively disallow memory operands with side-effects (pre/post 1666 // Conservatively disallow memory operands with side-effects (pre/post
1502 // increment) in case of duplication. 1667 // increment) in case of duplication.
1503 assert(Mem->getAddrMode() == OperandARM32Mem::Offset || 1668 assert(Mem->getAddrMode() == OperandARM32Mem::Offset ||
1504 Mem->getAddrMode() == OperandARM32Mem::NegOffset); 1669 Mem->getAddrMode() == OperandARM32Mem::NegOffset);
1505 Variable *BaseR = legalizeToReg(Mem->getBase());
1506 if (Mem->isRegReg()) { 1670 if (Mem->isRegReg()) {
1507 Variable *IndexR = legalizeToReg(Mem->getIndex()); 1671 Variable *IndexR = legalizeToReg(Mem->getIndex());
1508 return OperandARM32Mem::create(Func, IceType_i32, BaseR, IndexR, 1672 return OperandARM32Mem::create(Func, IceType_i32, Mem->getBase(), IndexR,
1509 Mem->getShiftOp(), Mem->getShiftAmt(), 1673 Mem->getShiftOp(), Mem->getShiftAmt(),
1510 Mem->getAddrMode()); 1674 Mem->getAddrMode());
1511 } else { 1675 } else {
1512 return OperandARM32Mem::create(Func, IceType_i32, BaseR, Mem->getOffset(), 1676 return OperandARM32Mem::create(Func, IceType_i32, Mem->getBase(),
1513 Mem->getAddrMode()); 1677 Mem->getOffset(), Mem->getAddrMode());
1514 } 1678 }
1515 } 1679 }
1516 llvm::report_fatal_error("Unsupported operand type"); 1680 llvm::report_fatal_error("Unsupported operand type");
1517 return nullptr; 1681 return nullptr;
1518 } 1682 }
1519 1683
1520 Operand *TargetARM32::hiOperand(Operand *Operand) { 1684 Operand *TargetARM32::hiOperand(Operand *Operand) {
1521 assert(Operand->getType() == IceType_i64); 1685 assert(Operand->getType() == IceType_i64);
1522 if (Operand->getType() != IceType_i64) 1686 if (Operand->getType() != IceType_i64)
1523 return Operand; 1687 return Operand;
(...skipping 3260 matching lines...) Expand 10 before | Expand all | Expand 10 after
4784 4948
4785 // Update the computed address parameters once we are sure optimization 4949 // Update the computed address parameters once we are sure optimization
4786 // is valid. 4950 // is valid.
4787 *Base = NewBase; 4951 *Base = NewBase;
4788 *Offset = NewOffset; 4952 *Offset = NewOffset;
4789 *Reason = BaseInst; 4953 *Reason = BaseInst;
4790 return true; 4954 return true;
4791 } 4955 }
4792 } // end of anonymous namespace 4956 } // end of anonymous namespace
4793 4957
4794 // ARM32 address modes:
4795 // ld/st i[8|16|32]: [reg], [reg +/- imm12], [pc +/- imm12],
4796 // [reg +/- reg << shamt5]
4797 // ld/st f[32|64] : [reg], [reg +/- imm8] , [pc +/- imm8]
4798 // ld/st vectors : [reg]
4799 //
4800 // For now, we don't handle address modes with Relocatables.
4801 namespace {
4802 // MemTraits contains per-type valid address mode information.
4803 #define X(tag, elementty, int_width, vec_width, sbits, ubits, rraddr, shaddr) \
4804 static_assert(!(shaddr) || rraddr, "Check ICETYPEARM32_TABLE::" #tag);
4805 ICETYPEARM32_TABLE
4806 #undef X
4807
4808 static const struct {
4809 int32_t ValidImmMask;
4810 bool CanHaveImm;
4811 bool CanHaveIndex;
4812 bool CanHaveShiftedIndex;
4813 } MemTraits[] = {
4814 #define X(tag, elementty, int_width, vec_width, sbits, ubits, rraddr, shaddr) \
4815 { (1 << ubits) - 1, (ubits) > 0, rraddr, shaddr, } \
4816 ,
4817 ICETYPEARM32_TABLE
4818 #undef X
4819 };
4820 static constexpr SizeT MemTraitsSize = llvm::array_lengthof(MemTraits);
4821 } // end of anonymous namespace
4822
4823 OperandARM32Mem *TargetARM32::formAddressingMode(Type Ty, Cfg *Func, 4958 OperandARM32Mem *TargetARM32::formAddressingMode(Type Ty, Cfg *Func,
4824 const Inst *LdSt, 4959 const Inst *LdSt,
4825 Operand *Base) { 4960 Operand *Base) {
4826 assert(Base != nullptr); 4961 assert(Base != nullptr);
4827 int32_t OffsetImm = 0; 4962 int32_t OffsetImm = 0;
4828 Variable *OffsetReg = nullptr; 4963 Variable *OffsetReg = nullptr;
4829 int32_t OffsetRegShamt = 0; 4964 int32_t OffsetRegShamt = 0;
4830 OperandARM32::ShiftKind ShiftKind = OperandARM32::kNoShift; 4965 OperandARM32::ShiftKind ShiftKind = OperandARM32::kNoShift;
4831 4966
4832 Func->resetCurrentNode(); 4967 Func->resetCurrentNode();
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
4948 OffsetImm = 0; 5083 OffsetImm = 0;
4949 } 5084 }
4950 } 5085 }
4951 5086
4952 assert(BaseVar != nullptr); 5087 assert(BaseVar != nullptr);
4953 assert(OffsetImm == 0 || OffsetReg == nullptr); 5088 assert(OffsetImm == 0 || OffsetReg == nullptr);
4954 assert(OffsetReg == nullptr || CanHaveIndex); 5089 assert(OffsetReg == nullptr || CanHaveIndex);
4955 assert(OffsetImm < 0 ? (ValidImmMask & -OffsetImm) == -OffsetImm 5090 assert(OffsetImm < 0 ? (ValidImmMask & -OffsetImm) == -OffsetImm
4956 : (ValidImmMask & OffsetImm) == OffsetImm); 5091 : (ValidImmMask & OffsetImm) == OffsetImm);
4957 5092
4958 Variable *BaseR = makeReg(getPointerType());
4959 Context.insert(InstAssign::create(Func, BaseR, BaseVar));
4960 if (OffsetReg != nullptr) { 5093 if (OffsetReg != nullptr) {
4961 Variable *OffsetR = makeReg(getPointerType()); 5094 Variable *OffsetR = makeReg(getPointerType());
4962 Context.insert(InstAssign::create(Func, OffsetR, OffsetReg)); 5095 Context.insert(InstAssign::create(Func, OffsetR, OffsetReg));
4963 return OperandARM32Mem::create(Func, Ty, BaseR, OffsetR, ShiftKind, 5096 return OperandARM32Mem::create(Func, Ty, BaseVar, OffsetR, ShiftKind,
4964 OffsetRegShamt); 5097 OffsetRegShamt);
4965 } 5098 }
4966 5099
4967 return OperandARM32Mem::create( 5100 return OperandARM32Mem::create(
4968 Func, Ty, BaseR, 5101 Func, Ty, BaseVar,
4969 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(OffsetImm))); 5102 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(OffsetImm)));
4970 } 5103 }
4971 5104
4972 void TargetARM32::doAddressOptLoad() { 5105 void TargetARM32::doAddressOptLoad() {
4973 Inst *Instr = Context.getCur(); 5106 Inst *Instr = Context.getCur();
4974 assert(llvm::isa<InstLoad>(Instr)); 5107 assert(llvm::isa<InstLoad>(Instr));
4975 Variable *Dest = Instr->getDest(); 5108 Variable *Dest = Instr->getDest();
4976 Operand *Addr = Instr->getSrc(0); 5109 Operand *Addr = Instr->getSrc(0);
4977 if (OperandARM32Mem *Mem = 5110 if (OperandARM32Mem *Mem =
4978 formAddressingMode(Dest->getType(), Func, Instr, Addr)) { 5111 formAddressingMode(Dest->getType(), Func, Instr, Addr)) {
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
5182 if (auto *Mem = llvm::dyn_cast<OperandARM32Mem>(From)) { 5315 if (auto *Mem = llvm::dyn_cast<OperandARM32Mem>(From)) {
5183 // Before doing anything with a Mem operand, we need to ensure that the 5316 // Before doing anything with a Mem operand, we need to ensure that the
5184 // Base and Index components are in physical registers. 5317 // Base and Index components are in physical registers.
5185 Variable *Base = Mem->getBase(); 5318 Variable *Base = Mem->getBase();
5186 Variable *Index = Mem->getIndex(); 5319 Variable *Index = Mem->getIndex();
5187 ConstantInteger32 *Offset = Mem->getOffset(); 5320 ConstantInteger32 *Offset = Mem->getOffset();
5188 assert(Index == nullptr || Offset == nullptr); 5321 assert(Index == nullptr || Offset == nullptr);
5189 Variable *RegBase = nullptr; 5322 Variable *RegBase = nullptr;
5190 Variable *RegIndex = nullptr; 5323 Variable *RegIndex = nullptr;
5191 assert(Base); 5324 assert(Base);
5192 RegBase = legalizeToReg(Base); 5325 RegBase = llvm::cast<Variable>(
5326 legalize(Base, Legal_Reg | Legal_Rematerializable));
5193 assert(Ty < MemTraitsSize); 5327 assert(Ty < MemTraitsSize);
5194 if (Index) { 5328 if (Index) {
5195 assert(Offset == nullptr); 5329 assert(Offset == nullptr);
5196 assert(MemTraits[Ty].CanHaveIndex); 5330 assert(MemTraits[Ty].CanHaveIndex);
5197 RegIndex = legalizeToReg(Index); 5331 RegIndex = legalizeToReg(Index);
5198 } 5332 }
5199 if (Offset && Offset->getValue() != 0) { 5333 if (Offset && Offset->getValue() != 0) {
5200 assert(Index == nullptr); 5334 assert(Index == nullptr);
5201 static constexpr bool ZeroExt = false; 5335 static constexpr bool ZeroExt = false;
5202 assert(MemTraits[Ty].CanHaveImm); 5336 assert(MemTraits[Ty].CanHaveImm);
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
5317 Variable *BaseReg = makeReg(getPointerType()); 5451 Variable *BaseReg = makeReg(getPointerType());
5318 _movw(BaseReg, Offset); 5452 _movw(BaseReg, Offset);
5319 _movt(BaseReg, Offset); 5453 _movt(BaseReg, Offset);
5320 From = formMemoryOperand(BaseReg, Ty); 5454 From = formMemoryOperand(BaseReg, Ty);
5321 return copyToReg(From, RegNum); 5455 return copyToReg(From, RegNum);
5322 } 5456 }
5323 } 5457 }
5324 5458
5325 if (auto *Var = llvm::dyn_cast<Variable>(From)) { 5459 if (auto *Var = llvm::dyn_cast<Variable>(From)) {
5326 if (Var->isRematerializable()) { 5460 if (Var->isRematerializable()) {
5461 if (Allowed & Legal_Rematerializable) {
5462 return From;
5463 }
5464
5327 // TODO(jpp): We don't need to rematerialize Var if legalize() was invoked 5465 // TODO(jpp): We don't need to rematerialize Var if legalize() was invoked
5328 // for a Variable in a Mem operand. 5466 // for a Variable in a Mem operand.
5329 Variable *T = makeReg(Var->getType(), RegNum); 5467 Variable *T = makeReg(Var->getType(), RegNum);
5330 _mov(T, Var); 5468 _mov(T, Var);
5331 return T; 5469 return T;
5332 } 5470 }
5333 // Check if the variable is guaranteed a physical register. This can happen 5471 // Check if the variable is guaranteed a physical register. This can happen
5334 // either when the variable is pre-colored or when it is assigned infinite 5472 // either when the variable is pre-colored or when it is assigned infinite
5335 // weight. 5473 // weight.
5336 bool MustHaveRegister = (Var->hasReg() || Var->mustHaveReg()); 5474 bool MustHaveRegister = (Var->hasReg() || Var->mustHaveReg());
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
5379 OperandARM32Mem *Mem = llvm::dyn_cast<OperandARM32Mem>(Operand); 5517 OperandARM32Mem *Mem = llvm::dyn_cast<OperandARM32Mem>(Operand);
5380 // It may be the case that address mode optimization already creates an 5518 // It may be the case that address mode optimization already creates an
5381 // OperandARM32Mem, so in that case it wouldn't need another level of 5519 // OperandARM32Mem, so in that case it wouldn't need another level of
5382 // transformation. 5520 // transformation.
5383 if (Mem) { 5521 if (Mem) {
5384 return llvm::cast<OperandARM32Mem>(legalize(Mem)); 5522 return llvm::cast<OperandARM32Mem>(legalize(Mem));
5385 } 5523 }
5386 // If we didn't do address mode optimization, then we only have a 5524 // If we didn't do address mode optimization, then we only have a
5387 // base/offset to work with. ARM always requires a base register, so 5525 // base/offset to work with. ARM always requires a base register, so
5388 // just use that to hold the operand. 5526 // just use that to hold the operand.
5389 Variable *BaseR = legalizeToReg(Operand); 5527 Variable *Base = llvm::cast<Variable>(
5528 legalize(Operand, Legal_Reg | Legal_Rematerializable));
5390 return OperandARM32Mem::create( 5529 return OperandARM32Mem::create(
5391 Func, Ty, BaseR, 5530 Func, Ty, Base,
5392 llvm::cast<ConstantInteger32>(Ctx->getConstantZero(IceType_i32))); 5531 llvm::cast<ConstantInteger32>(Ctx->getConstantZero(IceType_i32)));
5393 } 5532 }
5394 5533
5395 Variable64On32 *TargetARM32::makeI64RegPair() { 5534 Variable64On32 *TargetARM32::makeI64RegPair() {
5396 Variable64On32 *Reg = 5535 Variable64On32 *Reg =
5397 llvm::cast<Variable64On32>(Func->makeVariable(IceType_i64)); 5536 llvm::cast<Variable64On32>(Func->makeVariable(IceType_i64));
5398 Reg->setMustHaveReg(); 5537 Reg->setMustHaveReg();
5399 Reg->initHiLo(Func); 5538 Reg->initHiLo(Func);
5400 Reg->getLo()->setMustNotHaveReg(); 5539 Reg->getLo()->setMustNotHaveReg();
5401 Reg->getHi()->setMustNotHaveReg(); 5540 Reg->getHi()->setMustNotHaveReg();
(...skipping 556 matching lines...) Expand 10 before | Expand all | Expand 10 after
5958 // Technically R9 is used for TLS with Sandboxing, and we reserve it. 6097 // Technically R9 is used for TLS with Sandboxing, and we reserve it.
5959 // However, for compatibility with current NaCl LLVM, don't claim that. 6098 // However, for compatibility with current NaCl LLVM, don't claim that.
5960 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; 6099 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n";
5961 } 6100 }
5962 6101
5963 llvm::SmallBitVector TargetARM32::TypeToRegisterSet[IceType_NUM]; 6102 llvm::SmallBitVector TargetARM32::TypeToRegisterSet[IceType_NUM];
5964 llvm::SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; 6103 llvm::SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM];
5965 llvm::SmallBitVector TargetARM32::ScratchRegs; 6104 llvm::SmallBitVector TargetARM32::ScratchRegs;
5966 6105
5967 } // end of namespace Ice 6106 } // end of namespace Ice
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698