Skip to content

Commit ad3bf33

Browse files
Improve constant-foldign of nested phinodes.
1 parent a942a55 commit ad3bf33

File tree

1 file changed

+29
-14
lines changed

1 file changed

+29
-14
lines changed

llvm/lib/Transforms/IPO/FunctionSpecialization.cpp

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)