@@ -1014,109 +1014,6 @@ RISCVCC::CondCode RISCVCC::getOppositeBranchCondition(RISCVCC::CondCode CC) {
1014
1014
}
1015
1015
}
1016
1016
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
-
1120
1017
bool RISCVInstrInfo::analyzeBranch (MachineBasicBlock &MBB,
1121
1018
MachineBasicBlock *&TBB,
1122
1019
MachineBasicBlock *&FBB,
@@ -1174,9 +1071,12 @@ bool RISCVInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
1174
1071
// Handle a single conditional branch.
1175
1072
if (NumTerminators == 1 && I->getDesc ().isConditionalBranch ()) {
1176
1073
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
+ }
1180
1080
return false ;
1181
1081
}
1182
1082
@@ -1185,10 +1085,14 @@ bool RISCVInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
1185
1085
I->getDesc ().isUnconditionalBranch ()) {
1186
1086
parseCondBranch (*std::prev (I), TBB, Cond);
1187
1087
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
+ }
1192
1096
return false ;
1193
1097
}
1194
1098
@@ -1344,7 +1248,8 @@ bool RISCVInstrInfo::reverseBranchCondition(
1344
1248
1345
1249
bool RISCVInstrInfo::optimizeCondBranch (MachineInstr &MI) const {
1346
1250
MachineBasicBlock *MBB = MI.getParent ();
1347
- MachineRegisterInfo &MRI = MBB->getParent ()->getRegInfo ();
1251
+ if (!MBB)
1252
+ return false ;
1348
1253
1349
1254
MachineBasicBlock *TBB, *FBB;
1350
1255
SmallVector<MachineOperand, 3 > Cond;
@@ -1354,8 +1259,98 @@ bool RISCVInstrInfo::optimizeCondBranch(MachineInstr &MI) const {
1354
1259
RISCVCC::CondCode CC = static_cast <RISCVCC::CondCode>(Cond[0 ].getImm ());
1355
1260
assert (CC != RISCVCC::COND_INVALID);
1356
1261
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
+ }
1358
1269
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
+ }
1359
1354
1360
1355
// For two constants C0 and C1 from
1361
1356
// ```
@@ -1374,24 +1369,6 @@ bool RISCVInstrInfo::optimizeCondBranch(MachineInstr &MI) const {
1374
1369
//
1375
1370
// To make sure this optimization is really beneficial, we only
1376
1371
// 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
-
1395
1372
MachineOperand &LHS = MI.getOperand (0 );
1396
1373
MachineOperand &RHS = MI.getOperand (1 );
1397
1374
// Try to find the register for constant Z; return
@@ -1410,7 +1387,6 @@ bool RISCVInstrInfo::optimizeCondBranch(MachineInstr &MI) const {
1410
1387
};
1411
1388
1412
1389
bool Modify = false ;
1413
- int64_t C0;
1414
1390
if (isFromLoadImm (LHS, C0) && MRI.hasOneUse (LHS.getReg ())) {
1415
1391
// Might be case 1.
1416
1392
// Signed integer overflow is UB. (UINT64_MAX is bigger so we don't need
0 commit comments