@@ -1005,109 +1005,6 @@ RISCVCC::CondCode RISCVCC::getOppositeBranchCondition(RISCVCC::CondCode CC) {
1005
1005
}
1006
1006
}
1007
1007
1008
- // Return true if MO definitely contains the value one.
1009
- static bool isOne (MachineOperand &MO) {
1010
- if (MO.isImm () && MO.getImm () == 1 )
1011
- return true ;
1012
-
1013
- if (!MO.isReg () || !MO.getReg ().isVirtual ())
1014
- return false ;
1015
-
1016
- MachineRegisterInfo &MRI =
1017
- MO.getParent ()->getParent ()->getParent ()->getRegInfo ();
1018
- MachineInstr *DefMI = MRI.getUniqueVRegDef (MO.getReg ());
1019
- if (!DefMI)
1020
- return false ;
1021
-
1022
- // For now, just check the canonical one value.
1023
- if (DefMI->getOpcode () == RISCV::ADDI &&
1024
- DefMI->getOperand (1 ).getReg () == RISCV::X0 &&
1025
- DefMI->getOperand (2 ).getImm () == 1 )
1026
- return true ;
1027
-
1028
- return false ;
1029
- }
1030
-
1031
- // Return true if MO definitely contains the value zero.
1032
- static bool isZero (MachineOperand &MO) {
1033
- if (MO.isImm () && MO.getImm () == 0 )
1034
- return true ;
1035
- if (MO.isReg () && MO.getReg () == RISCV::X0)
1036
- return true ;
1037
- return false ;
1038
- }
1039
-
1040
- bool RISCVInstrInfo::trySimplifyCondBr (
1041
- MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB,
1042
- SmallVectorImpl<MachineOperand> &Cond) const {
1043
-
1044
- if (!TBB || Cond.size () != 3 )
1045
- return false ;
1046
-
1047
- RISCVCC::CondCode CC = static_cast <RISCVCC::CondCode>(Cond[0 ].getImm ());
1048
- auto LHS = Cond[1 ];
1049
- auto RHS = Cond[2 ];
1050
-
1051
- MachineBasicBlock *Folded = nullptr ;
1052
- switch (CC) {
1053
- default :
1054
- // TODO: Implement for more CCs
1055
- return false ;
1056
- case RISCVCC::COND_EQ: {
1057
- // We can statically evaluate that we take the first branch
1058
- if ((isZero (LHS) && isZero (RHS)) || (isOne (LHS) && isOne (RHS))) {
1059
- Folded = TBB;
1060
- break ;
1061
- }
1062
- // We can statically evaluate that we take the second branch
1063
- if ((isZero (LHS) && isOne (RHS)) || (isOne (LHS) && isZero (RHS))) {
1064
- Folded = FBB;
1065
- break ;
1066
- }
1067
- return false ;
1068
- }
1069
- case RISCVCC::COND_NE: {
1070
- // We can statically evaluate that we take the first branch
1071
- if ((isOne (LHS) && isZero (RHS)) || (isZero (LHS) && isOne (RHS))) {
1072
- Folded = TBB;
1073
- break ;
1074
- }
1075
- // We can statically evaluate that we take the second branch
1076
- if ((isZero (LHS) && isZero (RHS)) || (isOne (LHS) && isOne (RHS))) {
1077
- Folded = FBB;
1078
- break ;
1079
- }
1080
- return false ;
1081
- }
1082
- }
1083
-
1084
- // At this point, its legal to optimize.
1085
- removeBranch (MBB);
1086
- Cond.clear ();
1087
-
1088
- // Only need to insert a branch if we're not falling through.
1089
- if (Folded) {
1090
- DebugLoc DL = MBB.findBranchDebugLoc ();
1091
- insertBranch (MBB, Folded, nullptr , {}, DL);
1092
- }
1093
-
1094
- // Update the successors. Remove them all and add back the correct one.
1095
- while (!MBB.succ_empty ())
1096
- MBB.removeSuccessor (MBB.succ_end () - 1 );
1097
-
1098
- // If it's a fallthrough, we need to figure out where MBB is going.
1099
- if (!Folded) {
1100
- MachineFunction::iterator Fallthrough = ++MBB.getIterator ();
1101
- if (Fallthrough != MBB.getParent ()->end ())
1102
- MBB.addSuccessor (&*Fallthrough);
1103
- } else
1104
- MBB.addSuccessor (Folded);
1105
-
1106
- TBB = Folded;
1107
- FBB = nullptr ;
1108
- return true ;
1109
- }
1110
-
1111
1008
bool RISCVInstrInfo::analyzeBranch (MachineBasicBlock &MBB,
1112
1009
MachineBasicBlock *&TBB,
1113
1010
MachineBasicBlock *&FBB,
@@ -1165,9 +1062,12 @@ bool RISCVInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
1165
1062
// Handle a single conditional branch.
1166
1063
if (NumTerminators == 1 && I->getDesc ().isConditionalBranch ()) {
1167
1064
parseCondBranch (*I, TBB, Cond);
1168
- // Try to fold the branch of the conditional branch into a the fallthru.
1169
- if (AllowModify)
1170
- trySimplifyCondBr (MBB, TBB, FBB, Cond);
1065
+ // Try and optimize the conditional branch.
1066
+ if (AllowModify) {
1067
+ optimizeCondBranch (*I);
1068
+ // The branch might have changed, reanalyze it.
1069
+ return analyzeBranch (MBB, TBB, FBB, Cond, false );
1070
+ }
1171
1071
return false ;
1172
1072
}
1173
1073
@@ -1176,10 +1076,14 @@ bool RISCVInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
1176
1076
I->getDesc ().isUnconditionalBranch ()) {
1177
1077
parseCondBranch (*std::prev (I), TBB, Cond);
1178
1078
FBB = getBranchDestBlock (*I);
1179
- // Try to fold the branch of the conditional branch into an unconditional
1180
- // branch.
1181
- if (AllowModify)
1182
- trySimplifyCondBr (MBB, TBB, FBB, Cond);
1079
+ // Try and optimize the pair.
1080
+ if (AllowModify) {
1081
+ if (optimizeCondBranch (*std::prev (I)))
1082
+ I->eraseFromParent ();
1083
+
1084
+ // The branch might have changed, reanalyze it.
1085
+ return analyzeBranch (MBB, TBB, FBB, Cond, false );
1086
+ }
1183
1087
return false ;
1184
1088
}
1185
1089
@@ -1335,7 +1239,8 @@ bool RISCVInstrInfo::reverseBranchCondition(
1335
1239
1336
1240
bool RISCVInstrInfo::optimizeCondBranch (MachineInstr &MI) const {
1337
1241
MachineBasicBlock *MBB = MI.getParent ();
1338
- MachineRegisterInfo &MRI = MBB->getParent ()->getRegInfo ();
1242
+ if (!MBB)
1243
+ return false ;
1339
1244
1340
1245
MachineBasicBlock *TBB, *FBB;
1341
1246
SmallVector<MachineOperand, 3 > Cond;
@@ -1345,8 +1250,98 @@ bool RISCVInstrInfo::optimizeCondBranch(MachineInstr &MI) const {
1345
1250
RISCVCC::CondCode CC = static_cast <RISCVCC::CondCode>(Cond[0 ].getImm ());
1346
1251
assert (CC != RISCVCC::COND_INVALID);
1347
1252
1348
- if (CC == RISCVCC::COND_EQ || CC == RISCVCC::COND_NE)
1253
+ // Right now we only care about LI (i.e. ADDI x0, imm)
1254
+ auto isLoadImm = [](const MachineInstr *MI, int64_t &Imm) -> bool {
1255
+ if (MI->getOpcode () == RISCV::ADDI && MI->getOperand (1 ).isReg () &&
1256
+ MI->getOperand (1 ).getReg () == RISCV::X0) {
1257
+ Imm = MI->getOperand (2 ).getImm ();
1258
+ return true ;
1259
+ }
1349
1260
return false ;
1261
+ };
1262
+
1263
+ MachineRegisterInfo &MRI = MBB->getParent ()->getRegInfo ();
1264
+ // Either a load from immediate instruction or X0.
1265
+ auto isFromLoadImm = [&](const MachineOperand &Op, int64_t &Imm) -> bool {
1266
+ if (!Op.isReg ())
1267
+ return false ;
1268
+ Register Reg = Op.getReg ();
1269
+ if (Reg == RISCV::X0) {
1270
+ Imm = 0 ;
1271
+ return true ;
1272
+ }
1273
+ return Reg.isVirtual () && isLoadImm (MRI.getVRegDef (Reg), Imm);
1274
+ };
1275
+
1276
+ // Try and convert a conditional branch that can be evaluated statically
1277
+ // into an unconditional branch.
1278
+ MachineBasicBlock *Folded = nullptr ;
1279
+ int64_t C0, C1;
1280
+ if (isFromLoadImm (Cond[1 ], C0) && isFromLoadImm (Cond[2 ], C1)) {
1281
+ switch (CC) {
1282
+ default :
1283
+ // TODO: Implement for more CCs
1284
+ break ;
1285
+ case RISCVCC::COND_EQ: {
1286
+ Folded = (C0 == C1) ? TBB : FBB;
1287
+ break ;
1288
+ }
1289
+ case RISCVCC::COND_NE: {
1290
+ Folded = (C0 != C1) ? TBB : FBB;
1291
+ break ;
1292
+ }
1293
+ case RISCVCC::COND_LT: {
1294
+ Folded = (C0 < C1) ? TBB : FBB;
1295
+ break ;
1296
+ }
1297
+ case RISCVCC::COND_GE: {
1298
+ Folded = (C0 >= C1) ? TBB : FBB;
1299
+ break ;
1300
+ }
1301
+ case RISCVCC::COND_LTU: {
1302
+ Folded = ((uint64_t )C0 < (uint64_t )C1) ? TBB : FBB;
1303
+ break ;
1304
+ }
1305
+ case RISCVCC::COND_GEU: {
1306
+ Folded = ((uint64_t )C0 >= (uint64_t )C1) ? TBB : FBB;
1307
+ break ;
1308
+ }
1309
+ }
1310
+
1311
+ // Do the conversion
1312
+ // Build the new unconditional branch
1313
+ DebugLoc DL = MBB->findBranchDebugLoc ();
1314
+ if (Folded) {
1315
+ BuildMI (*MBB, MI, DL, get (RISCV::PseudoBR)).addMBB (Folded);
1316
+ } else {
1317
+ MachineFunction::iterator Fallthrough = ++MBB->getIterator ();
1318
+ if (Fallthrough == MBB->getParent ()->end ())
1319
+ return false ;
1320
+ BuildMI (*MBB, MI, DL, get (RISCV::PseudoBR)).addMBB (&*Fallthrough);
1321
+ }
1322
+
1323
+ // Update successors of MBB.
1324
+ if (Folded == TBB) {
1325
+ // If we're taking TBB, then the succ to delete is the fallthrough (if
1326
+ // it was a succ in the first place), or its the MBB from the
1327
+ // unconditional branch.
1328
+ if (!FBB) {
1329
+ MachineFunction::iterator Fallthrough = ++MBB->getIterator ();
1330
+ if (Fallthrough != MBB->getParent ()->end () &&
1331
+ MBB->isSuccessor (&*Fallthrough))
1332
+ MBB->removeSuccessor (&*Fallthrough, true );
1333
+ } else {
1334
+ MBB->removeSuccessor (FBB, true );
1335
+ }
1336
+ } else if (Folded == FBB) {
1337
+ // If we're taking the fallthrough or unconditional branch, then the
1338
+ // succ to remove is the one from the conditional branch.
1339
+ MBB->removeSuccessor (TBB, true );
1340
+ }
1341
+
1342
+ MI.eraseFromParent ();
1343
+ return true ;
1344
+ }
1350
1345
1351
1346
// For two constants C0 and C1 from
1352
1347
// ```
@@ -1365,24 +1360,6 @@ bool RISCVInstrInfo::optimizeCondBranch(MachineInstr &MI) const {
1365
1360
//
1366
1361
// To make sure this optimization is really beneficial, we only
1367
1362
// optimize for cases where Y had only one use (i.e. only used by the branch).
1368
-
1369
- // Right now we only care about LI (i.e. ADDI x0, imm)
1370
- auto isLoadImm = [](const MachineInstr *MI, int64_t &Imm) -> bool {
1371
- if (MI->getOpcode () == RISCV::ADDI && MI->getOperand (1 ).isReg () &&
1372
- MI->getOperand (1 ).getReg () == RISCV::X0) {
1373
- Imm = MI->getOperand (2 ).getImm ();
1374
- return true ;
1375
- }
1376
- return false ;
1377
- };
1378
- // Either a load from immediate instruction or X0.
1379
- auto isFromLoadImm = [&](const MachineOperand &Op, int64_t &Imm) -> bool {
1380
- if (!Op.isReg ())
1381
- return false ;
1382
- Register Reg = Op.getReg ();
1383
- return Reg.isVirtual () && isLoadImm (MRI.getVRegDef (Reg), Imm);
1384
- };
1385
-
1386
1363
MachineOperand &LHS = MI.getOperand (0 );
1387
1364
MachineOperand &RHS = MI.getOperand (1 );
1388
1365
// Try to find the register for constant Z; return
@@ -1401,7 +1378,6 @@ bool RISCVInstrInfo::optimizeCondBranch(MachineInstr &MI) const {
1401
1378
};
1402
1379
1403
1380
bool Modify = false ;
1404
- int64_t C0;
1405
1381
if (isFromLoadImm (LHS, C0) && MRI.hasOneUse (LHS.getReg ())) {
1406
1382
// Might be case 1.
1407
1383
// Signed integer overflow is UB. (UINT64_MAX is bigger so we don't need
0 commit comments