[llvm] [VPlan] Lower safe uniform load to unconditional scalar load (PR #216767)
Luke Lau via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 27 04:22:37 PDT 2026
================
@@ -5499,6 +5480,29 @@ void VPlanTransforms::makeMemOpWideningDecisions(VPlan &Plan, VFRange &Range,
return ReplaceWith(VPI, StoreR);
});
+ // Lower safe uniform (potentially masked) loads to unconditional scalar
+ // loads.
+ VPlanTransforms::runPass(
+ "lowerSafeUniformLoads", ProcessSubset, Plan, [&](VPInstruction *VPI) {
+ if (VPI->getOpcode() != Instruction::Load)
+ return false;
+ VPValue *Addr = VPI->getOperand(0);
+ if (!vputils::isUniformAcrossVFsAndUFs(Addr))
+ return false;
+ auto &LI = cast<LoadInst>(*VPI->getUnderlyingInstr());
+ Value *Underlying = Addr->getUnderlyingValue();
+ if (!Underlying || !isSafeToLoadUnconditionally(
+ Underlying, LI.getType(), LI.getAlign(),
+ Plan.getDataLayout(), &LI,
+ /*AC=*/nullptr, /*DT=*/nullptr, &CostCtx.TLI))
+ return false;
----------------
lukel97 wrote:
Is it safe to use this underlying value based analysis here? I think isSafeToLoadUnconditionally scans the underlying basic block to see if another load was already performed at that address and allows it if there is one. In this example it sees that `%a` is in the same block as `%b` so `%b` gets transformed to an unconditional load even though it needs to be masked by `%cmp`:
```llvm
define void @load_safe_only_via_predicated_load(ptr noalias %out, ptr noalias %cond, ptr %p, i64 %n) {
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %latch ]
%cond.gep = getelementptr inbounds i32, ptr %cond, i64 %iv
%c = load i32, ptr %cond.gep, align 4
%cmp = icmp ne i32 %c, 0
br i1 %cmp, label %if.then, label %latch
if.then:
%a = load i32, ptr %p, align 4
%b = load i32, ptr %p, align 4
%sum = add i32 %a, %b
%out.gep = getelementptr inbounds i32, ptr %out, i64 %iv
store i32 %sum, ptr %out.gep, align 4
br label %latch
latch:
%iv.next = add nuw nsw i64 %iv, 1
%ec = icmp eq i64 %iv.next, %n
br i1 %ec, label %exit, label %loop
exit:
ret void
}
```
I think we can probably use `isDereferenceableAndAlignedInLoop` since that operates on SCEVs only and doesn't check the underlying value
https://github.com/llvm/llvm-project/pull/216767
More information about the llvm-commits
mailing list