[llvm] [VPlan] Avoid marking Broadcast as uniformity-preserving (PR #195254)
Ramkumar Ramachandra via llvm-commits
llvm-commits at lists.llvm.org
Fri May 1 07:01:47 PDT 2026
artagnon wrote:
> I am not sure if this only works around a different issue. Conceptually, the result of the broadcast is still uniform, we just transition from scalar to vector. Is there perhaps an issue in how we use it?
If you look at the test changes, they come entirely from a select's execute:
```cpp
case Instruction::Select: {
bool OnlyFirstLaneUsed = vputils::onlyFirstLaneUsed(this);
Value *Cond =
State.get(getOperand(0),
OnlyFirstLaneUsed || vputils::isSingleScalar(getOperand(0)));
Value *Op1 = State.get(getOperand(1), OnlyFirstLaneUsed);
Value *Op2 = State.get(getOperand(2), OnlyFirstLaneUsed);
return Builder.CreateSelectFMF(Cond, Op1, Op2, getFastMathFlags(), Name);
}
...
case Instruction::Select: {
VPValue *CondOp = getOperand(0);
Value *Cond = State.get(CondOp, vputils::isSingleScalar(CondOp));
Value *Op0 = State.get(getOperand(1));
Value *Op1 = State.get(getOperand(2));
Value *Sel = State.Builder.CreateSelect(Cond, Op0, Op1);
State.set(this, Sel);
if (auto *I = dyn_cast<Instruction>(Sel)) {
if (isa<FPMathOperator>(I))
applyFlags(*I);
applyMetadata(*I);
}
```
Here, we do need isSingleScalar to determine whether to get the scalar or vector value of the select condition. If you think about it, isSingleScalar is an "analysis" that recursively goes through the operands of a recipe to return information about whether it was "unnecessarily widened" (this can be seen clearly with the example of wide recipes). Broadcasts, however, are introduced out of necessity, when we _require_ a vector value but only a scalar one is present -- they do not fall in the class of "unnecessarily widened recipes". Just like any other recipe, they can be "simplified" when all users are extracts, cse'd, and licm'd.
The context for this change is that I'm trying to write an analysis that makes principled widen/replicate/single-scalar decisions in an optimal manner, replacing the existing recursive only-first-lane-used/only-scalar-values-used reasoning. So far, I have reasoned that isSingleScalar < onlyFirstLaneUsed < onlyScalarValuesUsed (the LHS implies the RHS) -- the onlyFirstLaneUsed < onlyScalarValuesUsed already holds, although incidentally: a ton of stuff would break if this invariant weren't maintained; I have a local change to make isSingleScalar < onlyFirstLaneUsed, and am working through the test changes. My current thinking is that scalar-to-vector recipes fall in the second class of onlyFirstLaneUsed (and indeed Broadcast and BuildVector are present in VPI::usesFirstLaneOnly), while vector-to-scalar recipes fall in the first class of isSingleScalar.
Broader understanding: isSingleScalar recursively goes through operands, while onlyFirstLaneUsed recursively goes through users in an inverse walk. There may be special recipe-specific leaf cases, but in general, the leaf cases must be live-ins. All the widening/replicate/single-scalar information must hence be inferable by simply analyzing the Plan.
https://github.com/llvm/llvm-project/pull/195254
More information about the llvm-commits
mailing list