@@ -371,56 +371,71 @@ Constant *InstCostVisitor::visitPHINode(PHINode &I) {
371
371
return nullptr ;
372
372
}
373
373
374
- // Try to see if we can collect a nest of transitive phis. Bail if
375
- // it's too complex.
374
+ // Try to see if we can collect a nest of transitive phis.
376
375
for (PHINode *Phi : UnknownIncomingValues)
377
376
discoverTransitivelyIncomngValues (TransitivePHIs, Phi, 1 );
378
377
379
-
380
378
// A nested set of PHINodes can be constantfolded if:
381
379
// - It has a constant input.
382
380
// - It is always the SAME constant.
383
- auto canConstantFoldNestedPhi = [&](PHINode *PN) -> Constant * {
384
- Constant *Const = nullptr ;
381
+ // - All the nodes are part of the nest, or a constant.
382
+ // Later we will check that the constant is always the same one.
383
+ Constant *Const = nullptr ;
384
+ enum FoldStatus {
385
+ Failed, // Stop, this can't be folded.
386
+ KeepGoing, // Maybe can be folded, didn't find a constant.
387
+ FoundConst // Maybe can be folded, we found constant.
388
+ };
389
+ auto canConstantFoldNestedPhi = [&](PHINode *PN) -> FoldStatus {
390
+ FoldStatus Status = KeepGoing;
385
391
386
392
for (unsigned I = 0 , E = PN->getNumIncomingValues (); I != E; ++I) {
387
393
Value *V = PN->getIncomingValue (I);
388
-
389
394
// Disregard self-references and dead incoming values.
390
395
if (auto *Inst = dyn_cast<Instruction>(V))
391
396
if (Inst == PN || DeadBlocks.contains (PN->getIncomingBlock (I)))
392
397
continue ;
393
398
394
399
if (Constant *C = findConstantFor (V, KnownConstants)) {
395
- if (!Const)
400
+ if (!Const) {
396
401
Const = C;
402
+ Status = FoundConst;
403
+ }
397
404
// Not all incoming values are the same constant. Bail immediately.
398
405
if (C != Const)
399
- return nullptr ;
406
+ return Failed ;
400
407
continue ;
401
408
}
402
409
if (auto *Phi = dyn_cast<PHINode>(V)) {
403
410
// It's not a Transitive phi. Bail out.
404
411
if (!TransitivePHIs.contains (Phi))
405
- return nullptr ;
412
+ return Failed ;
406
413
continue ;
407
414
}
408
415
409
416
// We can't reason about anything else.
410
- return nullptr ;
417
+ return Failed ;
411
418
}
412
- return Const ;
419
+ return Status ;
413
420
};
414
421
415
422
// All TransitivePHIs have to be the SAME constant.
416
423
Constant *Retval = nullptr ;
417
424
for (PHINode *Phi : TransitivePHIs) {
418
- if (Constant *Const = canConstantFoldNestedPhi (Phi)) {
419
- if (!Retval)
425
+ FoldStatus Status = canConstantFoldNestedPhi (Phi);
426
+ if (Status == FoundConst) {
427
+ if (!Retval) {
420
428
Retval = Const;
421
- else if (Retval != Const)
429
+ continue ;
430
+ }
431
+ // Found more than one constant, can't fold.
432
+ if (Retval != Const)
422
433
return nullptr ;
423
434
}
435
+ // Found something "wrong", can't fold.
436
+ else if (Status == Failed)
437
+ return nullptr ;
438
+ assert (Status == KeepGoing && " Status should be KeepGoing here" );
424
439
}
425
440
426
441
return Retval;
0 commit comments