diff options
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r-- | llvm/lib/Target/ARM/ARMBasicBlockInfo.h | 4 | ||||
-rw-r--r-- | llvm/lib/Target/ARM/ARMISelLowering.cpp | 20 | ||||
-rw-r--r-- | llvm/lib/Target/ARM/ARMLowOverheadLoops.cpp | 16 |
3 files changed, 29 insertions, 11 deletions
diff --git a/llvm/lib/Target/ARM/ARMBasicBlockInfo.h b/llvm/lib/Target/ARM/ARMBasicBlockInfo.h index d969a6f6d57..400bba351ce 100644 --- a/llvm/lib/Target/ARM/ARMBasicBlockInfo.h +++ b/llvm/lib/Target/ARM/ARMBasicBlockInfo.h @@ -132,6 +132,10 @@ public: unsigned getOffsetOf(MachineInstr *MI) const; + unsigned getOffsetOf(MachineBasicBlock *MBB) const { + return BBInfo[MBB->getNumber()].Offset; + } + void adjustBBOffsetsAfter(MachineBasicBlock *MBB); void adjustBBSize(MachineBasicBlock *MBB, int Size) { diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp index 36b669b8526..dd11ed6ede7 100644 --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -12989,22 +12989,26 @@ static SDValue PerformHWLoopCombine(SDNode *N, const ARMSubtarget *ST) { // Look for (brcond (xor test.set.loop.iterations, -1) SDValue CC = N->getOperand(1); + unsigned Opc = CC->getOpcode(); + SDValue Int; - if (CC->getOpcode() != ISD::XOR && CC->getOpcode() != ISD::SETCC) - return SDValue(); + if ((Opc == ISD::XOR || Opc == ISD::SETCC) && + (CC->getOperand(0)->getOpcode() == ISD::INTRINSIC_W_CHAIN)) { + + assert((isa<ConstantSDNode>(CC->getOperand(1)) && + cast<ConstantSDNode>(CC->getOperand(1))->isOne()) && + "Expected to compare against 1"); - if (CC->getOperand(0)->getOpcode() != ISD::INTRINSIC_W_CHAIN) + Int = CC->getOperand(0); + } else if (CC->getOpcode() == ISD::INTRINSIC_W_CHAIN) + Int = CC; + else return SDValue(); - SDValue Int = CC->getOperand(0); unsigned IntOp = cast<ConstantSDNode>(Int.getOperand(1))->getZExtValue(); if (IntOp != Intrinsic::test_set_loop_iterations) return SDValue(); - assert((isa<ConstantSDNode>(CC->getOperand(1)) && - cast<ConstantSDNode>(CC->getOperand(1))->isOne()) && - "Expected to compare against 1"); - SDLoc dl(Int); SDValue Chain = N->getOperand(0); SDValue Elements = Int.getOperand(2); diff --git a/llvm/lib/Target/ARM/ARMLowOverheadLoops.cpp b/llvm/lib/Target/ARM/ARMLowOverheadLoops.cpp index a790ab0f852..cedf3bd3c74 100644 --- a/llvm/lib/Target/ARM/ARMLowOverheadLoops.cpp +++ b/llvm/lib/Target/ARM/ARMLowOverheadLoops.cpp @@ -91,6 +91,7 @@ bool ARMLowOverheadLoops::runOnMachineFunction(MachineFunction &MF) { MF.getSubtarget().getInstrInfo()); BBUtils = std::unique_ptr<ARMBasicBlockUtils>(new ARMBasicBlockUtils(MF)); BBUtils->computeAllBlockSizes(); + BBUtils->adjustBBOffsetsAfter(&MF.front()); bool Changed = false; for (auto ML : MLI) { @@ -200,9 +201,18 @@ bool ARMLowOverheadLoops::ProcessLoop(MachineLoop *ML) { End->getOperand(1).getMBB() != ML->getHeader()) report_fatal_error("Expected LoopEnd to target Loop Header"); - // The LE instructions has 12-bits for the label offset. - if (!BBUtils->isBBInRange(End, ML->getHeader(), 4096)) { - LLVM_DEBUG(dbgs() << "ARM Loops: Too large for a low-overhead loop!\n"); + // The WLS and LE instructions have 12-bits for the label offset. WLS + // requires a positive offset, while LE uses negative. + if (BBUtils->getOffsetOf(End) < BBUtils->getOffsetOf(ML->getHeader()) || + !BBUtils->isBBInRange(End, ML->getHeader(), 4094)) { + LLVM_DEBUG(dbgs() << "ARM Loops: LE offset is out-of-range\n"); + Revert = true; + } + if (Start->getOpcode() == ARM::t2WhileLoopStart && + (BBUtils->getOffsetOf(Start) > + BBUtils->getOffsetOf(Start->getOperand(1).getMBB()) || + !BBUtils->isBBInRange(Start, Start->getOperand(1).getMBB(), 4094))) { + LLVM_DEBUG(dbgs() << "ARM Loops: WLS offset is out-of-range!\n"); Revert = true; } |