llvm.org GIT mirror llvm / c6f9261
ARM stm/ldm instructions require more than one register in the register list. Otherwise, a plain str/ldr should be used instead. Make sure we account for that in prologue/epilogue code generation. rdar://8745460 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@121391 91177308-0d34-0410-b5e6-96231b3b80d8 Jim Grosbach 9 years ago
4 changed file(s) with 65 addition(s) and 24 deletion(s). Raw diff Collapse all Expand all
1111 //===----------------------------------------------------------------------===//
1212
1313 #include "ARMFrameInfo.h"
14 #include "ARMAddressingModes.h"
1415 #include "ARMBaseInstrInfo.h"
1516 #include "ARMMachineFunctionInfo.h"
1617 #include "llvm/CodeGen/MachineFrameInfo.h"
500501 void ARMFrameInfo::emitPushInst(MachineBasicBlock &MBB,
501502 MachineBasicBlock::iterator MI,
502503 const std::vector &CSI,
503 unsigned Opc, bool NoGap,
504 unsigned StmOpc, unsigned StrOpc, bool NoGap,
504505 bool(*Func)(unsigned, bool)) const {
505506 MachineFunction &MF = *MBB.getParent();
506507 const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
539540 Regs.push_back(std::make_pair(Reg, isKill));
540541 }
541542
542 if (!Regs.empty()) {
543 if (Regs.empty())
544 continue;
545 if (Regs.size() > 1 || StrOpc== 0) {
543546 MachineInstrBuilder MIB =
544 AddDefaultPred(BuildMI(MBB, MI, DL, TII.get(Opc), ARM::SP)
547 AddDefaultPred(BuildMI(MBB, MI, DL, TII.get(StmOpc), ARM::SP)
545548 .addReg(ARM::SP));
546549 for (unsigned i = 0, e = Regs.size(); i < e; ++i)
547550 MIB.addReg(Regs[i].first, getKillRegState(Regs[i].second));
548 Regs.clear();
549 }
551 } else if (Regs.size() == 1) {
552 MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, TII.get(StrOpc),
553 ARM::SP)
554 .addReg(Regs[0].first, getKillRegState(Regs[0].second))
555 .addReg(ARM::SP);
556 // ARM mode needs an extra reg0 here due to addrmode2. Will go away once
557 // that refactoring is complete (eventually).
558 if (StrOpc == ARM::STR_PRE) {
559 MIB.addReg(0);
560 MIB.addImm(ARM_AM::getAM2Opc(ARM_AM::sub, 4, ARM_AM::no_shift));
561 } else
562 MIB.addImm(-4);
563 AddDefaultPred(MIB);
564 }
565 Regs.clear();
550566 }
551567 }
552568
553569 void ARMFrameInfo::emitPopInst(MachineBasicBlock &MBB,
554570 MachineBasicBlock::iterator MI,
555571 const std::vector &CSI,
556 unsigned Opc, bool isVarArg, bool NoGap,
572 unsigned LdmOpc, unsigned LdrOpc,
573 bool isVarArg, bool NoGap,
557574 bool(*Func)(unsigned, bool)) const {
558575 MachineFunction &MF = *MBB.getParent();
559576 const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
571588
572589 if (Reg == ARM::LR && !isVarArg) {
573590 Reg = ARM::PC;
574 Opc = AFI->isThumbFunction() ? ARM::t2LDMIA_RET : ARM::LDMIA_RET;
591 LdmOpc = AFI->isThumbFunction() ? ARM::t2LDMIA_RET : ARM::LDMIA_RET;
575592 // Fold the return instruction into the LDM.
576593 DeleteRet = true;
577594 }
586603 Regs.push_back(Reg);
587604 }
588605
589 if (!Regs.empty()) {
606 if (Regs.empty())
607 continue;
608 if (Regs.size() > 1 || LdrOpc == 0) {
590609 MachineInstrBuilder MIB =
591 AddDefaultPred(BuildMI(MBB, MI, DL, TII.get(Opc), ARM::SP)
610 AddDefaultPred(BuildMI(MBB, MI, DL, TII.get(LdmOpc), ARM::SP)
592611 .addReg(ARM::SP));
593612 for (unsigned i = 0, e = Regs.size(); i < e; ++i)
594613 MIB.addReg(Regs[i], getDefRegState(true));
595614 if (DeleteRet)
596615 MI->eraseFromParent();
597616 MI = MIB;
598 Regs.clear();
599 }
617 } else if (Regs.size() == 1) {
618 // If we adjusted the reg to PC from LR above, switch it back here. We
619 // only do that for LDM.
620 if (Regs[0] == ARM::PC)
621 Regs[0] = ARM::LR;
622 MachineInstrBuilder MIB =
623 BuildMI(MBB, MI, DL, TII.get(LdrOpc), Regs[0])
624 .addReg(ARM::SP, RegState::Define)
625 .addReg(ARM::SP);
626 // ARM mode needs an extra reg0 here due to addrmode2. Will go away once
627 // that refactoring is complete (eventually).
628 if (LdrOpc == ARM::LDR_POST) {
629 MIB.addReg(0);
630 MIB.addImm(ARM_AM::getAM2Opc(ARM_AM::add, 4, ARM_AM::no_shift));
631 } else
632 MIB.addImm(4);
633 AddDefaultPred(MIB);
634 }
635 Regs.clear();
600636 }
601637 }
602638
612648 DebugLoc DL = MI->getDebugLoc();
613649
614650 unsigned PushOpc = AFI->isThumbFunction() ? ARM::t2STMDB_UPD : ARM::STMDB_UPD;
651 unsigned PushOneOpc = AFI->isThumbFunction() ? ARM::t2STR_PRE : ARM::STR_PRE;
615652 unsigned FltOpc = ARM::VSTMDDB_UPD;
616 emitPushInst(MBB, MI, CSI, PushOpc, false, &isARMArea1Register);
617 emitPushInst(MBB, MI, CSI, PushOpc, false, &isARMArea2Register);
618 emitPushInst(MBB, MI, CSI, FltOpc, true, &isARMArea3Register);
653 emitPushInst(MBB, MI, CSI, PushOpc, PushOneOpc, false, &isARMArea1Register);
654 emitPushInst(MBB, MI, CSI, PushOpc, PushOneOpc, false, &isARMArea2Register);
655 emitPushInst(MBB, MI, CSI, FltOpc, 0, true, &isARMArea3Register);
619656
620657 return true;
621658 }
633670 DebugLoc DL = MI->getDebugLoc();
634671
635672 unsigned PopOpc = AFI->isThumbFunction() ? ARM::t2LDMIA_UPD : ARM::LDMIA_UPD;
673 unsigned LdrOpc = AFI->isThumbFunction() ? ARM::t2LDR_POST : ARM::LDR_POST;
636674 unsigned FltOpc = ARM::VLDMDIA_UPD;
637 emitPopInst(MBB, MI, CSI, FltOpc, isVarArg, true, &isARMArea3Register);
638 emitPopInst(MBB, MI, CSI, PopOpc, isVarArg, false, &isARMArea2Register);
639 emitPopInst(MBB, MI, CSI, PopOpc, isVarArg, false, &isARMArea1Register);
675 emitPopInst(MBB, MI, CSI, FltOpc, 0, isVarArg, true, &isARMArea3Register);
676 emitPopInst(MBB, MI, CSI, PopOpc, LdrOpc, isVarArg, false,
677 &isARMArea2Register);
678 emitPopInst(MBB, MI, CSI, PopOpc, LdrOpc, isVarArg, false,
679 &isARMArea1Register);
640680
641681 return true;
642682 }
5858
5959 private:
6060 void emitPushInst(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
61 const std::vector &CSI, unsigned Opc,
62 bool NoGap, bool(*Func)(unsigned, bool)) const;
61 const std::vector &CSI, unsigned StmOpc,
62 unsigned StrOpc, bool NoGap,
63 bool(*Func)(unsigned, bool)) const;
6364 void emitPopInst(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
64 const std::vector &CSI, unsigned Opc,
65 bool isVarArg, bool NoGap,
65 const std::vector &CSI, unsigned LdmOpc,
66 unsigned LdrOpc, bool isVarArg, bool NoGap,
6667 bool(*Func)(unsigned, bool)) const;
6768 };
6869
33
44 define i64 @t(i64 %a) nounwind readonly {
55 entry:
6 ; CHECK: push {lr}
7 ; CHECK: ldmia sp!, {pc}
6 ; CHECK: str lr, [sp, #-4]!
7 ; CHECK: ldr lr, [sp], #4
88 %0 = load i64** @b, align 4
99 %1 = load i64* %0, align 4
1010 %2 = mul i64 %1, %a
3838 ; CHECK: ittt eq
3939 ; CHECK: moveq r0
4040 ; CHECK-NOT: LBB0_
41 ; CHECK: popeq
41 ; CHECK: ldreq
4242 ; CHECK: popeq
4343 switch i32 undef, label %bb7 [
4444 i32 37, label %bb43