@@ -1059,49 +1059,30 @@ static bool hoistChecksInLoop(DominanceInfo *DT, DominanceInfoNode *DTNode,
1059
1059
return Changed;
1060
1060
}
1061
1061
1062
- // / Match a range check that is exactly within the bounds of the induction
1063
- // / variable.
1064
- static bool matchRangeCheck (CondFailInst *CondFail, InductionInfo &IndVar, DominanceInfo *DT) {
1062
+
1063
+ // / A dominating cond_fail on the same value ensures that this value is false.
1064
+ static bool isValueKnownFalseAt (SILValue Val, SILInstruction *At,
1065
+ DominanceInfo *DT) {
1066
+ auto *Inst = dyn_cast<SILInstruction>(Val);
1067
+ if (!Inst ||
1068
+ std::next (SILBasicBlock::iterator (Inst)) == Inst->getParent ()->end ())
1069
+ return false ;
1070
+ auto *CF = dyn_cast<CondFailInst>(std::next (SILBasicBlock::iterator (Inst)));
1071
+ return CF && DT->properlyDominates (CF, At);
1072
+ }
1073
+
1074
+ // / Based on the induction variable information this comparison is known to be
1075
+ // / true.
1076
+ static bool isComparisonKnownTrue (BuiltinInst *Builtin, InductionInfo &IndVar) {
1065
1077
if (!IndVar.IsOverflowCheckInserted ||
1066
1078
IndVar.Cmp != BuiltinValueKind::ICMP_EQ)
1067
1079
return false ;
1068
-
1069
- SILValue CheckedCondition;
1070
- // This check matches a pattern that includes a predicate that is checked
1071
- // outside of the loop to be false.
1072
- if (match (CondFail->getOperand (),
1073
- m_Or (m_Or (m_SILValue (CheckedCondition),
1074
- m_ApplyInst (BuiltinValueKind::Xor,
1075
- m_ApplyInst (BuiltinValueKind::ICMP_SLE,
1076
- m_Specific (IndVar.Start ),
1077
- m_Specific (IndVar.HeaderVal )),
1078
- m_One ())),
1079
- m_ApplyInst (BuiltinValueKind::Xor,
1080
- m_ApplyInst (BuiltinValueKind::ICMP_SLT,
1081
- m_Specific (IndVar.HeaderVal ),
1082
- m_Specific (IndVar.End )),
1083
- m_One ())))) {
1084
- auto *Inst = dyn_cast<SILInstruction>(CheckedCondition);
1085
- if (Inst &&
1086
- std::next (SILBasicBlock::iterator (Inst)) != Inst->getParent ()->end ()) {
1087
- auto *CF =
1088
- dyn_cast<CondFailInst>(std::next (SILBasicBlock::iterator (Inst)));
1089
- if (CF && DT->properlyDominates (CF, CondFail))
1090
- return true ;
1091
- }
1092
- }
1093
-
1094
- return match (CondFail->getOperand (),
1095
- m_Or (m_ApplyInst (BuiltinValueKind::Xor,
1096
- m_ApplyInst (BuiltinValueKind::ICMP_SLE,
1097
- m_Specific (IndVar.Start ),
1098
- m_Specific (IndVar.HeaderVal )),
1099
- m_One ()),
1100
- m_ApplyInst (BuiltinValueKind::Xor,
1101
- m_ApplyInst (BuiltinValueKind::ICMP_SLT,
1102
- m_Specific (IndVar.HeaderVal ),
1103
- m_Specific (IndVar.End )),
1104
- m_One ())));
1080
+ return match (Builtin,
1081
+ m_ApplyInst (BuiltinValueKind::ICMP_SLE, m_Specific (IndVar.Start ),
1082
+ m_Specific (IndVar.HeaderVal ))) ||
1083
+ match (Builtin, m_ApplyInst (BuiltinValueKind::ICMP_SLT,
1084
+ m_Specific (IndVar.HeaderVal ),
1085
+ m_Specific (IndVar.End )));
1105
1086
}
1106
1087
1107
1088
// / Analyse the loop for arrays that are not modified and perform dominator tree
@@ -1152,7 +1133,20 @@ static bool hoistBoundsChecks(SILLoop *Loop, DominanceInfo *DT, SILLoopInfo *LI,
1152
1133
if (!ExitingBlk || !Latch || !ExitBlk) {
1153
1134
DEBUG (llvm::dbgs ()
1154
1135
<< " No single exiting block or latch found\n " );
1155
- return Changed;
1136
+ if (!Latch)
1137
+ return Changed;
1138
+
1139
+ // Look back a split edge.
1140
+ if (!Loop->isLoopExiting (Latch) && Latch->getSinglePredecessor () &&
1141
+ Loop->isLoopExiting (Latch->getSinglePredecessor ()))
1142
+ Latch = Latch->getSinglePredecessor ();
1143
+ if (Loop->isLoopExiting (Latch) && Latch->getSuccessors ().size () == 2 ) {
1144
+ ExitingBlk = Latch;
1145
+ ExitBlk = Loop->contains (Latch->getSuccessors ()[0 ])
1146
+ ? Latch->getSuccessors ()[1 ]
1147
+ : Latch->getSuccessors ()[0 ];
1148
+ DEBUG (llvm::dbgs () << " Found a latch ...\n " );
1149
+ } else return Changed;
1156
1150
}
1157
1151
1158
1152
DEBUG (Preheader->getParent ()->dump ());
@@ -1167,26 +1161,51 @@ static bool hoistBoundsChecks(SILLoop *Loop, DominanceInfo *DT, SILLoopInfo *LI,
1167
1161
// Hoist the overflow check of induction variables out of the loop. This also
1168
1162
// needs to happen for memory safety. Also remove superflous range checks.
1169
1163
if (IVarsFound) {
1170
- SmallPtrSet<SILInstruction *, 8 > InstsToDelete;
1164
+ SILValue TrueVal;
1165
+ SILValue FalseVal;
1171
1166
for (auto *Arg: Header->getBBArgs ()) {
1172
1167
if (auto *IV = IndVars[Arg]) {
1173
1168
SILBuilderWithScope B (Preheader->getTerminator (), IV->getInstruction ());
1174
1169
IV->checkOverflow (B);
1175
1170
1176
1171
if (!IV->IsOverflowCheckInserted )
1177
1172
continue ;
1178
-
1179
- for (auto &Inst : *Header) {
1180
- auto *CondFail = dyn_cast<CondFailInst>(&Inst);
1181
- if (!CondFail)
1182
- continue ;
1183
- if (matchRangeCheck (CondFail, *IV, DT))
1184
- InstsToDelete.insert (CondFail);
1185
- }
1173
+ for (auto *BB : Loop->getBlocks ())
1174
+ for (auto &Inst : *BB) {
1175
+ auto *Builtin = dyn_cast<BuiltinInst>(&Inst);
1176
+ if (!Builtin)
1177
+ continue ;
1178
+ if (isComparisonKnownTrue (Builtin, *IV)) {
1179
+ if (!TrueVal)
1180
+ TrueVal = SILValue (B.createIntegerLiteral (
1181
+ Builtin->getLoc (), Builtin->getType (), -1 ));
1182
+ Builtin->replaceAllUsesWith (TrueVal);
1183
+ Changed = true ;
1184
+ continue ;
1185
+ }
1186
+ // Check whether a dominating check of the condition let's us
1187
+ // replace
1188
+ // the condition by false.
1189
+ SILValue Left, Right;
1190
+ if (match (Builtin, m_Or (m_SILValue (Left), m_SILValue (Right)))) {
1191
+ if (isValueKnownFalseAt (Left, Builtin, DT)) {
1192
+ if (!FalseVal)
1193
+ FalseVal = SILValue (B.createIntegerLiteral (
1194
+ Builtin->getLoc (), Builtin->getType (), 0 ));
1195
+ Builtin->setOperand (0 , FalseVal);
1196
+ Changed = true ;
1197
+ }
1198
+ if (isValueKnownFalseAt (Right, Builtin, DT)) {
1199
+ if (!FalseVal)
1200
+ FalseVal = SILValue (B.createIntegerLiteral (
1201
+ Builtin->getLoc (), Builtin->getType (), 0 ));
1202
+ Builtin->setOperand (1 , FalseVal);
1203
+ Changed = true ;
1204
+ }
1205
+ }
1206
+ }
1186
1207
}
1187
1208
}
1188
- for (auto *Inst : InstsToDelete)
1189
- Inst->eraseFromParent ();
1190
1209
}
1191
1210
1192
1211
DEBUG (Preheader->getParent ()->dump ());
0 commit comments