[llvm] [LoopVectorize] Add an option to test potential issues with VPlan (PR #121154)

via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 26 08:19:18 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-vectorizers

Author: Danila Malyutin (danilaml)

<details>
<summary>Changes</summary>

Add a way to test for https://github.com/llvm/llvm-project/issues/115169.

---
Full diff: https://github.com/llvm/llvm-project/pull/121154.diff


2 Files Affected:

- (modified) llvm/lib/Transforms/Vectorize/LoopVectorize.cpp (+7-1) 
- (added) llvm/test/Transforms/LoopVectorize/vplan-speculate-loads.ll (+96) 


``````````diff
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index cb828b738d310f..286cf645643a14 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -350,6 +350,11 @@ static cl::opt<bool> PreferPredicatedReductionSelect(
     cl::desc(
         "Prefer predicating a reduction operation over an after loop select."));
 
+static cl::opt<bool> CheckSpeculatabilityAtUse(
+    "check-specutalability-at-use", cl::init(false), cl::Hidden,
+    cl::desc("Use instruction as a context when checking if it is safe to"
+             " speculate. This is used for testing purposes only."));
+
 namespace llvm {
 cl::opt<bool> EnableVPlanNativePath(
     "enable-vplan-native-path", cl::Hidden,
@@ -3448,8 +3453,9 @@ bool LoopVectorizationCostModel::isPredicatedInst(Instruction *I) const {
   // If predication is not needed, avoid it.
   // TODO: We can use the loop-preheader as context point here and get
   // context sensitive reasoning for isSafeToSpeculativelyExecute.
+  Instruction *CtxI = CheckSpeculatabilityAtUse ? I->getNextNode() : nullptr;
   if (!blockNeedsPredicationForAnyReason(I->getParent()) ||
-      isSafeToSpeculativelyExecute(I) ||
+      isSafeToSpeculativelyExecute(I, CtxI) ||
       (isa<LoadInst, StoreInst, CallInst>(I) && !Legal->isMaskRequired(I)) ||
       isa<BranchInst, SwitchInst, PHINode, AllocaInst>(I))
     return false;
diff --git a/llvm/test/Transforms/LoopVectorize/vplan-speculate-loads.ll b/llvm/test/Transforms/LoopVectorize/vplan-speculate-loads.ll
new file mode 100644
index 00000000000000..a3eda8f95064d4
--- /dev/null
+++ b/llvm/test/Transforms/LoopVectorize/vplan-speculate-loads.ll
@@ -0,0 +1,96 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt < %s  -S -passes=loop-vectorize -force-vector-width=2 -check-specutalability-at-use | FileCheck %s
+
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128-ni:1-p2:32:8:8:32-ni:2"
+target triple = "x86_64-unknown-linux-gnu"
+
+; MISCOMPILE: this code currently miscompiles by introducing loads from poison pointers
+define void @test(i1 %arg, i64 %arg1, ptr %arg2) {
+; CHECK-LABEL: define void @test(
+; CHECK-SAME: i1 [[ARG:%.*]], i64 [[ARG1:%.*]], ptr [[ARG2:%.*]]) {
+; CHECK-NEXT:  [[BB:.*]]:
+; CHECK-NEXT:    br i1 false, label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]
+; CHECK:       [[VECTOR_PH]]:
+; CHECK-NEXT:    [[BROADCAST_SPLATINSERT:%.*]] = insertelement <2 x i1> poison, i1 [[ARG]], i64 0
+; CHECK-NEXT:    [[BROADCAST_SPLAT:%.*]] = shufflevector <2 x i1> [[BROADCAST_SPLATINSERT]], <2 x i1> poison, <2 x i32> zeroinitializer
+; CHECK-NEXT:    br label %[[VECTOR_BODY:.*]]
+; CHECK:       [[VECTOR_BODY]]:
+; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[PRED_LOAD_CONTINUE2:.*]] ]
+; CHECK-NEXT:    [[TMP0:%.*]] = xor <2 x i1> [[BROADCAST_SPLAT]], splat (i1 true)
+; CHECK-NEXT:    [[TMP1:%.*]] = extractelement <2 x i1> [[TMP0]], i32 0
+; CHECK-NEXT:    br i1 [[TMP1]], label %[[PRED_LOAD_IF:.*]], label %[[PRED_LOAD_CONTINUE:.*]]
+; CHECK:       [[PRED_LOAD_IF]]:
+; CHECK-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[ARG2]], align 8, !nonnull [[META0:![0-9]+]], !dereferenceable_or_null [[META1:![0-9]+]], !align [[META1]]
+; CHECK-NEXT:    br label %[[PRED_LOAD_CONTINUE]]
+; CHECK:       [[PRED_LOAD_CONTINUE]]:
+; CHECK-NEXT:    [[TMP9:%.*]] = phi ptr [ poison, %[[VECTOR_BODY]] ], [ [[TMP2]], %[[PRED_LOAD_IF]] ]
+; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <2 x i1> [[TMP0]], i32 1
+; CHECK-NEXT:    br i1 [[TMP4]], label %[[PRED_LOAD_IF1:.*]], label %[[PRED_LOAD_CONTINUE2]]
+; CHECK:       [[PRED_LOAD_IF1]]:
+; CHECK-NEXT:    [[TMP5:%.*]] = load ptr, ptr [[ARG2]], align 8, !nonnull [[META0]], !dereferenceable_or_null [[META1]], !align [[META1]]
+; CHECK-NEXT:    br label %[[PRED_LOAD_CONTINUE2]]
+; CHECK:       [[PRED_LOAD_CONTINUE2]]:
+; CHECK-NEXT:    [[TMP12:%.*]] = phi ptr [ poison, %[[PRED_LOAD_CONTINUE]] ], [ [[TMP5]], %[[PRED_LOAD_IF1]] ]
+; CHECK-NEXT:    [[TMP15:%.*]] = load i32, ptr [[TMP9]], align 8
+; CHECK-NEXT:    [[TMP16:%.*]] = load i32, ptr [[TMP12]], align 8
+; CHECK-NEXT:    [[TMP14:%.*]] = insertelement <2 x i32> poison, i32 [[TMP15]], i32 0
+; CHECK-NEXT:    [[TMP10:%.*]] = insertelement <2 x i32> [[TMP14]], i32 [[TMP16]], i32 1
+; CHECK-NEXT:    [[TMP11:%.*]] = add <2 x i32> [[TMP10]], splat (i32 1)
+; CHECK-NEXT:    [[PREDPHI:%.*]] = select <2 x i1> [[BROADCAST_SPLAT]], <2 x i32> zeroinitializer, <2 x i32> [[TMP11]]
+; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2
+; CHECK-NEXT:    [[TMP22:%.*]] = icmp eq i64 [[INDEX_NEXT]], 100
+; CHECK-NEXT:    br i1 [[TMP22]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP2:![0-9]+]]
+; CHECK:       [[MIDDLE_BLOCK]]:
+; CHECK-NEXT:    [[TMP13:%.*]] = extractelement <2 x i32> [[PREDPHI]], i32 1
+; CHECK-NEXT:    br i1 false, label %[[BB8:.*]], label %[[SCALAR_PH]]
+; CHECK:       [[SCALAR_PH]]:
+; CHECK-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i64 [ 100, %[[MIDDLE_BLOCK]] ], [ 0, %[[BB]] ]
+; CHECK-NEXT:    br label %[[BB3:.*]]
+; CHECK:       [[BB3]]:
+; CHECK-NEXT:    [[PHI:%.*]] = phi i64 [ [[ADD:%.*]], %[[BB6:.*]] ], [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ]
+; CHECK-NEXT:    br i1 [[ARG]], label %[[BB6]], label %[[BB4:.*]]
+; CHECK:       [[BB4]]:
+; CHECK-NEXT:    [[ARG4:%.*]] = load ptr, ptr [[ARG2]], align 8, !nonnull [[META0]], !dereferenceable_or_null [[META1]], !align [[META1]]
+; CHECK-NEXT:    [[LOAD1:%.*]] = load i32, ptr [[ARG4]], align 8
+; CHECK-NEXT:    [[ADD5:%.*]] = add i32 [[LOAD1]], 1
+; CHECK-NEXT:    br label %[[BB6]]
+; CHECK:       [[BB6]]:
+; CHECK-NEXT:    [[PHI7:%.*]] = phi i32 [ [[ADD5]], %[[BB4]] ], [ 0, %[[BB3]] ]
+; CHECK-NEXT:    [[ADD]] = add i64 [[PHI]], 1
+; CHECK-NEXT:    [[ICMP:%.*]] = icmp samesign ult i64 [[PHI]], 100
+; CHECK-NEXT:    br i1 [[ICMP]], label %[[BB3]], label %[[BB8]], !llvm.loop [[LOOP5:![0-9]+]]
+; CHECK:       [[BB8]]:
+; CHECK-NEXT:    [[PHI9:%.*]] = phi i32 [ [[PHI7]], %[[BB6]] ], [ [[TMP13]], %[[MIDDLE_BLOCK]] ]
+; CHECK-NEXT:    ret void
+;
+bb:
+  br label %bb3
+
+bb3:                                              ; preds = %bb6, %bb
+  %phi = phi i64 [ %add, %bb6 ], [ 0, %bb ]
+  br i1 %arg, label %bb6, label %bb4
+
+bb4:                                              ; preds = %bb3
+  %arg3 = load ptr, ptr %arg2, align 8, !dereferenceable_or_null !{i64 8}, !align !{i64 8}, !nonnull !{}
+  %load = load i32, ptr %arg3, align 8
+  %add5 = add i32 %load, 1
+  br label %bb6
+
+bb6:                                              ; preds = %bb4, %bb3
+  %phi7 = phi i32 [ %add5, %bb4 ], [ 0, %bb3 ]
+  %add = add i64 %phi, 1
+  %icmp = icmp samesign ult i64 %phi, 100
+  br i1 %icmp, label %bb3, label %bb8
+
+bb8:                                              ; preds = %bb6
+  %phi9 = phi i32 [ %phi7, %bb6 ]
+  ret void
+}
+;.
+; CHECK: [[META0]] = !{}
+; CHECK: [[META1]] = !{i64 8}
+; CHECK: [[LOOP2]] = distinct !{[[LOOP2]], [[META3:![0-9]+]], [[META4:![0-9]+]]}
+; CHECK: [[META3]] = !{!"llvm.loop.isvectorized", i32 1}
+; CHECK: [[META4]] = !{!"llvm.loop.unroll.runtime.disable"}
+; CHECK: [[LOOP5]] = distinct !{[[LOOP5]], [[META4]], [[META3]]}
+;.

``````````

</details>


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


More information about the llvm-commits mailing list