Skip to content

Conversation

@ParkHanbum
Copy link
Contributor

When -pass-remarks=loop-vectorize is specified, the subsequent logic is executed to display detailed debug messages even if no PreHeader exists in the loop.

Therefore, an assert occurs when the getLoopPreHeader() function is called. This commit resolves that issue.

Fixed: #165377

@llvmbot
Copy link
Member

llvmbot commented Nov 4, 2025

@llvm/pr-subscribers-llvm-analysis
@llvm/pr-subscribers-llvm-transforms

@llvm/pr-subscribers-vectorizers

Author: hanbeom (ParkHanbum)

Changes

When -pass-remarks=loop-vectorize is specified, the subsequent logic is executed to display detailed debug messages even if no PreHeader exists in the loop.

Therefore, an assert occurs when the getLoopPreHeader() function is called. This commit resolves that issue.

Fixed: #165377


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

2 Files Affected:

  • (modified) llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp (+8)
  • (added) llvm/test/Transforms/LoopVectorize/loop-legality-checks-remarks.ll (+33)
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
index 8e09e6f8d4935..311cf4ecbe121 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
@@ -795,6 +795,14 @@ static bool canWidenCallReturnType(Type *Ty) {
 bool LoopVectorizationLegality::canVectorizeInstrs() {
   BasicBlock *Header = TheLoop->getHeader();
 
+  /// Generally, if `TheLoop` lacks a PreHeader, it won't reach this point.
+  /// However, when executed with remarks options like `-pass-remarks=vector`
+  /// it will reach here to output extra debug messages, so need to check.
+  /// Additionally, before reaching here, the debug messages would have
+  /// included `Loop doesn't have a legal pre-header`, so we omit that.
+  if (ORE->allowExtraAnalysis(DEBUG_TYPE) && !TheLoop->getLoopPreheader())
+    return false;
+
   // For each block in the loop.
   for (BasicBlock *BB : TheLoop->blocks()) {
     // Scan the instructions in the block and look for hazards.
diff --git a/llvm/test/Transforms/LoopVectorize/loop-legality-checks-remarks.ll b/llvm/test/Transforms/LoopVectorize/loop-legality-checks-remarks.ll
new file mode 100644
index 0000000000000..ec5dcacb0f765
--- /dev/null
+++ b/llvm/test/Transforms/LoopVectorize/loop-legality-checks-remarks.ll
@@ -0,0 +1,33 @@
+; RUN: opt < %s -passes=loop-vectorize -pass-remarks=loop-vectorize -debug -disable-output 2>&1 | FileCheck %s
+; REQUIRES: asserts
+
+; Make sure LV legal bails out when the loop doesn't have a legal pre-header.
+; CHECK-LABEL: 'not_exist_preheader'
+; CHECK: LV: Not vectorizing: Loop doesn't have a legal pre-header.
+define void @not_exist_preheader(ptr %currMB, i1 %arg, ptr %arg2) nounwind uwtable {
+entry:
+  br i1 %arg, label %start.exit, label %if.then.i
+
+if.then.i:
+  unreachable
+
+start.exit:
+  indirectbr ptr %arg2, [label %0, label %for.bodyprime]
+
+0:
+  unreachable
+
+for.bodyprime:
+  %i.057375 = phi i32 [0, %start.exit], [%1, %for.bodyprime]
+  %arrayidx8prime = getelementptr inbounds i32, ptr %currMB, i32 %i.057375
+  store i32 0, ptr %arrayidx8prime, align 4
+  %1 = add i32 %i.057375, 1
+  %cmp5prime = icmp slt i32 %1, 4
+  br i1 %cmp5prime, label %for.bodyprime, label %for.endprime
+
+for.endprime:
+  br label %for.body23prime
+
+for.body23prime:
+  br label %for.body23prime
+}

Comment on lines 8 to 12
entry:
br i1 %arg, label %start.exit, label %if.then.i

if.then.i:
unreachable
Copy link
Contributor

Choose a reason for hiding this comment

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

I think you can remove those

Comment on lines 28 to 32
for.endprime:
br label %for.body23prime

for.body23prime:
br label %for.body23prime
Copy link
Contributor

Choose a reason for hiding this comment

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

Can do something like below?

Suggested change
for.endprime:
br label %for.body23prime
for.body23prime:
br label %for.body23prime
exit:
ret void

Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like the test still needs cleaning up?

Comment on lines 798 to 804
/// Generally, if `TheLoop` lacks a PreHeader, it won't reach this point.
/// However, when executed with remarks options like `-pass-remarks=vector`
/// it will reach here to output extra debug messages, so need to check.
/// Additionally, before reaching here, the debug messages would have
/// included `Loop doesn't have a legal pre-header`, so we omit that.
if (ORE->allowExtraAnalysis(DEBUG_TYPE) && !TheLoop->getLoopPreheader())
return false;
Copy link
Contributor

Choose a reason for hiding this comment

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

Checking here means we will miss out on any extra analysis for subsequent instructions.

We should be able to check in IVDescriptor and bail out if there's no preheader there, which would still allow continuing with the other checks.

You can add an unvectorizable instruction to the function, perhaps something like an unsupported call, for which we should get a missed remark ideally, even if there's no preheader.

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 understand that you are asking me to modify the subcode so that no issues arise even if the PreHeader does not exist. Is that correct?

Copy link
Contributor

Choose a reason for hiding this comment

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

I understand that you are asking me to modify the subcode so that no issues arise even if the PreHeader does not exist. Is that correct?

Yep.

You can add an unvectorizable instruction to the function, perhaps something like an unsupported call, for which we should get a missed remark ideally, even if there's no preheader.

Looks like this is still pending?

@llvmbot llvmbot added the llvm:analysis Includes value tracking, cost tables and constant folding label Nov 7, 2025
@github-actions
Copy link

github-actions bot commented Nov 7, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

Copy link
Contributor

@fhahn fhahn left a comment

Choose a reason for hiding this comment

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

Would be good to update the title to reflect the updates to the PR (now fixed in IVDescriptors)

Comment on lines +225 to +227
Value *RdxStart;
if (TheLoop->getLoopPreheader())
RdxStart = Phi->getIncomingValueForBlock(TheLoop->getLoopPreheader());
Copy link
Contributor

Choose a reason for hiding this comment

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

can we just return false here?

Suggested change
Value *RdxStart;
if (TheLoop->getLoopPreheader())
RdxStart = Phi->getIncomingValueForBlock(TheLoop->getLoopPreheader());
if (TheLoop->getLoopPreheader())
return false;
// Obtain the reduction start value from the value that comes from the loop
// preheader.
Value *RdxStart = Phi->getIncomingValueForBlock(TheLoop->getLoopPreheader());

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sure, I'll update it

Copy link
Contributor Author

Choose a reason for hiding this comment

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

  LLVM-Unit :: Analysis/./AnalysisTests/IVDescriptorsTest/FMaxRednIdentity
  LLVM-Unit :: Analysis/./AnalysisTests/IVDescriptorsTest/FMinRednIdentity


Testing Time: 429.16s

Total Discovered Tests: 113200
  Skipped          :     20 (0.02%)
  Unsupported      :   1351 (1.19%)
  Passed           : 111396 (98.41%)
  Expectedly Failed:    215 (0.19%)
  Failed           :    218 (0.19%)

@fhahn After making the change, many failures occurred.

Comment on lines 798 to 804
/// Generally, if `TheLoop` lacks a PreHeader, it won't reach this point.
/// However, when executed with remarks options like `-pass-remarks=vector`
/// it will reach here to output extra debug messages, so need to check.
/// Additionally, before reaching here, the debug messages would have
/// included `Loop doesn't have a legal pre-header`, so we omit that.
if (ORE->allowExtraAnalysis(DEBUG_TYPE) && !TheLoop->getLoopPreheader())
return false;
Copy link
Contributor

Choose a reason for hiding this comment

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

I understand that you are asking me to modify the subcode so that no issues arise even if the PreHeader does not exist. Is that correct?

Yep.

You can add an unvectorizable instruction to the function, perhaps something like an unsupported call, for which we should get a missed remark ideally, even if there's no preheader.

Looks like this is still pending?

Comment on lines 28 to 32
for.endprime:
br label %for.body23prime

for.body23prime:
br label %for.body23prime
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like the test still needs cleaning up?

…bled

When `-pass-remarks=loop-vectorize` is specified, the subsequent
logic is executed to display detailed debug messages even
if no PreHeader exists in the loop.

Therefore, an assert occurs when the `getLoopPreHeader()` function
is called. This commit resolves that issue.

Fixed: llvm#165377
@ParkHanbum ParkHanbum changed the title [LV] Check loop-preheader for loop-legality when pass-remarks enabled [IVDesc] Check loop-preheader for loop-legality when pass-remarks enabled Nov 13, 2025
@ParkHanbum ParkHanbum requested a review from fhahn November 14, 2025 14:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

llvm:analysis Includes value tracking, cost tables and constant folding llvm:transforms vectorizers

Projects

None yet

Development

Successfully merging this pull request may close these issues.

opt -passes=loop-vectorize -pass-remarks=vector causes Assertion `Idx >= 0 && "Invalid basic block argument!"' failed.

3 participants