[llvm] [VectorCombine] Avoid inserting freeze when scalarizing extend-extract if all extracts would lead to UB on poison. (PR #164683)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Sat Nov 1 01:13:29 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);
+               });
----------------
dtcxzyw wrote:

```suggestion
        isGuaranteedToTransferExecutionToSuccessor(Ext->getIterator(), LastExtract->getIterator());
```


https://github.com/llvm/llvm-project/pull/164683


More information about the llvm-commits mailing list