Skip to content

Commit e7670a7

Browse files
[BranchFolding][RISCV] Optimize branches NE/EQ to zero or one
There are two changes here. The first that we teach analyzeBranch how to evaluate a conditional branch followed by a unconditional branch such that we can evaluate the conditional branch statically. Often, we will see comparison to one or zero since SelectionDAG often uses i1 for the conditional comparison. As a result, we handle this specific case. We handle only EQ and NEQ for now, but this can be expanded in the future. We can also expand on handling arbitrary constants in the future. The second change is that we pass AllowModify=false to analyzeBranch in the tail merging code. The reason we do this is because this code is doing some clever tricks to the branch code that it will restore later. Now that we are actually optimizing branches in analyzeBranch, we have to be careful not to mess up this canonical form that the tail merging code expects.
1 parent aba3aaa commit e7670a7

File tree

3 files changed

+108
-4
lines changed

3 files changed

+108
-4
lines changed

llvm/lib/CodeGen/BranchFolding.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1107,7 +1107,7 @@ bool BranchFolder::TailMergeBlocks(MachineFunction &MF) {
11071107

11081108
MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
11091109
SmallVector<MachineOperand, 4> Cond;
1110-
if (!TII->analyzeBranch(*PBB, TBB, FBB, Cond, true)) {
1110+
if (!TII->analyzeBranch(*PBB, TBB, FBB, Cond)) {
11111111
// Failing case: IBB is the target of a cbr, and we cannot reverse the
11121112
// branch.
11131113
SmallVector<MachineOperand, 4> NewCond(Cond);

llvm/lib/Target/RISCV/RISCVInstrInfo.cpp

Lines changed: 107 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1005,6 +1005,96 @@ RISCVCC::CondCode RISCVCC::getOppositeBranchCondition(RISCVCC::CondCode CC) {
10051005
}
10061006
}
10071007

1008+
/// Return true if the branch represented by the conditional branch with
1009+
/// components TBB, FBB, and CurCond can folded into an unconditional branch
1010+
/// that branches to FoldedBB.
1011+
///
1012+
/// For example:
1013+
/// BRCOND EQ 0, 0, BB1
1014+
/// BR BB2
1015+
///
1016+
/// can be simplified to BR BB1 since 0 == 0 statically. On the other hand,
1017+
///
1018+
///
1019+
/// BRCOND EQ 0, 1, BB1
1020+
/// BR BB2
1021+
///
1022+
/// can be simplified to BR BB2 because 0 != 1 statically.
1023+
static bool canFoldBrOfCondBr(MachineBasicBlock *TBB, MachineBasicBlock *FBB,
1024+
SmallVectorImpl<MachineOperand> &CurCond,
1025+
MachineBasicBlock *&FoldedBB) {
1026+
if (!TBB || !FBB || CurCond.size() != 3)
1027+
return false;
1028+
1029+
RISCVCC::CondCode CC = static_cast<RISCVCC::CondCode>(CurCond[0].getImm());
1030+
auto LHS = CurCond[1];
1031+
auto RHS = CurCond[2];
1032+
1033+
// Return true if MO definitely contains the value one.
1034+
auto isOne = [](MachineOperand &MO) -> bool {
1035+
if (MO.isImm() && MO.getImm() == 1)
1036+
return true;
1037+
1038+
if (!MO.isReg() || !MO.getReg().isVirtual())
1039+
return false;
1040+
1041+
MachineRegisterInfo &MRI =
1042+
MO.getParent()->getParent()->getParent()->getRegInfo();
1043+
MachineInstr *DefMI = MRI.getUniqueVRegDef(MO.getReg());
1044+
if (!DefMI)
1045+
return false;
1046+
1047+
// For now, just check the canonical zero value.
1048+
if (DefMI->getOpcode() == RISCV::ADDI &&
1049+
DefMI->getOperand(1).getReg() == RISCV::X0 &&
1050+
DefMI->getOperand(2).getImm() == 1)
1051+
return true;
1052+
1053+
return false;
1054+
};
1055+
1056+
// Return true if MO definitely contains the value zero.
1057+
auto isZero = [](MachineOperand &MO) -> bool {
1058+
if (MO.isImm() && MO.getImm() == 0)
1059+
return true;
1060+
if (MO.isReg() && MO.getReg() == RISCV::X0)
1061+
return true;
1062+
return false;
1063+
};
1064+
1065+
switch (CC) {
1066+
default:
1067+
// TODO: Implement for more CCs
1068+
return false;
1069+
case RISCVCC::COND_EQ: {
1070+
// We can statically evaluate that we take the first branch
1071+
if ((isZero(LHS) && isZero(RHS)) || (isOne(LHS) && isOne(RHS))) {
1072+
FoldedBB = TBB;
1073+
return true;
1074+
}
1075+
// We can statically evaluate that we take the second branch
1076+
if ((isZero(LHS) && isOne(RHS)) || (isOne(LHS) && isZero(RHS))) {
1077+
FoldedBB = FBB;
1078+
return true;
1079+
}
1080+
return false;
1081+
}
1082+
case RISCVCC::COND_NE: {
1083+
// We can statically evaluate that we take the first branch
1084+
if ((isOne(LHS) && isZero(RHS)) || (isZero(LHS) && isOne(RHS))) {
1085+
FoldedBB = TBB;
1086+
return true;
1087+
}
1088+
// We can statically evaluate that we take the second branch
1089+
if ((isZero(LHS) && isZero(RHS)) || (isOne(LHS) && isOne(RHS))) {
1090+
FoldedBB = FBB;
1091+
return true;
1092+
}
1093+
return false;
1094+
}
1095+
}
1096+
}
1097+
10081098
bool RISCVInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
10091099
MachineBasicBlock *&TBB,
10101100
MachineBasicBlock *&FBB,
@@ -1068,8 +1158,24 @@ bool RISCVInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
10681158
// Handle a conditional branch followed by an unconditional branch.
10691159
if (NumTerminators == 2 && std::prev(I)->getDesc().isConditionalBranch() &&
10701160
I->getDesc().isUnconditionalBranch()) {
1071-
parseCondBranch(*std::prev(I), TBB, Cond);
1161+
1162+
// Try to fold the branch of the conditional branch into an unconditional
1163+
// branch.
1164+
MachineInstr &CondBr = *std::prev(I);
1165+
parseCondBranch(CondBr, TBB, Cond);
10721166
FBB = getBranchDestBlock(*I);
1167+
MachineBasicBlock *Folded = nullptr;
1168+
if (AllowModify && canFoldBrOfCondBr(TBB, FBB, Cond, Folded)) {
1169+
DebugLoc DL = MBB.findBranchDebugLoc();
1170+
removeBranch(MBB);
1171+
insertBranch(MBB, Folded, nullptr, {}, DL);
1172+
while (!MBB.succ_empty())
1173+
MBB.removeSuccessor(MBB.succ_end() - 1);
1174+
MBB.addSuccessor(Folded);
1175+
TBB = Folded;
1176+
FBB = nullptr;
1177+
Cond.clear();
1178+
}
10731179
return false;
10741180
}
10751181

llvm/test/CodeGen/RISCV/branch_zero.ll

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,9 @@ if.then:
8787
define ptr @baz() {
8888
; CHECK-LABEL: baz:
8989
; CHECK: # %bb.0: # %entry
90-
; CHECK-NEXT: beqz zero, .LBB2_2
9190
; CHECK-NEXT: # %bb.1: # %if.end12
9291
; CHECK-NEXT: li a0, 0
9392
; CHECK-NEXT: ret
94-
; CHECK-NEXT: .LBB2_2: # %if.then10
9593
entry:
9694
%or.cond = or i1 false, false
9795
br i1 %or.cond, label %if.end12, label %if.then10

0 commit comments

Comments
 (0)