[llvm] [Uniformity] Avoid marking all PHIs as divergent in join blocks (PR #157808)
Carl Ritson via llvm-commits
llvm-commits at lists.llvm.org
Mon Oct 6 01:03:07 PDT 2025
================
@@ -917,19 +919,61 @@ void GenericUniformityAnalysisImpl<ContextT>::taintAndPushAllDefs(
/// Mark divergent phi nodes in a join block
template <typename ContextT>
void GenericUniformityAnalysisImpl<ContextT>::taintAndPushPhiNodes(
- const BlockT &JoinBlock) {
+ const BlockT &JoinBlock, const BlockT &DivTermBlock,
+ const DivergenceDescriptorT &DivDesc) {
LLVM_DEBUG(dbgs() << "taintAndPushPhiNodes in " << Context.print(&JoinBlock)
<< "\n");
for (const auto &Phi : JoinBlock.phis()) {
- // FIXME: The non-undef value is not constant per se; it just happens to be
- // uniform and may not dominate this PHI. So assuming that the same value
- // reaches along all incoming edges may itself be undefined behaviour. This
- // particular interpretation of the undef value was added to
- // DivergenceAnalysis in the following review:
- //
- // https://reviews.llvm.org/D19013
- if (ContextT::isConstantOrUndefValuePhi(Phi))
+ // Attempt to maintain uniformity for PHIs by considering control
+ // dependencies before marking them.
+ SmallVector<ConstValueRefT> Values;
+ SmallVector<const BlockT *> Blocks;
+ Context.getPhiInputs(Phi, Values, Blocks);
+ assert(Blocks.size() == Values.size());
+
+ // Allow an empty Blocks/Values list to signify getPhiInputs is not
+ // implemented; in which case no uniformity is possible.
+ bool Uniform = !Values.empty();
+
+ std::optional<ConstValueRefT> PhiCommon, PathCommon;
+ bool HasSingleValue = true;
+ for (unsigned I = 0; I < Blocks.size() && (HasSingleValue || Uniform);
+ ++I) {
+ // FIXME: We assume undefs are uniform and/or do not dominate the PHI
+ // in the presence of other constant or uniform values.
+ // This particular interpretation of the undef value was added to
+ // DivergenceAnalysis in the following review:
+ //
+ // https://reviews.llvm.org/D19013
+ if (!Values[I])
+ continue;
+
+ // Track common value for all inputs.
+ if (!PhiCommon)
+ PhiCommon = Values[I];
+ else if (Values[I] != *PhiCommon)
+ HasSingleValue = false;
+
+ // Only consider predecessors on divergent path.
+ if (Blocks[I] != &DivTermBlock &&
+ !DivDesc.BlockLabels.lookup_or(Blocks[I], nullptr))
+ continue;
+
+ // Phi uniformity is maintained if all values on divergent path match.
+ if (!PathCommon)
+ PathCommon = Values[I];
+ else if (Values[I] != *PathCommon)
+ Uniform = false;
----------------
perlfu wrote:
We can only break here if `HasSingleValue` is also false -- the loop condition will handle this.
https://github.com/llvm/llvm-project/pull/157808
More information about the llvm-commits
mailing list