Commit 13f0ca32 by Jaydeep Patil Committed by Jim Stichnoth

Delete unconditional branch to the next node.

R=stichnot@chromium.org Review URL: https://codereview.chromium.org/2275883002 . Patch from Jaydeep Patil <jaydeep.patil@imgtec.com>.
parent 519fe047
......@@ -200,6 +200,46 @@ InstMIPS32Br::InstMIPS32Br(Cfg *Func, const CfgNode *TargetTrue,
addSource(Src1);
}
CondMIPS32::Cond InstMIPS32::getOppositeCondition(CondMIPS32::Cond Cond) {
return InstMIPS32CondAttributes[Cond].Opposite;
}
bool InstMIPS32Br::optimizeBranch(const CfgNode *NextNode) {
// If there is no next block, then there can be no fallthrough to optimize.
if (NextNode == nullptr)
return false;
// Intra-block conditional branches can't be optimized.
if (Label != nullptr)
return false;
// Unconditional branch to the next node can be removed.
if (isUnconditionalBranch() && getTargetFalse() == NextNode) {
assert(getTargetTrue() == nullptr);
setDeleted();
return true;
}
// If there is no fallthrough node, such as a non-default case label for a
// switch instruction, then there is no opportunity to optimize.
if (getTargetTrue() == nullptr)
return false;
// If the fallthrough is to the next node, set fallthrough to nullptr to
// indicate.
if (getTargetTrue() == NextNode) {
TargetTrue = nullptr;
return true;
}
// If TargetFalse is the next node, and TargetTrue is not nullptr
// then invert the branch condition, swap the targets, and set new
// fallthrough to nullptr.
if (getTargetFalse() == NextNode) {
assert(Predicate != CondMIPS32::AL);
setPredicate(getOppositeCondition(getPredicate()));
TargetFalse = getTargetTrue();
TargetTrue = nullptr;
return true;
}
return false;
}
bool InstMIPS32Br::repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
bool Found = false;
if (TargetFalse == OldNode) {
......@@ -419,6 +459,11 @@ void InstMIPS32Br::emit(const Cfg *Func) const {
}
}
Str << getTargetFalse()->getAsmName();
if (getTargetTrue()) {
Str << "\n\t"
<< "b"
<< "\t" << getTargetTrue()->getAsmName();
}
}
}
}
......@@ -439,6 +484,11 @@ void InstMIPS32Br::dump(const Cfg *Func) const {
dumpSources(Func);
Str << ", ";
Str << getTargetFalse()->getAsmName();
if (getTargetTrue()) {
Str << "\n\t"
<< "b"
<< "\t" << getTargetTrue()->getAsmName();
}
}
}
}
......
......@@ -201,6 +201,8 @@ public:
static const char *getWidthString(Type Ty);
CondMIPS32::Cond getOppositeCondition(CondMIPS32::Cond Cond);
void dump(const Cfg *Func) const override;
void dumpOpcode(Ostream &Str, const char *Opcode, Type Ty) const {
......@@ -669,7 +671,9 @@ public:
const CfgNode *getTargetTrue() const { return TargetTrue; }
const CfgNode *getTargetFalse() const { return TargetFalse; }
CondMIPS32::Cond getPredicate() const { return Predicate; }
void setPredicate(CondMIPS32::Cond Pred) { Predicate = Pred; }
bool optimizeBranch(const CfgNode *NextNode);
bool isUnconditionalBranch() const override {
return Predicate == CondMIPS32::AL;
}
......@@ -694,7 +698,7 @@ private:
const CfgNode *TargetTrue;
const CfgNode *TargetFalse;
const InstMIPS32Label *Label; // Intra-block branch target
const CondMIPS32::Cond Predicate;
CondMIPS32::Cond Predicate;
};
class InstMIPS32Call : public InstMIPS32 {
......
......@@ -396,9 +396,9 @@ void TargetMIPS32::translateOm1() {
}
bool TargetMIPS32::doBranchOpt(Inst *Instr, const CfgNode *NextNode) {
(void)Instr;
(void)NextNode;
UnimplementedError(getFlags());
if (auto *Br = llvm::dyn_cast<InstMIPS32Br>(Instr)) {
return Br->optimizeBranch(NextNode);
}
return false;
}
......
......@@ -27,6 +27,24 @@
; RUN: --command FileCheck \
; RUN: --check-prefix ARM32OM1 %s
; TODO(jaydeep.patil): Using --skip-unimplemented for MIPS32
; RUN: %if --need=target_MIPS32 --need=allow_dump \
; RUN: --command %p2i --filetype=asm --assemble \
; RUN: --disassemble --target mips32 -i %s --args -O2 \
; RUN: --skip-unimplemented \
; RUN: -allow-externally-defined-symbols \
; RUN: | %if --need=target_MIPS32 --need=allow_dump \
; RUN: --command FileCheck --check-prefix MIPS32O2 %s
; RUN: %if --need=target_MIPS32 --need=allow_dump \
; RUN: --command %p2i --filetype=asm --assemble \
; RUN: --disassemble --target mips32 -i %s --args -Om1 \
; RUN: --skip-unimplemented \
; RUN: -allow-externally-defined-symbols \
; RUN: | %if --need=target_MIPS32 --need=allow_dump \
; RUN: --command FileCheck \
; RUN: --check-prefix MIPS32OM1 %s
declare void @dummy()
; An unconditional branch to the next block should be removed.
......@@ -59,6 +77,22 @@ next:
; ARM32OM1-NEXT: b
; ARM32OM1-NEXT: bl {{.*}} dummy
; MIPS32O2-LABEL: testUncondToNextBlock
; MIPS32O2: jal {{.*}} dummy
; MIPS32O2-NEXT: nop
; MIPS32O2-LABEL: <.LtestUncondToNextBlock$next>:
; MIPS32O2-NEXT: jal {{.*}} dummy
; MIPS32O2-NEXT: nop
; MIPS32OM1-LABEL: testUncondToNextBlock
; MIPS32OM1: jal {{.*}} dummy
; MIPS32OM1-NEXT: nop
; MIPS32OM1-NEXT: b {{.*}} <.LtestUncondToNextBlock$next>
; MIPS32OM1-NEXT: nop
; MIPS32OM1-LABEL: <.LtestUncondToNextBlock$next>:
; MIPS32OM1-NEXT: jal {{.*}} dummy
; MIPS32OM1-NEXT: nop
; For a conditional branch with a fallthrough to the next block, the
; fallthrough branch should be removed.
define internal void @testCondFallthroughToNextBlock(i32 %arg) {
......@@ -112,6 +146,41 @@ target:
; ARM32OM1: bl
; ARM32OM1: bx lr
; MIPS32O2-LABEL: testCondFallthroughToNextBlock
; MIPS32O2: li {{.*}},123
; MIPS32O2: slt {{.*}},{{.*}},{{.*}}
; MIPS32O2: beqz
; MIPS32O2: nop
; MIPS32O2: .LtestCondFallthroughToNextBlock$fallthrough
; MIPS32O2: jal {{.*}} dummy
; MIPS32O2: nop
; MIPS32O2: jr
; MIPS32O2: nop
; MIPS32O2: .LtestCondFallthroughToNextBlock$target
; MIPS32O2: jal {{.*}} dummy
; MIPS32O2: nop
; MIPS32O2: jr
; MIPS32O2: nop
; MIPS32OM1-LABEL: testCondFallthroughToNextBlock
; MIPS32OM1: li {{.*}},123
; MIPS32OM1: slt {{.*}},{{.*}},{{.*}}
; MIPS32OM1: xori {{.*}},{{.*}},{{.*}}
; MIPS32OM1: beqz
; MIPS32OM1: nop
; MIPS32OM1: b
; MIPS32OM1: nop
; MIPS32OM1: .LtestCondFallthroughToNextBlock$fallthrough
; MIPS32OM1: jal {{.*}} dummy
; MIPS32OM1: nop
; MIPS32OM1: jr
; MIPS32OM1: nop
; MIPS32OM1: .LtestCondFallthroughToNextBlock$target
; MIPS32OM1: jal {{.*}} dummy
; MIPS32OM1: nop
; MIPS32OM1: jr
; MIPS32OM1: nop
; For a conditional branch with the next block as the target and a
; different block as the fallthrough, the branch condition should be
; inverted, the fallthrough block changed to the target, and the
......@@ -168,6 +237,41 @@ target:
; ARM32OM1: bl
; ARM32OM1: bx lr
; MIPS32O2-LABEL: testCondTargetNextBlock
; MIPS32O2: li {{.*}},123
; MIPS32O2: slt {{.*}},{{.*}},{{.*}}
; MIPS32O2: bnez
; MIPS32O2: nop
; MIPS32O2: .LtestCondTargetNextBlock$fallthrough
; MIPS32O2: jal {{.*}} dummy
; MIPS32O2: nop
; MIPS32O2: jr
; MIPS32O2: nop
; MIPS32O2: .LtestCondTargetNextBlock$target
; MIPS32O2: jal {{.*}} dummy
; MIPS32O2: nop
; MIPS32O2: jr
; MIPS32O2: nop
; MIPS32OM1-LABEL: testCondTargetNextBlock
; MIPS32OM1: li {{.*}},123
; MIPS32OM1: slt {{.*}},{{.*}},{{.*}}
; MIPS32OM1: xori {{.*}},{{.*}},{{.*}}
; MIPS32OM1: beqz
; MIPS32OM1: nop
; MIPS32OM1: b
; MIPS32OM1: nop
; MIPS32OM1: .LtestCondTargetNextBlock$fallthrough
; MIPS32OM1: jal {{.*}} dummy
; MIPS32OM1: nop
; MIPS32OM1: jr
; MIPS32OM1: nop
; MIPS32OM1: .LtestCondTargetNextBlock$target
; MIPS32OM1: jal {{.*}} dummy
; MIPS32OM1: nop
; MIPS32OM1: jr
; MIPS32OM1: nop
; Unconditional branches to the block after a contracted block should be
; removed.
define internal void @testUncondToBlockAfterContract() {
......@@ -201,3 +305,12 @@ target:
; ARM32OM1: bl {{.*}} dummy
; ARM32OM1-NEXT: b
; ARM32OM1-NEXT: bl {{.*}} dummy
; MIPS32O2-LABEL: testUncondToBlockAfterContract
; MIPS32O2: jal {{.*}} dummy
; MIPS32O2: .LtestUncondToBlockAfterContract$target
; MIPS32OM1-LABEL: testUncondToBlockAfterContract
; MIPS32OM1: jal {{.*}} dummy
; MIPS32OM1: b
; MIPS32OM1: .LtestUncondToBlockAfterContract$target
......@@ -22,10 +22,12 @@ branch2:
ret i32 2
}
; COMMON-LABEL: cond_br_eq
; MIPS32: bne
; MIPS32: bne {{.*}} .Lcond_br_eq$branch2
; MIPS32-NEXT: .Lcond_br_eq$branch1
; MIPS32-OM1: xor
; MIPS32-OM1: sltiu {{.*}}, {{.*}}, 1
; MIPS32-OM1: beqz
; MIPS32-OM1: beqz {{.*}} .Lcond_br_eq$branch2
; MIPS32-OM1-NEXT: b .Lcond_br_eq$branch1
define internal i32 @cond_br_ne(i32 %arg1, i32 %arg2) {
entry:
......@@ -37,10 +39,12 @@ branch2:
ret i32 2
}
; COMMON-LABEL: cond_br_ne
; MIPS32: beq
; MIPS32: beq {{.*}} .Lcond_br_ne$branch2
; MIPS32-NEXT: .Lcond_br_ne$branch1
; MIPS32-OM1: xor
; MIPS32-OM1: sltu {{.*}}, $zero, {{.*}}
; MIPS32-OM1: beqz
; MIPS32-OM1: beqz {{.*}} .Lcond_br_ne$branch2
; MIPS32-OM1-NEXT: b .Lcond_br_ne$branch1
define internal i32 @cond_br_slt(i32 %arg1, i32 %arg2) {
entry:
......@@ -53,9 +57,11 @@ branch2:
}
; COMMON-LABEL: cond_br_slt
; MIPS32: slt
; MIPS32: beqz
; MIPS32: beqz {{.*}} .Lcond_br_slt$branch2
; MIPS32-NEXT: .Lcond_br_slt$branch1
; MIPS32-OM1: slt
; MIPS32-OM1: beqz
; MIPS32-OM1: beqz {{.*}} .Lcond_br_slt$branch2
; MIPS32-OM1-NEXT: b .Lcond_br_slt$branch1
define internal i32 @cond_br_sle(i32 %arg1, i32 %arg2) {
entry:
......@@ -68,10 +74,12 @@ branch2:
}
; COMMON-LABEL: cond_br_sle
; MIPS32: slt
; MIPS32: bnez
; MIPS32: bnez {{.*}} .Lcond_br_sle$branch2
; MIPS32-NEXT: .Lcond_br_sle$branch1
; MIPS32-OM1: slt
; MIPS32-OM1: xori {{.*}}, {{.*}}, 1
; MIPS32-OM1: beqz
; MIPS32-OM1: beqz {{.*}} .Lcond_br_sle$branch2
; MIPS32-OM1-NEXT: b .Lcond_br_sle$branch1
define internal i32 @cond_br_sgt(i32 %arg1, i32 %arg2) {
entry:
......@@ -84,9 +92,11 @@ branch2:
}
; COMMON-LABEL: cond_br_sgt
; MIPS32: slt
; MIPS32: beqz
; MIPS32-NEXT: beqz {{.*}} .Lcond_br_sgt$branch2
; MIPS32-NEXT: .Lcond_br_sgt$branch1
; MIPS32-OM1: slt
; MIPS32-OM1: beqz
; MIPS32-OM1: beqz {{.*}} .Lcond_br_sgt$branch2
; MIPS32-OM1-NEXT: b .Lcond_br_sgt$branch1
define internal i32 @cond_br_sge(i32 %arg1, i32 %arg2) {
entry:
......@@ -99,10 +109,12 @@ branch2:
}
; COMMON-LABEL: cond_br_sge
; MIPS32: slt
; MIPS32: bnez
; MIPS32: bnez {{.*}} .Lcond_br_sge$branch2
; MIPS32-NEXT: .Lcond_br_sge$branch1
; MIPS32-OM1: slt
; MIPS32-OM1: xori {{.*}}, {{.*}}, 1
; MIPS32-OM1: beqz
; MIPS32-OM1: beqz {{.*}} .Lcond_br_sge$branch2
; MIPS32-OM1-NEXT: b .Lcond_br_sge$branch1
define internal i32 @cond_br_ugt(i32 %arg1, i32 %arg2) {
entry:
......@@ -115,9 +127,11 @@ branch2:
}
; COMMON-LABEL: cond_br_ugt
; MIPS32: sltu
; MIPS32: beqz
; MIPS32: beqz {{.*}} .Lcond_br_ugt$branch2
; MIPS32-NEXT: .Lcond_br_ugt$branch1
; MIPS32-OM1: sltu
; MIPS32-OM1: beqz
; MIPS32-OM1: beqz {{.*}} .Lcond_br_ugt$branch2
; MIPS32-OM1-NEXT: b .Lcond_br_ugt$branch1
define internal i32 @cond_br_uge(i32 %arg1, i32 %arg2) {
entry:
......@@ -130,10 +144,12 @@ branch2:
}
; COMMON-LABEL: cond_br_uge
; MIPS32: sltu
; MIPS32: bnez
; MIPS32: bnez {{.*}} .Lcond_br_uge$branch2
; MIPS32-NEXT: .Lcond_br_uge$branch1
; MIPS32-OM1: sltu
; MIPS32-OM1: xori {{.*}}, {{.*}}, 1
; MIPS32-OM1: beqz
; MIPS32-OM1: beqz {{.*}} .Lcond_br_uge$branch2
; MIPS32-OM1-NEXT: b .Lcond_br_uge$branch1
define internal i32 @cond_br_ult(i32 %arg1, i32 %arg2) {
entry:
......@@ -146,9 +162,11 @@ branch2:
}
; COMMON-LABEL: cond_br_ult
; MIPS32: sltu
; MIPS32: beqz
; MIPS32: beqz {{.*}} .Lcond_br_ult$branch2
; MIPS32-NEXT: .Lcond_br_ult$branch1
; MIPS32-OM1: sltu
; MIPS32-OM1: beqz
; MIPS32-OM1: beqz {{.*}} .Lcond_br_ult$branch2
; MIPS32-OM1-NEXT: b .Lcond_br_ult$branch1
define internal i32 @cond_br_ule(i32 %arg1, i32 %arg2) {
entry:
......@@ -161,7 +179,9 @@ branch2:
}
; COMMON-LABEL: cond_br_ule
; MIPS32: sltu
; MIPS32: bnez
; MIPS32: bnez {{.*}} .Lcond_br_ule$branch2
; MIPS32-NEXT: .Lcond_br_ule$branch1
; MIPS32-OM1: sltu
; MIPS32-OM1: xori {{.*}}, {{.*}}, 1
; MIPS32-OM1: beqz
; MIPS32-OM1: beqz {{.*}} .Lcond_br_ule$branch2
; MIPS32-OM1-NEXT: b .Lcond_br_ule$branch1
......@@ -23,7 +23,6 @@ target:
}
; MIPS32-LABEL: uncond1
; MIPS32: b {{[0-9a-f]+}} <.Luncond1$target>
; MIPS32: <.Luncond1$target>:
; MIPS32: li
; MIPS32: addu
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment