[llvm] [VectorCombine] Avoid inserting freeze when scalarizing extend-extract if all extracts would lead to UB on poison. (PR #164683)
Julian Nagele via llvm-commits
llvm-commits at lists.llvm.org
Sat Nov 1 08:52:22 PDT 2025
================
@@ -2017,8 +2017,35 @@ bool VectorCombine::scalarizeExtExtract(Instruction &I) {
Value *ScalarV = Ext->getOperand(0);
if (!isGuaranteedNotToBePoison(ScalarV, &AC, dyn_cast<Instruction>(ScalarV),
- &DT))
- ScalarV = Builder.CreateFreeze(ScalarV);
+ &DT)) {
+ // Check if all lanes are extracted and all extracts trigger UB on poison.
+ // If so, we do not need to insert a freeze.
+ SmallDenseSet<ConstantInt *, 8> ExtractedLanes;
+ bool AllExtractsTriggerUB = true;
+ ExtractElementInst *LastExtract = nullptr;
+ BasicBlock *ExtBB = Ext->getParent();
+ for (User *U : Ext->users()) {
+ auto *Extract = cast<ExtractElementInst>(U);
+ if (Extract->getParent() != ExtBB || !programUndefinedIfPoison(Extract)) {
+ AllExtractsTriggerUB = false;
+ break;
+ }
+ ExtractedLanes.insert(cast<ConstantInt>(Extract->getIndexOperand()));
+ if (!LastExtract || LastExtract->comesBefore(Extract))
+ LastExtract = Extract;
+ }
+ // Check that the last extract (and hence all previous ones) are guaranteed
+ // to execute if Ext executes.
+ AllExtractsTriggerUB =
+ AllExtractsTriggerUB &&
+ all_of(make_range(Ext->getIterator(), LastExtract->getIterator()),
+ [](Instruction &I) {
+ return isGuaranteedToTransferExecutionToSuccessor(&I);
+ });
+ if (!AllExtractsTriggerUB ||
+ ExtractedLanes.size() != DstTy->getNumElements())
----------------
juliannagele wrote:
I'm not sure we can drop this one, I think we still need to check that all lanes are extracted, which is different from all extracts executing: see https://alive2.llvm.org/ce/z/iPLATi and test `zext_v4i8_not_all_lanes_used`
https://github.com/llvm/llvm-project/pull/164683
More information about the llvm-commits
mailing list