[llvm] [LoopVectorize] Add an option to test potential issues with VPlan (PR #121154)
Danila Malyutin via llvm-commits
llvm-commits at lists.llvm.org
Thu Dec 26 08:18:50 PST 2024
https://github.com/danilaml created https://github.com/llvm/llvm-project/pull/121154
Add a way to test for https://github.com/llvm/llvm-project/issues/115169.
>From 366ab2d2125899e92f7f3717b243467f4a571e8e Mon Sep 17 00:00:00 2001
From: Danila Malyutin <dmalyutin at azul.com>
Date: Thu, 26 Dec 2024 20:16:58 +0400
Subject: [PATCH] [LoopVectorize] Add an option to test potential issues with
VPlan
Add a way to test for https://github.com/llvm/llvm-project/issues/115169
---
.../Transforms/Vectorize/LoopVectorize.cpp | 8 +-
.../LoopVectorize/vplan-speculate-loads.ll | 96 +++++++++++++++++++
2 files changed, 103 insertions(+), 1 deletion(-)
create mode 100644 llvm/test/Transforms/LoopVectorize/vplan-speculate-loads.ll
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]]}
+;.
More information about the llvm-commits
mailing list