mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
Revert "[AVR] Add the branch selection pass from the GitHub repository"
This reverts commit 602ef067c1d58ecb425d061f35f2bc4c7e92f4f3. llvm-svn: 307111
This commit is contained in:
parent
590d049bd1
commit
4df9fae587
@ -1,262 +0,0 @@
|
|||||||
//===-- AVRBranchSelector.cpp - Emit long conditional branches ------------===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This file contains a pass that scans a machine function to determine which
|
|
||||||
// conditional branches need more than 8 bits of displacement to reach their
|
|
||||||
// target basic block. It does this in two passes; a calculation of basic block
|
|
||||||
// positions pass, and a branch pseudo op to machine branch opcode pass. This
|
|
||||||
// pass should be run last, just before the assembly printer.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#include "AVR.h"
|
|
||||||
|
|
||||||
#include "llvm/ADT/Statistic.h"
|
|
||||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
|
||||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
|
||||||
|
|
||||||
#include "AVRInstrInfo.h"
|
|
||||||
#include "AVRTargetMachine.h"
|
|
||||||
#include "MCTargetDesc/AVRMCTargetDesc.h"
|
|
||||||
|
|
||||||
#define DEBUG_TYPE "avr-branch-select"
|
|
||||||
|
|
||||||
STATISTIC(NumExpanded, "Number of branches expanded to long format");
|
|
||||||
|
|
||||||
namespace llvm {
|
|
||||||
|
|
||||||
/// Ensures branch targets can fit inside the instruction
|
|
||||||
/// they reside in.
|
|
||||||
///
|
|
||||||
/// If a branch target is too large for the instruction it
|
|
||||||
/// is being used with, this pass replaces it with a larger,
|
|
||||||
/// equivalent instruction which can fit the target.
|
|
||||||
class AVRBSel : public MachineFunctionPass {
|
|
||||||
public:
|
|
||||||
static char ID;
|
|
||||||
|
|
||||||
explicit AVRBSel() : MachineFunctionPass(ID) {}
|
|
||||||
|
|
||||||
bool runOnMachineFunction(MachineFunction &MF) override;
|
|
||||||
|
|
||||||
StringRef getPassName() const override { return "AVR Branch Selector"; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
/// Measure and sum the size of all basic blocks in a function.
|
|
||||||
unsigned calculateFunctionSize(const MachineFunction &MF);
|
|
||||||
|
|
||||||
private:
|
|
||||||
/// The sizes of the basic blocks in the function.
|
|
||||||
std::vector<unsigned> BlockSizes;
|
|
||||||
};
|
|
||||||
|
|
||||||
char AVRBSel::ID = 0;
|
|
||||||
|
|
||||||
/// Checks whether the passed opcode is a conditional branch.
|
|
||||||
static bool isConditionalBranch(int Opcode) {
|
|
||||||
switch (Opcode) {
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
case AVR::BREQk:
|
|
||||||
case AVR::BRNEk:
|
|
||||||
case AVR::BRSHk:
|
|
||||||
case AVR::BRLOk:
|
|
||||||
case AVR::BRMIk:
|
|
||||||
case AVR::BRPLk:
|
|
||||||
case AVR::BRGEk:
|
|
||||||
case AVR::BRLTk:
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned AVRBSel::calculateFunctionSize(const MachineFunction &MF) {
|
|
||||||
const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>();
|
|
||||||
const AVRInstrInfo &TII = *STI.getInstrInfo();
|
|
||||||
|
|
||||||
unsigned FuncSize = 0;
|
|
||||||
|
|
||||||
for (const MachineBasicBlock &MBB : MF) {
|
|
||||||
unsigned BlockSize = 0;
|
|
||||||
|
|
||||||
for (const MachineInstr &MI : MBB) {
|
|
||||||
BlockSize += TII.getInstSizeInBytes(MI);
|
|
||||||
}
|
|
||||||
|
|
||||||
BlockSizes[MBB.getNumber()] = BlockSize;
|
|
||||||
FuncSize += BlockSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(FuncSize % 2 == 0 && "function should have an even number of bytes");
|
|
||||||
|
|
||||||
return FuncSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AVRBSel::runOnMachineFunction(MachineFunction &MF) {
|
|
||||||
const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>();
|
|
||||||
const AVRInstrInfo &TII = *STI.getInstrInfo();
|
|
||||||
|
|
||||||
// Give the blocks of the function a dense, in-order, numbering.
|
|
||||||
MF.RenumberBlocks();
|
|
||||||
BlockSizes.resize(MF.getNumBlockIDs());
|
|
||||||
|
|
||||||
unsigned FuncSize = calculateFunctionSize(MF);
|
|
||||||
|
|
||||||
// If the entire function is smaller than the displacement of a branch field,
|
|
||||||
// we know we don't need to shrink any branches in this function. This is a
|
|
||||||
// common case.
|
|
||||||
if (isUInt<7>(FuncSize)) {
|
|
||||||
BlockSizes.clear();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// For each conditional branch, if the offset to its destination is larger
|
|
||||||
// than the offset field allows, transform it into a long or a huge branch
|
|
||||||
// sequence like this:
|
|
||||||
// -short branch:
|
|
||||||
// brCC MBB
|
|
||||||
// -long branch:
|
|
||||||
// br!CC $PC+2
|
|
||||||
// rjmp MBB
|
|
||||||
// -huge branch:
|
|
||||||
// br!CC $PC+4
|
|
||||||
// jmp MBB
|
|
||||||
bool MadeChange = true;
|
|
||||||
while (MadeChange) {
|
|
||||||
// Iteratively expand branches until we reach a fixed point.
|
|
||||||
MadeChange = false;
|
|
||||||
|
|
||||||
for (MachineBasicBlock &MBB : MF) {
|
|
||||||
unsigned MBBStartOffset = 0;
|
|
||||||
|
|
||||||
for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E;
|
|
||||||
++I) {
|
|
||||||
int Opc = I->getOpcode();
|
|
||||||
if ((!isConditionalBranch(Opc) || I->getOperand(0).isImm()) &&
|
|
||||||
(Opc != AVR::RJMPk)) {
|
|
||||||
MBBStartOffset += TII.getInstSizeInBytes(*I);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine the offset from the current branch to the destination
|
|
||||||
// block.
|
|
||||||
MachineBasicBlock &Dest = *I->getOperand(0).getMBB();
|
|
||||||
|
|
||||||
assert(Dest.getNumber() >= 0 &&
|
|
||||||
"Destination basic block isn't in a function");
|
|
||||||
|
|
||||||
int BranchSize;
|
|
||||||
if (Dest.getNumber() <= MBB.getNumber()) {
|
|
||||||
// If this is a backwards branch, the delta is the offset from the
|
|
||||||
// start of this block to this branch, plus the sizes of all blocks
|
|
||||||
// from this block to the dest.
|
|
||||||
BranchSize = MBBStartOffset;
|
|
||||||
|
|
||||||
for (unsigned i = Dest.getNumber(), e = MBB.getNumber(); i != e;
|
|
||||||
++i) {
|
|
||||||
BranchSize += BlockSizes[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the size of backwards branches to a negative value.
|
|
||||||
BranchSize = -BranchSize;
|
|
||||||
} else {
|
|
||||||
// Otherwise, add the size of the blocks between this block and the
|
|
||||||
// dest to the number of bytes left in this block.
|
|
||||||
BranchSize = -MBBStartOffset;
|
|
||||||
|
|
||||||
for (unsigned i = MBB.getNumber(), e = Dest.getNumber(); i != e;
|
|
||||||
++i) {
|
|
||||||
BranchSize += BlockSizes[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isConditionalBranch(Opc))
|
|
||||||
BranchSize -= 2; // take the size of the current instruction.
|
|
||||||
|
|
||||||
assert(BranchSize % 2 == 0 &&
|
|
||||||
"BranchSize should have an even number of bytes");
|
|
||||||
|
|
||||||
// If this branch is in range, ignore it.
|
|
||||||
if ((isConditionalBranch(Opc) && isInt<8>(BranchSize)) ||
|
|
||||||
(Opc == AVR::RJMPk && isInt<13>(BranchSize))) {
|
|
||||||
MBBStartOffset += 2;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, we have to expand it to a long branch.
|
|
||||||
unsigned NewSize;
|
|
||||||
int UncondOpc;
|
|
||||||
MachineInstr &OldBranch = *I;
|
|
||||||
DebugLoc DL = OldBranch.getDebugLoc();
|
|
||||||
|
|
||||||
if (Opc == AVR::RJMPk) {
|
|
||||||
// Replace this instruction with a jmp which has a size of 4 bytes.
|
|
||||||
NewSize = 4;
|
|
||||||
UncondOpc = AVR::JMPk;
|
|
||||||
|
|
||||||
// We may be converting a conditional long jump to a huge one, if this
|
|
||||||
// is the case, update the $PC+2 operand in brCC to $PC+4.
|
|
||||||
// Skip the check when this instruction is the first inside the BB.
|
|
||||||
if (I != MBB.begin()) {
|
|
||||||
MachineInstr &PI = *std::prev(I);
|
|
||||||
|
|
||||||
if (isConditionalBranch(PI.getOpcode()) &&
|
|
||||||
PI.getOperand(0).isImm() &&
|
|
||||||
PI.getOperand(0).getImm() == 2) {
|
|
||||||
PI.getOperand(0).setImm(4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
assert(isConditionalBranch(Opc) &&
|
|
||||||
"opcode should be a conditional branch");
|
|
||||||
|
|
||||||
unsigned BrCCOffs;
|
|
||||||
// Determine if we can reach the destination block with a rjmp,
|
|
||||||
// otherwise a jmp instruction is needed.
|
|
||||||
if (isInt<13>(BranchSize)) {
|
|
||||||
NewSize = 4;
|
|
||||||
BrCCOffs = 2;
|
|
||||||
UncondOpc = AVR::RJMPk;
|
|
||||||
} else {
|
|
||||||
NewSize = 6;
|
|
||||||
BrCCOffs = 4;
|
|
||||||
UncondOpc = AVR::JMPk;
|
|
||||||
}
|
|
||||||
|
|
||||||
AVRCC::CondCodes OCC =
|
|
||||||
TII.getOppositeCondition(TII.getCondFromBranchOpc(Opc));
|
|
||||||
// Jump over the uncond branch inst (i.e. $+2) on opposite condition.
|
|
||||||
BuildMI(MBB, I, DL, TII.getBrCond(OCC)).addImm(BrCCOffs);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uncond branch to the real destination.
|
|
||||||
I = BuildMI(MBB, I, DL, TII.get(UncondOpc)).addMBB(&Dest);
|
|
||||||
|
|
||||||
// Remove the old branch from the function.
|
|
||||||
OldBranch.eraseFromParent();
|
|
||||||
|
|
||||||
// Remember that this instruction is NewSize bytes, increase the size of
|
|
||||||
// the block by NewSize-2, remember to iterate.
|
|
||||||
BlockSizes[MBB.getNumber()] += NewSize - 2;
|
|
||||||
MBBStartOffset += NewSize;
|
|
||||||
|
|
||||||
++NumExpanded;
|
|
||||||
MadeChange = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BlockSizes.clear();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
FunctionPass *createAVRBranchSelectionPass() { return new AVRBSel(); }
|
|
||||||
|
|
||||||
} // end of namespace llvm
|
|
||||||
|
|
@ -67,7 +67,6 @@ public:
|
|||||||
bool addInstSelector() override;
|
bool addInstSelector() override;
|
||||||
void addPreSched2() override;
|
void addPreSched2() override;
|
||||||
void addPreRegAlloc() override;
|
void addPreRegAlloc() override;
|
||||||
void addPreEmitPass() override;
|
|
||||||
};
|
};
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
@ -116,9 +115,4 @@ void AVRPassConfig::addPreSched2() {
|
|||||||
addPass(createAVRExpandPseudoPass());
|
addPass(createAVRExpandPseudoPass());
|
||||||
}
|
}
|
||||||
|
|
||||||
void AVRPassConfig::addPreEmitPass() {
|
|
||||||
// Must run branch selection immediately preceding the asm printer.
|
|
||||||
addPass(createAVRBranchSelectionPass());
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end of namespace llvm
|
} // end of namespace llvm
|
||||||
|
@ -18,7 +18,6 @@ add_public_tablegen_target(AVRCommonTableGen)
|
|||||||
|
|
||||||
add_llvm_target(AVRCodeGen
|
add_llvm_target(AVRCodeGen
|
||||||
AVRAsmPrinter.cpp
|
AVRAsmPrinter.cpp
|
||||||
AVRBranchSelector.cpp
|
|
||||||
AVRExpandPseudoInsts.cpp
|
AVRExpandPseudoInsts.cpp
|
||||||
AVRFrameLowering.cpp
|
AVRFrameLowering.cpp
|
||||||
AVRInstrInfo.cpp
|
AVRInstrInfo.cpp
|
||||||
|
@ -10,7 +10,7 @@ declare i8 @llvm.ctlz.i8(i8)
|
|||||||
|
|
||||||
; CHECK-LABEL: count_leading_zeros:
|
; CHECK-LABEL: count_leading_zeros:
|
||||||
; CHECK: cpi [[RESULT:r[0-9]+]], 0
|
; CHECK: cpi [[RESULT:r[0-9]+]], 0
|
||||||
; CHECK: breq LBB0_2
|
; CHECK: breq LBB0_1
|
||||||
; CHECK: mov [[SCRATCH:r[0-9]+]], {{.*}}[[RESULT]]
|
; CHECK: mov [[SCRATCH:r[0-9]+]], {{.*}}[[RESULT]]
|
||||||
; CHECK: lsr {{.*}}[[SCRATCH]]
|
; CHECK: lsr {{.*}}[[SCRATCH]]
|
||||||
; CHECK: or {{.*}}[[SCRATCH]], {{.*}}[[RESULT]]
|
; CHECK: or {{.*}}[[SCRATCH]], {{.*}}[[RESULT]]
|
||||||
@ -43,6 +43,6 @@ declare i8 @llvm.ctlz.i8(i8)
|
|||||||
; CHECK: add {{.*}}[[RESULT]], {{.*}}[[SCRATCH]]
|
; CHECK: add {{.*}}[[RESULT]], {{.*}}[[SCRATCH]]
|
||||||
; CHECK: andi {{.*}}[[RESULT]], 15
|
; CHECK: andi {{.*}}[[RESULT]], 15
|
||||||
; CHECK: ret
|
; CHECK: ret
|
||||||
; CHECK: LBB0_2:
|
; CHECK: LBB0_1:
|
||||||
; CHECK: ldi {{.*}}[[RESULT]], 8
|
; CHECK: ldi {{.*}}[[RESULT]], 8
|
||||||
; CHECK: ret
|
; CHECK: ret
|
||||||
|
@ -10,7 +10,7 @@ declare i8 @llvm.cttz.i8(i8)
|
|||||||
|
|
||||||
; CHECK-LABEL: count_trailing_zeros:
|
; CHECK-LABEL: count_trailing_zeros:
|
||||||
; CHECK: cpi [[RESULT:r[0-9]+]], 0
|
; CHECK: cpi [[RESULT:r[0-9]+]], 0
|
||||||
; CHECK: breq LBB0_2
|
; CHECK: breq LBB0_1
|
||||||
; CHECK: mov [[SCRATCH:r[0-9]+]], {{.*}}[[RESULT]]
|
; CHECK: mov [[SCRATCH:r[0-9]+]], {{.*}}[[RESULT]]
|
||||||
; CHECK: dec {{.*}}[[SCRATCH]]
|
; CHECK: dec {{.*}}[[SCRATCH]]
|
||||||
; CHECK: com {{.*}}[[RESULT]]
|
; CHECK: com {{.*}}[[RESULT]]
|
||||||
@ -34,7 +34,7 @@ declare i8 @llvm.cttz.i8(i8)
|
|||||||
; CHECK: andi {{.*}}[[SCRATCH]], 15
|
; CHECK: andi {{.*}}[[SCRATCH]], 15
|
||||||
; CHECK: mov {{.*}}[[RESULT]], {{.*}}[[SCRATCH]]
|
; CHECK: mov {{.*}}[[RESULT]], {{.*}}[[SCRATCH]]
|
||||||
; CHECK: ret
|
; CHECK: ret
|
||||||
; CHECK: LBB0_2:
|
; CHECK: LBB0_1:
|
||||||
; CHECK: ldi {{.*}}[[SCRATCH]], 8
|
; CHECK: ldi {{.*}}[[SCRATCH]], 8
|
||||||
; CHECK: mov {{.*}}[[RESULT]], {{.*}}[[SCRATCH]]
|
; CHECK: mov {{.*}}[[RESULT]], {{.*}}[[SCRATCH]]
|
||||||
; CHECK: ret
|
; CHECK: ret
|
||||||
|
@ -8,9 +8,9 @@ define internal fastcc void @loopy() {
|
|||||||
;
|
;
|
||||||
; https://github.com/avr-rust/rust/issues/49
|
; https://github.com/avr-rust/rust/issues/49
|
||||||
|
|
||||||
; CHECK: LBB0_{{[0-9]+}}:
|
; CHECK: LBB0_1:
|
||||||
; CHECK: LBB0_{{[0-9]+}}:
|
; CHECK: LBB0_2:
|
||||||
; CHECK-NOT: LBB0_{{[0-9]+}}:
|
; CHECK-NOT: LBB0_3:
|
||||||
start:
|
start:
|
||||||
br label %bb7.preheader
|
br label %bb7.preheader
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user