@@ -1014,109 +1014,6 @@ RISCVCC::CondCode RISCVCC::getOppositeBranchCondition(RISCVCC::CondCode CC) {
10141014 }
10151015}
10161016
1017- // Return true if MO definitely contains the value one.
1018- static bool isOne (MachineOperand &MO) {
1019- if (MO.isImm () && MO.getImm () == 1 )
1020- return true ;
1021-
1022- if (!MO.isReg () || !MO.getReg ().isVirtual ())
1023- return false ;
1024-
1025- MachineRegisterInfo &MRI =
1026- MO.getParent ()->getParent ()->getParent ()->getRegInfo ();
1027- MachineInstr *DefMI = MRI.getUniqueVRegDef (MO.getReg ());
1028- if (!DefMI)
1029- return false ;
1030-
1031- // For now, just check the canonical one value.
1032- if (DefMI->getOpcode () == RISCV::ADDI &&
1033- DefMI->getOperand (1 ).getReg () == RISCV::X0 &&
1034- DefMI->getOperand (2 ).getImm () == 1 )
1035- return true ;
1036-
1037- return false ;
1038- }
1039-
1040- // Return true if MO definitely contains the value zero.
1041- static bool isZero (MachineOperand &MO) {
1042- if (MO.isImm () && MO.getImm () == 0 )
1043- return true ;
1044- if (MO.isReg () && MO.getReg () == RISCV::X0)
1045- return true ;
1046- return false ;
1047- }
1048-
1049- bool RISCVInstrInfo::trySimplifyCondBr (
1050- MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB,
1051- SmallVectorImpl<MachineOperand> &Cond) const {
1052-
1053- if (!TBB || Cond.size () != 3 )
1054- return false ;
1055-
1056- RISCVCC::CondCode CC = static_cast <RISCVCC::CondCode>(Cond[0 ].getImm ());
1057- auto LHS = Cond[1 ];
1058- auto RHS = Cond[2 ];
1059-
1060- MachineBasicBlock *Folded = nullptr ;
1061- switch (CC) {
1062- default :
1063- // TODO: Implement for more CCs
1064- return false ;
1065- case RISCVCC::COND_EQ: {
1066- // We can statically evaluate that we take the first branch
1067- if ((isZero (LHS) && isZero (RHS)) || (isOne (LHS) && isOne (RHS))) {
1068- Folded = TBB;
1069- break ;
1070- }
1071- // We can statically evaluate that we take the second branch
1072- if ((isZero (LHS) && isOne (RHS)) || (isOne (LHS) && isZero (RHS))) {
1073- Folded = FBB;
1074- break ;
1075- }
1076- return false ;
1077- }
1078- case RISCVCC::COND_NE: {
1079- // We can statically evaluate that we take the first branch
1080- if ((isOne (LHS) && isZero (RHS)) || (isZero (LHS) && isOne (RHS))) {
1081- Folded = TBB;
1082- break ;
1083- }
1084- // We can statically evaluate that we take the second branch
1085- if ((isZero (LHS) && isZero (RHS)) || (isOne (LHS) && isOne (RHS))) {
1086- Folded = FBB;
1087- break ;
1088- }
1089- return false ;
1090- }
1091- }
1092-
1093- // At this point, its legal to optimize.
1094- removeBranch (MBB);
1095- Cond.clear ();
1096-
1097- // Only need to insert a branch if we're not falling through.
1098- if (Folded) {
1099- DebugLoc DL = MBB.findBranchDebugLoc ();
1100- insertBranch (MBB, Folded, nullptr , {}, DL);
1101- }
1102-
1103- // Update the successors. Remove them all and add back the correct one.
1104- while (!MBB.succ_empty ())
1105- MBB.removeSuccessor (MBB.succ_end () - 1 );
1106-
1107- // If it's a fallthrough, we need to figure out where MBB is going.
1108- if (!Folded) {
1109- MachineFunction::iterator Fallthrough = ++MBB.getIterator ();
1110- if (Fallthrough != MBB.getParent ()->end ())
1111- MBB.addSuccessor (&*Fallthrough);
1112- } else
1113- MBB.addSuccessor (Folded);
1114-
1115- TBB = Folded;
1116- FBB = nullptr ;
1117- return true ;
1118- }
1119-
11201017bool RISCVInstrInfo::analyzeBranch (MachineBasicBlock &MBB,
11211018 MachineBasicBlock *&TBB,
11221019 MachineBasicBlock *&FBB,
@@ -1174,9 +1071,12 @@ bool RISCVInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
11741071 // Handle a single conditional branch.
11751072 if (NumTerminators == 1 && I->getDesc ().isConditionalBranch ()) {
11761073 parseCondBranch (*I, TBB, Cond);
1177- // Try to fold the branch of the conditional branch into a the fallthru.
1178- if (AllowModify)
1179- trySimplifyCondBr (MBB, TBB, FBB, Cond);
1074+ // Try and optimize the conditional branch.
1075+ if (AllowModify) {
1076+ optimizeCondBranch (*I);
1077+ // The branch might have changed, reanalyze it.
1078+ return analyzeBranch (MBB, TBB, FBB, Cond, false );
1079+ }
11801080 return false ;
11811081 }
11821082
@@ -1185,10 +1085,14 @@ bool RISCVInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
11851085 I->getDesc ().isUnconditionalBranch ()) {
11861086 parseCondBranch (*std::prev (I), TBB, Cond);
11871087 FBB = getBranchDestBlock (*I);
1188- // Try to fold the branch of the conditional branch into an unconditional
1189- // branch.
1190- if (AllowModify)
1191- trySimplifyCondBr (MBB, TBB, FBB, Cond);
1088+ // Try and optimize the pair.
1089+ if (AllowModify) {
1090+ if (optimizeCondBranch (*std::prev (I)))
1091+ I->eraseFromParent ();
1092+
1093+ // The branch might have changed, reanalyze it.
1094+ return analyzeBranch (MBB, TBB, FBB, Cond, false );
1095+ }
11921096 return false ;
11931097 }
11941098
@@ -1344,7 +1248,8 @@ bool RISCVInstrInfo::reverseBranchCondition(
13441248
13451249bool RISCVInstrInfo::optimizeCondBranch (MachineInstr &MI) const {
13461250 MachineBasicBlock *MBB = MI.getParent ();
1347- MachineRegisterInfo &MRI = MBB->getParent ()->getRegInfo ();
1251+ if (!MBB)
1252+ return false ;
13481253
13491254 MachineBasicBlock *TBB, *FBB;
13501255 SmallVector<MachineOperand, 3 > Cond;
@@ -1354,8 +1259,98 @@ bool RISCVInstrInfo::optimizeCondBranch(MachineInstr &MI) const {
13541259 RISCVCC::CondCode CC = static_cast <RISCVCC::CondCode>(Cond[0 ].getImm ());
13551260 assert (CC != RISCVCC::COND_INVALID);
13561261
1357- if (CC == RISCVCC::COND_EQ || CC == RISCVCC::COND_NE)
1262+ // Right now we only care about LI (i.e. ADDI x0, imm)
1263+ auto isLoadImm = [](const MachineInstr *MI, int64_t &Imm) -> bool {
1264+ if (MI->getOpcode () == RISCV::ADDI && MI->getOperand (1 ).isReg () &&
1265+ MI->getOperand (1 ).getReg () == RISCV::X0) {
1266+ Imm = MI->getOperand (2 ).getImm ();
1267+ return true ;
1268+ }
13581269 return false ;
1270+ };
1271+
1272+ MachineRegisterInfo &MRI = MBB->getParent ()->getRegInfo ();
1273+ // Either a load from immediate instruction or X0.
1274+ auto isFromLoadImm = [&](const MachineOperand &Op, int64_t &Imm) -> bool {
1275+ if (!Op.isReg ())
1276+ return false ;
1277+ Register Reg = Op.getReg ();
1278+ if (Reg == RISCV::X0) {
1279+ Imm = 0 ;
1280+ return true ;
1281+ }
1282+ return Reg.isVirtual () && isLoadImm (MRI.getVRegDef (Reg), Imm);
1283+ };
1284+
1285+ // Try and convert a conditional branch that can be evaluated statically
1286+ // into an unconditional branch.
1287+ MachineBasicBlock *Folded = nullptr ;
1288+ int64_t C0, C1;
1289+ if (isFromLoadImm (Cond[1 ], C0) && isFromLoadImm (Cond[2 ], C1)) {
1290+ switch (CC) {
1291+ default :
1292+ // TODO: Implement for more CCs
1293+ break ;
1294+ case RISCVCC::COND_EQ: {
1295+ Folded = (C0 == C1) ? TBB : FBB;
1296+ break ;
1297+ }
1298+ case RISCVCC::COND_NE: {
1299+ Folded = (C0 != C1) ? TBB : FBB;
1300+ break ;
1301+ }
1302+ case RISCVCC::COND_LT: {
1303+ Folded = (C0 < C1) ? TBB : FBB;
1304+ break ;
1305+ }
1306+ case RISCVCC::COND_GE: {
1307+ Folded = (C0 >= C1) ? TBB : FBB;
1308+ break ;
1309+ }
1310+ case RISCVCC::COND_LTU: {
1311+ Folded = ((uint64_t )C0 < (uint64_t )C1) ? TBB : FBB;
1312+ break ;
1313+ }
1314+ case RISCVCC::COND_GEU: {
1315+ Folded = ((uint64_t )C0 >= (uint64_t )C1) ? TBB : FBB;
1316+ break ;
1317+ }
1318+ }
1319+
1320+ // Do the conversion
1321+ // Build the new unconditional branch
1322+ DebugLoc DL = MBB->findBranchDebugLoc ();
1323+ if (Folded) {
1324+ BuildMI (*MBB, MI, DL, get (RISCV::PseudoBR)).addMBB (Folded);
1325+ } else {
1326+ MachineFunction::iterator Fallthrough = ++MBB->getIterator ();
1327+ if (Fallthrough == MBB->getParent ()->end ())
1328+ return false ;
1329+ BuildMI (*MBB, MI, DL, get (RISCV::PseudoBR)).addMBB (&*Fallthrough);
1330+ }
1331+
1332+ // Update successors of MBB.
1333+ if (Folded == TBB) {
1334+ // If we're taking TBB, then the succ to delete is the fallthrough (if
1335+ // it was a succ in the first place), or its the MBB from the
1336+ // unconditional branch.
1337+ if (!FBB) {
1338+ MachineFunction::iterator Fallthrough = ++MBB->getIterator ();
1339+ if (Fallthrough != MBB->getParent ()->end () &&
1340+ MBB->isSuccessor (&*Fallthrough))
1341+ MBB->removeSuccessor (&*Fallthrough, true );
1342+ } else {
1343+ MBB->removeSuccessor (FBB, true );
1344+ }
1345+ } else if (Folded == FBB) {
1346+ // If we're taking the fallthrough or unconditional branch, then the
1347+ // succ to remove is the one from the conditional branch.
1348+ MBB->removeSuccessor (TBB, true );
1349+ }
1350+
1351+ MI.eraseFromParent ();
1352+ return true ;
1353+ }
13591354
13601355 // For two constants C0 and C1 from
13611356 // ```
@@ -1374,24 +1369,6 @@ bool RISCVInstrInfo::optimizeCondBranch(MachineInstr &MI) const {
13741369 //
13751370 // To make sure this optimization is really beneficial, we only
13761371 // optimize for cases where Y had only one use (i.e. only used by the branch).
1377-
1378- // Right now we only care about LI (i.e. ADDI x0, imm)
1379- auto isLoadImm = [](const MachineInstr *MI, int64_t &Imm) -> bool {
1380- if (MI->getOpcode () == RISCV::ADDI && MI->getOperand (1 ).isReg () &&
1381- MI->getOperand (1 ).getReg () == RISCV::X0) {
1382- Imm = MI->getOperand (2 ).getImm ();
1383- return true ;
1384- }
1385- return false ;
1386- };
1387- // Either a load from immediate instruction or X0.
1388- auto isFromLoadImm = [&](const MachineOperand &Op, int64_t &Imm) -> bool {
1389- if (!Op.isReg ())
1390- return false ;
1391- Register Reg = Op.getReg ();
1392- return Reg.isVirtual () && isLoadImm (MRI.getVRegDef (Reg), Imm);
1393- };
1394-
13951372 MachineOperand &LHS = MI.getOperand (0 );
13961373 MachineOperand &RHS = MI.getOperand (1 );
13971374 // Try to find the register for constant Z; return
@@ -1410,7 +1387,6 @@ bool RISCVInstrInfo::optimizeCondBranch(MachineInstr &MI) const {
14101387 };
14111388
14121389 bool Modify = false ;
1413- int64_t C0;
14141390 if (isFromLoadImm (LHS, C0) && MRI.hasOneUse (LHS.getReg ())) {
14151391 // Might be case 1.
14161392 // Signed integer overflow is UB. (UINT64_MAX is bigger so we don't need
0 commit comments