void AVRRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, unsigned FIOperandNum, RegScavenger *RS) const { assert(SPAdj == 0 && "Unexpected SPAdj value"); MachineInstr &MI = *II; DebugLoc dl = MI.getDebugLoc(); MachineBasicBlock &MBB = *MI.getParent(); const MachineFunction &MF = *MBB.getParent(); const AVRTargetMachine &TM = (const AVRTargetMachine &)MF.getTarget(); const TargetInstrInfo &TII = *TM.getSubtargetImpl()->getInstrInfo(); const MachineFrameInfo &MFI = MF.getFrameInfo(); const TargetFrameLowering *TFI = TM.getSubtargetImpl()->getFrameLowering(); int FrameIndex = MI.getOperand(FIOperandNum).getIndex(); int Offset = MFI.getObjectOffset(FrameIndex); // Add one to the offset because SP points to an empty slot. Offset += MFI.getStackSize() - TFI->getOffsetOfLocalArea() + 1; // Fold incoming offset. Offset += MI.getOperand(FIOperandNum + 1).getImm(); // This is actually "load effective address" of the stack slot // instruction. We have only two-address instructions, thus we need to // expand it into move + add. if (MI.getOpcode() == AVR::FRMIDX) { MI.setDesc(TII.get(AVR::MOVWRdRr)); MI.getOperand(FIOperandNum).ChangeToRegister(AVR::R29R28, false); assert(Offset > 0 && "Invalid offset"); // We need to materialize the offset via an add instruction. unsigned Opcode; unsigned DstReg = MI.getOperand(0).getReg(); assert(DstReg != AVR::R29R28 && "Dest reg cannot be the frame pointer"); // Generally, to load a frame address two add instructions are emitted that // could get folded into a single one: // movw r31:r30, r29:r28 // adiw r31:r30, 29 // adiw r31:r30, 16 // to: // movw r31:r30, r29:r28 // adiw r31:r30, 45 foldFrameOffset(*std::next(II), Offset, DstReg); // Select the best opcode based on DstReg and the offset size. switch (DstReg) { case AVR::R25R24: case AVR::R27R26: case AVR::R31R30: { if (isUInt<6>(Offset)) { Opcode = AVR::ADIWRdK; break; } LLVM_FALLTHROUGH; } default: { // This opcode will get expanded into a pair of subi/sbci. Opcode = AVR::SUBIWRdK; Offset = -Offset; break; } } MachineInstr *New = BuildMI(MBB, std::next(II), dl, TII.get(Opcode), DstReg) .addReg(DstReg, RegState::Kill) .addImm(Offset); New->getOperand(3).setIsDead(); return; } // If the offset is too big we have to adjust and restore the frame pointer // to materialize a valid load/store with displacement. //:TODO: consider using only one adiw/sbiw chain for more than one frame index if (Offset > 63) { unsigned AddOpc = AVR::ADIWRdK, SubOpc = AVR::SBIWRdK; int AddOffset = Offset - 63 + 1; // For huge offsets where adiw/sbiw cannot be used use a pair of subi/sbci. if ((Offset - 63 + 1) > 63) { AddOpc = AVR::SUBIWRdK; SubOpc = AVR::SUBIWRdK; AddOffset = -AddOffset; } // It is possible that the spiller places this frame instruction in between // a compare and branch, invalidating the contents of SREG set by the // compare instruction because of the add/sub pairs. Conservatively save and // restore SREG before and after each add/sub pair. BuildMI(MBB, II, dl, TII.get(AVR::INRdA), AVR::R0).addImm(0x3f); MachineInstr *New = BuildMI(MBB, II, dl, TII.get(AddOpc), AVR::R29R28) .addReg(AVR::R29R28, RegState::Kill) .addImm(AddOffset); New->getOperand(3).setIsDead(); // Restore SREG. BuildMI(MBB, std::next(II), dl, TII.get(AVR::OUTARr)) .addImm(0x3f) .addReg(AVR::R0, RegState::Kill); // No need to set SREG as dead here otherwise if the next instruction is a // cond branch it will be using a dead register. New = BuildMI(MBB, std::next(II), dl, TII.get(SubOpc), AVR::R29R28) .addReg(AVR::R29R28, RegState::Kill) .addImm(Offset - 63 + 1); Offset = 62; } MI.getOperand(FIOperandNum).ChangeToRegister(AVR::R29R28, false); assert(isUInt<6>(Offset) && "Offset is out of range"); MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset); }
bool AVRInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl<MachineOperand> &Cond, bool AllowModify) const { // Start from the bottom of the block and work up, examining the // terminator instructions. MachineBasicBlock::iterator I = MBB.end(); MachineBasicBlock::iterator UnCondBrIter = MBB.end(); while (I != MBB.begin()) { --I; if (I->isDebugValue()) { continue; } // Working from the bottom, when we see a non-terminator // instruction, we're done. if (!isUnpredicatedTerminator(*I)) { break; } // A terminator that isn't a branch can't easily be handled // by this analysis. if (!I->getDesc().isBranch()) { return true; } // Handle unconditional branches. //:TODO: add here jmp if (I->getOpcode() == AVR::RJMPk) { UnCondBrIter = I; if (!AllowModify) { TBB = I->getOperand(0).getMBB(); continue; } // If the block has any instructions after a JMP, delete them. while (std::next(I) != MBB.end()) { std::next(I)->eraseFromParent(); } Cond.clear(); FBB = 0; // Delete the JMP if it's equivalent to a fall-through. if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) { TBB = 0; I->eraseFromParent(); I = MBB.end(); UnCondBrIter = MBB.end(); continue; } // TBB is used to indicate the unconditinal destination. TBB = I->getOperand(0).getMBB(); continue; } // Handle conditional branches. AVRCC::CondCodes BranchCode = getCondFromBranchOpc(I->getOpcode()); if (BranchCode == AVRCC::COND_INVALID) { return true; // Can't handle indirect branch. } // Working from the bottom, handle the first conditional branch. if (Cond.empty()) { MachineBasicBlock *TargetBB = I->getOperand(0).getMBB(); if (AllowModify && UnCondBrIter != MBB.end() && MBB.isLayoutSuccessor(TargetBB)) { // If we can modify the code and it ends in something like: // // jCC L1 // jmp L2 // L1: // ... // L2: // // Then we can change this to: // // jnCC L2 // L1: // ... // L2: // // Which is a bit more efficient. // We conditionally jump to the fall-through block. BranchCode = getOppositeCondition(BranchCode); unsigned JNCC = getBrCond(BranchCode).getOpcode(); MachineBasicBlock::iterator OldInst = I; BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), get(JNCC)) .addMBB(UnCondBrIter->getOperand(0).getMBB()); BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), get(AVR::RJMPk)) .addMBB(TargetBB); OldInst->eraseFromParent(); UnCondBrIter->eraseFromParent(); // Restart the analysis. UnCondBrIter = MBB.end(); I = MBB.end(); continue; } FBB = TBB; TBB = I->getOperand(0).getMBB(); Cond.push_back(MachineOperand::CreateImm(BranchCode)); continue; } // Handle subsequent conditional branches. Only handle the case where all // conditional branches branch to the same destination. assert(Cond.size() == 1); assert(TBB); // Only handle the case where all conditional branches branch to // the same destination. if (TBB != I->getOperand(0).getMBB()) { return true; } AVRCC::CondCodes OldBranchCode = (AVRCC::CondCodes)Cond[0].getImm(); // If the conditions are the same, we can leave them alone. if (OldBranchCode == BranchCode) { continue; } return true; } return false; }