diff options
author | Venkatraman Govindaraju <venkatra@cs.wisc.edu> | 2013-06-02 21:48:17 +0000 |
---|---|---|
committer | Venkatraman Govindaraju <venkatra@cs.wisc.edu> | 2013-06-02 21:48:17 +0000 |
commit | 65ca7aa57d5e9b391f02a5686e7622deaac146f9 (patch) | |
tree | 9517c1fe25c819c191102a54d662f3be194bc7f2 /lib | |
parent | 0a972fa1ef70c0523091732d41f35f660f97e107 (diff) | |
download | external_llvm-65ca7aa57d5e9b391f02a5686e7622deaac146f9.zip external_llvm-65ca7aa57d5e9b391f02a5686e7622deaac146f9.tar.gz external_llvm-65ca7aa57d5e9b391f02a5686e7622deaac146f9.tar.bz2 |
Sparc: Combine add/or/sethi instruction with restore if possible.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@183088 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Target/Sparc/DelaySlotFiller.cpp | 199 |
1 files changed, 177 insertions, 22 deletions
diff --git a/lib/Target/Sparc/DelaySlotFiller.cpp b/lib/Target/Sparc/DelaySlotFiller.cpp index 9961232..271c630 100644 --- a/lib/Target/Sparc/DelaySlotFiller.cpp +++ b/lib/Target/Sparc/DelaySlotFiller.cpp @@ -82,6 +82,9 @@ namespace { bool needsUnimp(MachineBasicBlock::iterator I, unsigned &StructSize); + bool tryCombineRestoreWithPrevInst(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI); + }; char Filler::ID = 0; } // end of anonymous namespace @@ -100,29 +103,44 @@ FunctionPass *llvm::createSparcDelaySlotFillerPass(TargetMachine &tm) { bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) { bool Changed = false; - for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) - if (I->hasDelaySlot()) { - MachineBasicBlock::iterator D = MBB.end(); - MachineBasicBlock::iterator J = I; - - if (!DisableDelaySlotFiller) - D = findDelayInstr(MBB, I); - - ++FilledSlots; - Changed = true; - - if (D == MBB.end()) - BuildMI(MBB, ++J, I->getDebugLoc(), TII->get(SP::NOP)); - else - MBB.splice(++J, &MBB, D); - unsigned structSize = 0; - if (needsUnimp(I, structSize)) { - MachineBasicBlock::iterator J = I; - ++J; //skip the delay filler. - BuildMI(MBB, ++J, I->getDebugLoc(), - TII->get(SP::UNIMP)).addImm(structSize); - } + for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ) { + MachineBasicBlock::iterator MI = I; + ++I; + + //If MI is restore, try combining it with previous inst. + if (!DisableDelaySlotFiller && + (MI->getOpcode() == SP::RESTORErr + || MI->getOpcode() == SP::RESTOREri)) { + Changed |= tryCombineRestoreWithPrevInst(MBB, MI); + continue; + } + + //If MI has no delay slot, skip + if (!MI->hasDelaySlot()) + continue; + + MachineBasicBlock::iterator D = MBB.end(); + + if (!DisableDelaySlotFiller) + D = findDelayInstr(MBB, MI); + + ++FilledSlots; + Changed = true; + + if (D == MBB.end()) + BuildMI(MBB, I, MI->getDebugLoc(), TII->get(SP::NOP)); + else + MBB.splice(I, &MBB, D); + + unsigned structSize = 0; + if (needsUnimp(MI, structSize)) { + MachineBasicBlock::iterator J = MI; + ++J; //skip the delay filler. + assert (J != MBB.end() && "MI needs a delay instruction."); + BuildMI(MBB, ++J, I->getDebugLoc(), + TII->get(SP::UNIMP)).addImm(structSize); } + } return Changed; } @@ -332,3 +350,140 @@ bool Filler::needsUnimp(MachineBasicBlock::iterator I, unsigned &StructSize) StructSize = MO.getImm(); return true; } + +static bool combineRestoreADD(MachineBasicBlock::iterator RestoreMI, + MachineBasicBlock::iterator AddMI, + const TargetInstrInfo *TII) +{ + //Before: add <op0>, <op1>, %i[0-7] + // restore %g0, %g0, %i[0-7] + // + //After : restore <op0>, <op1>, %o[0-7] + + unsigned reg = AddMI->getOperand(0).getReg(); + if (reg < SP::I0 || reg > SP::I7) + return false; + + //Erase RESTORE + RestoreMI->eraseFromParent(); + + //Change ADD to RESTORE + AddMI->setDesc(TII->get((AddMI->getOpcode() == SP::ADDrr) + ? SP::RESTORErr + : SP::RESTOREri)); + + //map the destination register + AddMI->getOperand(0).setReg(reg - SP::I0 + SP::O0); + + return true; +} + +static bool combineRestoreOR(MachineBasicBlock::iterator RestoreMI, + MachineBasicBlock::iterator OrMI, + const TargetInstrInfo *TII) +{ + //Before: or <op0>, <op1>, %i[0-7] + // restore %g0, %g0, %i[0-7] + // and <op0> or <op1> is zero, + // + //After : restore <op0>, <op1>, %o[0-7] + + unsigned reg = OrMI->getOperand(0).getReg(); + if (reg < SP::I0 || reg > SP::I7) + return false; + + //check whether it is a copy + if (OrMI->getOpcode() == SP::ORrr + && OrMI->getOperand(1).getReg() != SP::G0 + && OrMI->getOperand(2).getReg() != SP::G0) + return false; + + if (OrMI->getOpcode() == SP::ORri + && OrMI->getOperand(1).getReg() != SP::G0 + && (!OrMI->getOperand(2).isImm() || OrMI->getOperand(2).getImm() != 0)) + return false; + + //Erase RESTORE + RestoreMI->eraseFromParent(); + + //Change OR to RESTORE + OrMI->setDesc(TII->get((OrMI->getOpcode() == SP::ORrr) + ? SP::RESTORErr + : SP::RESTOREri)); + + //map the destination register + OrMI->getOperand(0).setReg(reg - SP::I0 + SP::O0); + + return true; +} + +static bool combineRestoreSETHIi(MachineBasicBlock::iterator RestoreMI, + MachineBasicBlock::iterator SetHiMI, + const TargetInstrInfo *TII) +{ + //Before: sethi imm3, %i[0-7] + // restore %g0, %g0, %g0 + // + //After : restore %g0, (imm3<<10), %o[0-7] + + unsigned reg = SetHiMI->getOperand(0).getReg(); + if (reg < SP::I0 || reg > SP::I7) + return false; + + if (!SetHiMI->getOperand(1).isImm()) + return false; + + int64_t imm = SetHiMI->getOperand(1).getImm(); + + //is it a 3 bit immediate? + if (!isInt<3>(imm)) + return false; + + //make it a 13 bit immediate + imm = (imm << 10) & 0x1FFF; + + assert(RestoreMI->getOpcode() == SP::RESTORErr); + + RestoreMI->setDesc(TII->get(SP::RESTOREri)); + + RestoreMI->getOperand(0).setReg(reg - SP::I0 + SP::O0); + RestoreMI->getOperand(1).setReg(SP::G0); + RestoreMI->getOperand(2).ChangeToImmediate(imm); + + + //Erase the original SETHI + SetHiMI->eraseFromParent(); + + return true; +} + +bool Filler::tryCombineRestoreWithPrevInst(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI) +{ + //No previous instruction + if (MBBI == MBB.begin()) + return false; + + //asssert that MBBI is "restore %g0, %g0, %g0" + assert(MBBI->getOpcode() == SP::RESTORErr + && MBBI->getOperand(0).getReg() == SP::G0 + && MBBI->getOperand(1).getReg() == SP::G0 + && MBBI->getOperand(2).getReg() == SP::G0); + + MachineBasicBlock::iterator PrevInst = MBBI; --PrevInst; + + //Cannot combine with a delay filler + if (isDelayFiller(MBB, PrevInst)) + return false; + + switch (PrevInst->getOpcode()) { + default: break; + case SP::ADDrr: + case SP::ADDri: return combineRestoreADD(MBBI, PrevInst, TII); break; + case SP::ORrr: + case SP::ORri: return combineRestoreOR(MBBI, PrevInst, TII); break; + case SP::SETHIi: return combineRestoreSETHIi(MBBI, PrevInst, TII); break; + } + //Cannot combine with the previous instruction + return false; +} |