@@ -371,56 +371,71 @@ Constant *InstCostVisitor::visitPHINode(PHINode &I) {
371371 return nullptr ;
372372 }
373373
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.
376375 for (PHINode *Phi : UnknownIncomingValues)
377376 discoverTransitivelyIncomngValues (TransitivePHIs, Phi, 1 );
378377
379-
380378 // A nested set of PHINodes can be constantfolded if:
381379 // - It has a constant input.
382380 // - 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;
385391
386392 for (unsigned I = 0 , E = PN->getNumIncomingValues (); I != E; ++I) {
387393 Value *V = PN->getIncomingValue (I);
388-
389394 // Disregard self-references and dead incoming values.
390395 if (auto *Inst = dyn_cast<Instruction>(V))
391396 if (Inst == PN || DeadBlocks.contains (PN->getIncomingBlock (I)))
392397 continue ;
393398
394399 if (Constant *C = findConstantFor (V, KnownConstants)) {
395- if (!Const)
400+ if (!Const) {
396401 Const = C;
402+ Status = FoundConst;
403+ }
397404 // Not all incoming values are the same constant. Bail immediately.
398405 if (C != Const)
399- return nullptr ;
406+ return Failed ;
400407 continue ;
401408 }
402409 if (auto *Phi = dyn_cast<PHINode>(V)) {
403410 // It's not a Transitive phi. Bail out.
404411 if (!TransitivePHIs.contains (Phi))
405- return nullptr ;
412+ return Failed ;
406413 continue ;
407414 }
408415
409416 // We can't reason about anything else.
410- return nullptr ;
417+ return Failed ;
411418 }
412- return Const ;
419+ return Status ;
413420 };
414421
415422 // All TransitivePHIs have to be the SAME constant.
416423 Constant *Retval = nullptr ;
417424 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) {
420428 Retval = Const;
421- else if (Retval != Const)
429+ continue ;
430+ }
431+ // Found more than one constant, can't fold.
432+ if (Retval != Const)
422433 return nullptr ;
423434 }
435+ // Found something "wrong", can't fold.
436+ else if (Status == Failed)
437+ return nullptr ;
438+ assert (Status == KeepGoing && " Status should be KeepGoing here" );
424439 }
425440
426441 return Retval;
0 commit comments