[AVR] Use the generic branch relaxer

llvm-svn: 307617
This commit is contained in:
Dylan McKay 2017-07-11 04:17:13 +00:00
parent 510e70fdd5
commit 9cf1dc1e0f
7 changed files with 181 additions and 12 deletions

View File

@ -402,7 +402,7 @@ unsigned AVRInstrInfo::insertBranch(MachineBasicBlock &MBB,
ArrayRef<MachineOperand> Cond,
const DebugLoc &DL,
int *BytesAdded) const {
assert(!BytesAdded && "code size not handled");
if (BytesAdded) *BytesAdded = 0;
// Shouldn't be a fall through.
assert(TBB && "insertBranch must not be told to insert a fallthrough");
@ -411,19 +411,24 @@ unsigned AVRInstrInfo::insertBranch(MachineBasicBlock &MBB,
if (Cond.empty()) {
assert(!FBB && "Unconditional branch with multiple successors!");
BuildMI(&MBB, DL, get(AVR::RJMPk)).addMBB(TBB);
auto &MI = *BuildMI(&MBB, DL, get(AVR::RJMPk)).addMBB(TBB);
if (BytesAdded)
*BytesAdded += getInstSizeInBytes(MI);
return 1;
}
// Conditional branch.
unsigned Count = 0;
AVRCC::CondCodes CC = (AVRCC::CondCodes)Cond[0].getImm();
BuildMI(&MBB, DL, getBrCond(CC)).addMBB(TBB);
auto &CondMI = *BuildMI(&MBB, DL, getBrCond(CC)).addMBB(TBB);
if (BytesAdded) *BytesAdded += getInstSizeInBytes(CondMI);
++Count;
if (FBB) {
// Two-way Conditional branch. Insert the second branch.
BuildMI(&MBB, DL, get(AVR::RJMPk)).addMBB(FBB);
auto &MI = *BuildMI(&MBB, DL, get(AVR::RJMPk)).addMBB(FBB);
if (BytesAdded) *BytesAdded += getInstSizeInBytes(MI);
++Count;
}
@ -432,7 +437,7 @@ unsigned AVRInstrInfo::insertBranch(MachineBasicBlock &MBB,
unsigned AVRInstrInfo::removeBranch(MachineBasicBlock &MBB,
int *BytesRemoved) const {
assert(!BytesRemoved && "code size not handled");
if (BytesRemoved) *BytesRemoved = 0;
MachineBasicBlock::iterator I = MBB.end();
unsigned Count = 0;
@ -450,6 +455,7 @@ unsigned AVRInstrInfo::removeBranch(MachineBasicBlock &MBB,
}
// Remove the branch.
if (BytesRemoved) *BytesRemoved += getInstSizeInBytes(*I);
I->eraseFromParent();
I = MBB.end();
++Count;
@ -494,5 +500,61 @@ unsigned AVRInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
}
}
MachineBasicBlock *
AVRInstrInfo::getBranchDestBlock(const MachineInstr &MI) const {
switch (MI.getOpcode()) {
default:
llvm_unreachable("unexpected opcode!");
case AVR::JMPk:
case AVR::CALLk:
case AVR::RCALLk:
case AVR::RJMPk:
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 MI.getOperand(0).getMBB();
case AVR::BRBSsk:
case AVR::BRBCsk:
return MI.getOperand(1).getMBB();
case AVR::SBRCRrB:
case AVR::SBRSRrB:
case AVR::SBICAb:
case AVR::SBISAb:
llvm_unreachable("unimplemented branch instructions");
}
}
bool AVRInstrInfo::isBranchOffsetInRange(unsigned BranchOp,
int64_t BrOffset) const {
switch (BranchOp) {
default:
llvm_unreachable("unexpected opcode!");
case AVR::JMPk:
case AVR::CALLk:
assert(BrOffset >= 0 && "offset must be absolute address");
return isUIntN(16, BrOffset);
case AVR::RCALLk:
case AVR::RJMPk:
return isIntN(13, BrOffset);
case AVR::BRBSsk:
case AVR::BRBCsk:
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 isIntN(7, BrOffset);
}
}
} // end of namespace llvm

View File

@ -103,6 +103,10 @@ public:
bool
reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const override;
MachineBasicBlock *getBranchDestBlock(const MachineInstr &MI) const override;
bool isBranchOffsetInRange(unsigned BranchOpc,
int64_t BrOffset) const override;
private:
const AVRRegisterInfo RI;
};

View File

@ -66,6 +66,7 @@ public:
bool addInstSelector() override;
void addPreSched2() override;
void addPreEmitPass() override;
void addPreRegAlloc() override;
};
} // namespace
@ -115,4 +116,9 @@ void AVRPassConfig::addPreSched2() {
addPass(createAVRExpandPseudoPass());
}
void AVRPassConfig::addPreEmitPass() {
// Must run branch selection immediately preceding the asm printer.
addPass(&BranchRelaxationPassID);
}
} // end of namespace llvm

View File

@ -0,0 +1,96 @@
; RUN: llc < %s -march=avr | FileCheck %s
; CHECKC-LABEL: relax_breq
; CHECK: cpi r{{[0-9]+}}, 0
; CHECK: brne LBB0_1
; CHECK: rjmp LBB0_2
; LBB0_1:
define i8 @relax_breq(i1 %a) {
entry-block:
br i1 %a, label %hello, label %finished
hello:
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
br label %finished
finished:
ret i8 3
}
; CHECKC-LABEL: no_relax_breq
; CHECK: cpi r{{[0-9]+}}, 0
; CHECK: breq [[END_BB:LBB[0-9]+_[0-9]+]]
; CHECK: nop
; ...
; LBB0_1:
define i8 @no_relax_breq(i1 %a) {
entry-block:
br i1 %a, label %hello, label %finished
hello:
; There are not enough NOPs to require relaxation.
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
br label %finished
finished:
ret i8 3
}

View File

@ -10,7 +10,8 @@ declare i8 @llvm.ctlz.i8(i8)
; CHECK-LABEL: count_leading_zeros:
; CHECK: cpi [[RESULT:r[0-9]+]], 0
; CHECK: breq LBB0_1
; CHECK: brne LBB0_1
; CHECK: rjmp LBB0_2
; CHECK: mov [[SCRATCH:r[0-9]+]], {{.*}}[[RESULT]]
; CHECK: lsr {{.*}}[[SCRATCH]]
; CHECK: or {{.*}}[[SCRATCH]], {{.*}}[[RESULT]]
@ -43,6 +44,6 @@ declare i8 @llvm.ctlz.i8(i8)
; CHECK: add {{.*}}[[RESULT]], {{.*}}[[SCRATCH]]
; CHECK: andi {{.*}}[[RESULT]], 15
; CHECK: ret
; CHECK: LBB0_1:
; CHECK: LBB0_2:
; CHECK: ldi {{.*}}[[RESULT]], 8
; CHECK: ret

View File

@ -10,7 +10,7 @@ declare i8 @llvm.cttz.i8(i8)
; CHECK-LABEL: count_trailing_zeros:
; CHECK: cpi [[RESULT:r[0-9]+]], 0
; CHECK: breq LBB0_1
; CHECK: breq [[END_BB:LBB[0-9]+_[0-9]+]]
; CHECK: mov [[SCRATCH:r[0-9]+]], {{.*}}[[RESULT]]
; CHECK: dec {{.*}}[[SCRATCH]]
; CHECK: com {{.*}}[[RESULT]]
@ -34,7 +34,7 @@ declare i8 @llvm.cttz.i8(i8)
; CHECK: andi {{.*}}[[SCRATCH]], 15
; CHECK: mov {{.*}}[[RESULT]], {{.*}}[[SCRATCH]]
; CHECK: ret
; CHECK: LBB0_1:
; CHECK: [[END_BB]]:
; CHECK: ldi {{.*}}[[SCRATCH]], 8
; CHECK: mov {{.*}}[[RESULT]], {{.*}}[[SCRATCH]]
; CHECK: ret

View File

@ -8,9 +8,9 @@ define internal fastcc void @loopy() {
;
; https://github.com/avr-rust/rust/issues/49
; CHECK: LBB0_1:
; CHECK: LBB0_2:
; CHECK-NOT: LBB0_3:
; CHECK: LBB0_{{[0-9]+}}:
; CHECK: LBB0_{{[0-9]+}}:
; CHECK-NOT: LBB0_{{[0-9]+}}:
start:
br label %bb7.preheader