@@ -1285,40 +1285,96 @@ Instruction *InstCombinerImpl::foldSelectValueEquivalence(SelectInst &Sel,
1285
1285
Swapped = true ;
1286
1286
}
1287
1287
1288
- // In X == Y ? f(X) : Z, try to evaluate f(Y) and replace the operand.
1289
- // Make sure Y cannot be undef though, as we might pick different values for
1290
- // undef in the icmp and in f(Y). Additionally, take care to avoid replacing
1291
- // X == Y ? X : Z with X == Y ? Y : Z, as that would lead to an infinite
1292
- // replacement cycle.
1293
1288
Value *CmpLHS = Cmp.getOperand (0 ), *CmpRHS = Cmp.getOperand (1 );
1294
- if (TrueVal != CmpLHS &&
1295
- isGuaranteedNotToBeUndefOrPoison (CmpRHS, SQ.AC , &Sel, &DT)) {
1296
- if (Value *V = simplifyWithOpReplaced (TrueVal, CmpLHS, CmpRHS, SQ,
1297
- /* AllowRefinement */ true ))
1298
- // Require either the replacement or the simplification result to be a
1299
- // constant to avoid infinite loops.
1300
- // FIXME: Make this check more precise.
1301
- if (isa<Constant>(CmpRHS) || isa<Constant>(V))
1302
- return replaceOperand (Sel, Swapped ? 2 : 1 , V);
1289
+ auto ReplaceLHSOpWithRHSOp = [&](Value *OldOp,
1290
+ Value *NewOp) -> Instruction * {
1291
+ // In X == Y ? f(X) : Z, try to evaluate f(Y) and replace the operand.
1292
+ // Take care to avoid replacing X == Y ? X : Z with X == Y ? Y : Z, as that
1293
+ // would lead to an infinite replacement cycle.
1294
+ // If we will be able to evaluate f(Y) to a constant, we can allow undef,
1295
+ // otherwise Y cannot be undef as we might pick different values for undef
1296
+ // in the icmp and in f(Y).
1297
+ if (TrueVal == OldOp)
1298
+ return nullptr ;
1299
+
1300
+ std::optional<bool > IsNeverUndefCached;
1301
+ auto IsNeverUndef = [&](Value *Op) {
1302
+ if (!IsNeverUndefCached.has_value ())
1303
+ IsNeverUndefCached =
1304
+ isGuaranteedNotToBeUndefOrPoison (Op, SQ.AC , &Sel, &DT);
1305
+ return *IsNeverUndefCached;
1306
+ };
1303
1307
1308
+ if (Value *V = simplifyWithOpReplaced (TrueVal, OldOp, NewOp, SQ,
1309
+ /* AllowRefinement */ true )) {
1310
+ // Need some gurantees about the new simplified op to ensure we don't inf
1311
+ // loop.
1312
+ // If we simplify to a constant, replace.
1313
+ bool ShouldReplace = match (V, m_ImmConstant ());
1314
+ bool NeedsNoUndef = !ShouldReplace;
1315
+ // Or replace if either NewOp is a constant
1316
+ if (!ShouldReplace && match (NewOp, m_ImmConstant ()))
1317
+ ShouldReplace = true ;
1318
+ // Or if we end up simplifying f(Y) -> Y i.e: Old & New -> New & New ->
1319
+ // New.
1320
+ if (!ShouldReplace && V == NewOp)
1321
+ ShouldReplace = true ;
1322
+
1323
+ // Finally, if we are going to create a new one-use instruction, replace.
1324
+ if (!ShouldReplace && isa<Instruction>(OldOp) && OldOp->hasNUses (2 ) &&
1325
+ (!isa<Instruction>(NewOp) || !NewOp->hasOneUse ()))
1326
+ ShouldReplace = true ;
1327
+
1328
+ // Unless we simplify the new instruction to a constant, need to ensure Y
1329
+ // is not undef.
1330
+ if (NeedsNoUndef && ShouldReplace)
1331
+ ShouldReplace = IsNeverUndef (NewOp);
1332
+
1333
+ if (ShouldReplace)
1334
+ return replaceOperand (Sel, Swapped ? 2 : 1 , V);
1335
+ }
1336
+ // If we can't simplify, but we will either:
1337
+ // 1) Create a new binop where both ops are NewOp i.e (add x, y) is "worse"
1338
+ // than (add y, y) in this case, wait until the second call so we don't
1339
+ // miss a one-use simplification.
1340
+ // 2) Create a new one-use instruction.
1341
+ // proceed.
1342
+ else if (match (TrueVal, m_c_BinOp (m_Specific (OldOp), m_Specific (NewOp))) ||
1343
+ (isa<Instruction>(TrueVal) && TrueVal->hasOneUse () &&
1344
+ isa<Instruction>(OldOp) && OldOp->hasNUses (2 ) &&
1345
+ (!isa<Instruction>(NewOp) || !NewOp->hasOneUse ()))) {
1346
+ auto *TrueIns = cast<Instruction>(TrueVal);
1347
+ for (unsigned OpIdx = 0 ; OpIdx < TrueIns->getNumOperands (); ++OpIdx) {
1348
+ if (TrueIns->getOperand (OpIdx) == OldOp) {
1349
+ // Need to ensure NewOp is noundef (same reason as above). Wait until
1350
+ // the last moment to do this check as it can be relatively expensive.
1351
+ if (!IsNeverUndef (NewOp))
1352
+ break ;
1353
+ TrueIns->setOperand (OpIdx, NewOp);
1354
+ return replaceOperand (Sel, Swapped ? 2 : 1 , TrueIns);
1355
+ }
1356
+ }
1357
+ }
1304
1358
// Even if TrueVal does not simplify, we can directly replace a use of
1305
1359
// CmpLHS with CmpRHS, as long as the instruction is not used anywhere
1306
1360
// else and is safe to speculatively execute (we may end up executing it
1307
1361
// with different operands, which should not cause side-effects or trigger
1308
1362
// undefined behavior). Only do this if CmpRHS is a constant, as
1309
1363
// profitability is not clear for other cases.
1310
1364
// FIXME: Support vectors.
1311
- if (match (CmpRHS, m_ImmConstant ()) && !match (CmpLHS, m_ImmConstant ()) &&
1312
- !Cmp.getType ()->isVectorTy ())
1313
- if (replaceInInstruction (TrueVal, CmpLHS, CmpRHS))
1365
+ if (OldOp == CmpLHS && match (NewOp, m_ImmConstant ()) &&
1366
+ !match (OldOp, m_ImmConstant ()) && !Cmp.getType ()->isVectorTy () &&
1367
+ IsNeverUndef (NewOp))
1368
+ if (replaceInInstruction (TrueVal, OldOp, NewOp))
1314
1369
return &Sel;
1315
- }
1316
- if (TrueVal != CmpRHS &&
1317
- isGuaranteedNotToBeUndefOrPoison (CmpLHS, SQ.AC , &Sel, &DT))
1318
- if (Value *V = simplifyWithOpReplaced (TrueVal, CmpRHS, CmpLHS, SQ,
1319
- /* AllowRefinement */ true ))
1320
- if (isa<Constant>(CmpLHS) || isa<Constant>(V))
1321
- return replaceOperand (Sel, Swapped ? 2 : 1 , V);
1370
+
1371
+ return nullptr ;
1372
+ };
1373
+
1374
+ if (Instruction *R = ReplaceLHSOpWithRHSOp (CmpLHS, CmpRHS))
1375
+ return R;
1376
+ if (Instruction *R = ReplaceLHSOpWithRHSOp (CmpRHS, CmpLHS))
1377
+ return R;
1322
1378
1323
1379
auto *FalseInst = dyn_cast<Instruction>(FalseVal);
1324
1380
if (!FalseInst)
0 commit comments