forked from OSchip/llvm-project
parent
510e70fdd5
commit
9cf1dc1e0f
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue