Skip to content
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
81f1800
Emit better debug and opt-report messages when vectorization is disal…
Sep 14, 2025
6d941ff
Trafo -> Transforms
Sep 15, 2025
c0e6aec
Testing part 1: explicitly disabled code path
Sep 15, 2025
c290bec
Testing part 2: VectorizeOnlyWhenForced code path
Sep 15, 2025
109b3fd
Rename the two new tests so far to begin with diag-
Sep 16, 2025
3c4c8de
Testing part 3: hasDisableAllTransformsHint code path
Sep 16, 2025
fa19ccc
fix test 3
Sep 16, 2025
29d1fa2
use [BUG] instead of [FIXME] in the sanity check fail debug msg
Oct 13, 2025
117c358
Clean up function name and remove excessive attributes from Test 1 an…
Oct 13, 2025
2241343
Try combining Test1 and Test2 into one file
Oct 18, 2025
98a90e9
Address IR review pt1: datalayout
TiborGY Nov 1, 2025
55af5ac
Address IR review pt2: use llvm_unreachable
Nov 1, 2025
120a5bf
Address IR review pt3: only 1 load
Nov 1, 2025
a509ea9
Address IR review pt4: exit block
Nov 1, 2025
bc68571
Refactor the printing of the new messages
Nov 1, 2025
c6a624d
fix
Nov 1, 2025
d4f407b
update message in tests
Nov 1, 2025
5d656e8
give test fn a more descriptive name
Nov 1, 2025
0a933b2
Address IR review pt5: simplify entry block of disable_nonforced
Nov 1, 2025
6dfffe8
Address IR review pt6: simplify some variable and label names
Nov 1, 2025
936d9e3
Apply suggestions from code review
TiborGY Nov 7, 2025
b895a97
update check-nots as the message was removed in favor of llvm_unreach…
Nov 7, 2025
8173da8
fix test
Nov 7, 2025
835f8f0
try simplifying disabled_loop_vectorization test fn to constant store
Nov 7, 2025
7f9fe50
fix return type
Nov 7, 2025
552a8ab
try moving Test3 into the same file as Test 1&2
Nov 7, 2025
dcd926f
somehow a suggestion did not apply
Nov 7, 2025
86515c5
More reviewer suggestions, pt1
Nov 10, 2025
5f7c8b0
use CHECK-LABEL
Nov 10, 2025
96d6136
fix check-label
Nov 10, 2025
6c1932e
shorten loop control flow labels
Nov 15, 2025
8e0c12b
shorten %indvars.iv to %iv, make it 32 bits to remove truncates and s…
Nov 15, 2025
1ec46e8
group all RUN lines at the top, reduce check duplication between Test…
Nov 15, 2025
f530fd5
remove dump-input from FileCheck lines
Nov 17, 2025
60f86af
perform all checks on the second fn with all three RUN lines, also pe…
Nov 23, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 31 additions & 4 deletions llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -182,14 +182,41 @@ void LoopVectorizeHints::setAlreadyVectorized() {
bool LoopVectorizeHints::allowVectorization(
Function *F, Loop *L, bool VectorizeOnlyWhenForced) const {
if (getForce() == LoopVectorizeHints::FK_Disabled) {
LLVM_DEBUG(dbgs() << "LV: Not vectorizing: #pragma vectorize disable.\n");
emitRemarkWithHints();
if (Force.Value == LoopVectorizeHints::FK_Disabled) {
LLVM_DEBUG(dbgs() << "LV: Not vectorizing: #pragma vectorize disable.\n");
ORE.emit(OptimizationRemarkMissed(LV_NAME, "MissedExplicitlyDisabled",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this duplicated from emitRemarkWithHints?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am planning to refactor and rename emitRemarkWithHints in a future PR. Its name does not reflect well what it is doing and it does not let the caller emit a remark more specific than "loop not vectorized". So for now, I have inlined the relevant part of emitRemarkWithHints here.

TheLoop->getStartLoc(),
TheLoop->getHeader())
<< "loop not vectorized: vectorization is explicitly disabled");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could this use reportVectorizationFailure?

Copy link
Contributor Author

@TiborGY TiborGY Nov 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe, but not really? reportVectorizationFailure calls createLVAnalysis which always returns OptimizationRemarkAnalysis, and I feel like OptimizationRemarkMissed is more appropriate here. And FWIW OptimizationRemarkMissed is the preexisting behaviour for the subset of these messages that already existed before this PR.
I have added a new private function to LoopVectorizeHints, and refactored the new messages using it, to make allowVectorization less repetitive. Let me know if you think this was a bad idea.

} else if (hasDisableAllTransformsHint(TheLoop)) {
LLVM_DEBUG(
dbgs() << "LV: Not vectorizing: loop hasDisableAllTransformsHint.\n");
ORE.emit(OptimizationRemarkMissed(LV_NAME, "MissedTransformsDisabled",
TheLoop->getStartLoc(),
TheLoop->getHeader())
<< "loop not vectorized: loop transformations are disabled");
} else {
// This should be unreachable unless there is a bug.
LLVM_DEBUG(
dbgs() << "LV: [FIXME] Not vectorizing: loop vect disabled for "
"an unknown reason!\n");
ORE.emit(OptimizationRemarkMissed(LV_NAME, "MissedUnknown",
TheLoop->getStartLoc(),
TheLoop->getHeader())
<< "loop not vectorized: unknown reason, please file a bug "
"report on the LLVM issue tracker");
}
return false;
}

if (VectorizeOnlyWhenForced && getForce() != LoopVectorizeHints::FK_Enabled) {
LLVM_DEBUG(dbgs() << "LV: Not vectorizing: No #pragma vectorize enable.\n");
emitRemarkWithHints();
LLVM_DEBUG(dbgs() << "LV: Not vectorizing: VectorizeOnlyWhenForced is set, "
"and no #pragma vectorize enable.\n");
ORE.emit(OptimizationRemarkMissed(LV_NAME, "MissedForceOnly",
TheLoop->getStartLoc(),
TheLoop->getHeader())
<< "loop not vectorized: only vectorizing loops that "
"explicitly request it");
return false;
}

Expand Down
42 changes: 42 additions & 0 deletions llvm/test/Transforms/LoopVectorize/diag-disable_nonforced-msgs.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
; This test checks that we emit only the correct debug messages and
; optimization remark when the loop vectorizer is disabled by loop metadata
; that requests no loop transformations.

; REQUIRES: asserts
; RUN: opt -passes=loop-vectorize -pass-remarks=loop-vectorize \
; RUN: -pass-remarks-missed=loop-vectorize \
; RUN: -pass-remarks-analysis=loop-vectorize -debug -disable-output \
; RUN: -force-vector-interleave=1 -force-vector-width=2 \
; RUN: < %s 2>&1 | FileCheck %s
; CHECK-NOT: LV: We can vectorize this loop
; CHECK-NOT: LV: Not vectorizing: #pragma vectorize disable.
; CHECK-NOT: LV: [FIXME] Not vectorizing: loop vect disabled for an unknown reason
; CHECK-NOT: LV: Not vectorizing: VectorizeOnlyWhenForced is set
; CHECK-NOT: LV: Not vectorizing: Disabled/already vectorized
; CHECK-NOT: LV: Not vectorizing: Cannot prove legality
; CHECK: LV: Loop hints: force=disabled
; CHECK: LV: Not vectorizing: loop hasDisableAllTransformsHint.
; CHECK: remark:
; CHECK-SAME: loop not vectorized: loop transformations are disabled
; CHECK: LV: Loop hints prevent vectorization
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
define void @disable_nonforced(ptr nocapture %a, i32 %n) {
entry:
%cmp4 = icmp sgt i32 %n, 0
br i1 %cmp4, label %for.body, label %for.end

for.body:
%indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ]
%arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv
%0 = trunc i64 %indvars.iv to i32
store i32 %0, ptr %arrayidx, align 4
%indvars.iv.next = add i64 %indvars.iv, 1
%lftr.wideiv = trunc i64 %indvars.iv.next to i32
%exitcond = icmp eq i32 %lftr.wideiv, %n
br i1 %exitcond, label %for.end, label %for.body, !llvm.loop !0

for.end:
ret void
}

!0 = !{!0, !{!"llvm.loop.disable_nonforced"}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
; This test checks that we emit only the correct debug messages and
; optimization remark when the loop vectorizer is disabled by loop metadata.

; REQUIRES: asserts
; RUN: opt -passes=loop-vectorize -pass-remarks=loop-vectorize \
; RUN: -pass-remarks-missed=loop-vectorize \
; RUN: -pass-remarks-analysis=loop-vectorize -debug -disable-output \
; RUN: < %s 2>&1 | FileCheck %s
; CHECK-NOT: LV: We can vectorize this loop
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add CHECK-LABEL to match the 2 functions so it is clear to which function the debug output applies?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since opt seems to always output all of the remarks and debug messages first, before any of the IR, I could not get CHECK-LABEL to match on the actual function name. As a workaround I made it match a message that contains the function name in question. This is less elegant than I would like, but I cannot see a better solution without putting the two functions into separate files.

; CHECK-NOT: LV: Not vectorizing: loop hasDisableAllTransformsHint
; CHECK-NOT: LV: [FIXME] Not vectorizing: loop vect disabled for an unknown reason
; CHECK-NOT: LV: Not vectorizing: VectorizeOnlyWhenForced is set
; CHECK-NOT: LV: Not vectorizing: Disabled/already vectorized
; CHECK-NOT: LV: Not vectorizing: Cannot prove legality
; CHECK: LV: Loop hints: force=disabled
; CHECK: LV: Not vectorizing: #pragma vectorize disable.
; CHECK: remark:
; CHECK-SAME: loop not vectorized: vectorization is explicitly disabled
; CHECK: LV: Loop hints prevent vectorization

define dso_local noundef nofpclass(nan inf) double @_Z15CompareDistmatsPKdS0_(ptr noundef readonly captures(none) %distmat1, ptr noundef readonly captures(none) %distmat2) local_unnamed_addr {
entry:
br label %for.body

for.cond.cleanup: ; preds = %for.body
%add.lcssa = phi double [ %add, %for.body ]
%div = fmul fast double %add.lcssa, 0x3FB1111111111111
%0 = tail call fast double @llvm.sqrt.f64(double %div)
ret double %0

for.body: ; preds = %entry, %for.body
%i.014 = phi i64 [ 0, %entry ], [ %inc, %for.body ]
%RMSD.013 = phi double [ 0.000000e+00, %entry ], [ %add, %for.body ]
%arrayidx = getelementptr inbounds nuw double, ptr %distmat1, i64 %i.014
%1 = load double, ptr %arrayidx, align 8
%arrayidx1 = getelementptr inbounds nuw double, ptr %distmat2, i64 %i.014
%2 = load double, ptr %arrayidx1, align 8
%sub = fsub fast double %1, %2
%mul = fmul fast double %sub, %sub
%add = fadd fast double %mul, %RMSD.013
%inc = add nuw nsw i64 %i.014, 1
%exitcond.not = icmp eq i64 %inc, 15
br i1 %exitcond.not, label %for.cond.cleanup, label %for.body, !llvm.loop !0
}

!0 = distinct !{!0, !1}
!1 = !{!"llvm.loop.vectorize.enable", i1 false}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
; This test checks that we emit only the correct debug messages and
; optimization remark when the loop is not vectorized due to the
; vectorize-forced-only pass option being set.

; REQUIRES: asserts
; RUN: opt -passes='loop-vectorize<vectorize-forced-only>' \
; RUN: -pass-remarks=loop-vectorize \
; RUN: -pass-remarks-missed=loop-vectorize \
; RUN: -pass-remarks-analysis=loop-vectorize -debug -disable-output \
; RUN: < %s 2>&1 | FileCheck %s
; CHECK-NOT: LV: We can vectorize this loop
; CHECK-NOT: LV: Not vectorizing: loop hasDisableAllTransformsHint
; CHECK-NOT: LV: [FIXME] Not vectorizing: loop vect disabled for an unknown reason
; CHECK-NOT: LV: Not vectorizing: #pragma vectorize disable
; CHECK-NOT: LV: Not vectorizing: Disabled/already vectorized
; CHECK-NOT: LV: Not vectorizing: Cannot prove legality
; CHECK: LV: Loop hints: force=?
; CHECK: LV: Not vectorizing: VectorizeOnlyWhenForced is set, and no #pragma vectorize enable
; CHECK: remark:
; CHECK-SAME: loop not vectorized: only vectorizing loops that explicitly request it
; CHECK: LV: Loop hints prevent vectorization

define dso_local noundef nofpclass(nan inf) double @_Z15CompareDistmatsPKdS0_(ptr noundef readonly captures(none) %distmat1, ptr noundef readonly captures(none) %distmat2) local_unnamed_addr {
entry:
br label %for.body

for.cond.cleanup: ; preds = %for.body
%add.lcssa = phi double [ %add, %for.body ]
%div = fmul fast double %add.lcssa, 0x3FB1111111111111
%0 = tail call fast double @llvm.sqrt.f64(double %div)
ret double %0

for.body: ; preds = %entry, %for.body
%i.014 = phi i64 [ 0, %entry ], [ %inc, %for.body ]
%RMSD.013 = phi double [ 0.000000e+00, %entry ], [ %add, %for.body ]
%arrayidx = getelementptr inbounds nuw double, ptr %distmat1, i64 %i.014
%1 = load double, ptr %arrayidx, align 8
%arrayidx1 = getelementptr inbounds nuw double, ptr %distmat2, i64 %i.014
%2 = load double, ptr %arrayidx1, align 8
%sub = fsub fast double %1, %2
%mul = fmul fast double %sub, %sub
%add = fadd fast double %mul, %RMSD.013
%inc = add nuw nsw i64 %i.014, 1
%exitcond.not = icmp eq i64 %inc, 15
br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
}