Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Add debug location to strlen in LoopIdiomRecognize pass #140164

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 16, 2025

Conversation

amykhuang
Copy link
Collaborator

We should pass down the debug location to the generated strlen call because LLVM maintains
that calls to inlinable functions must have debug info.

@llvmbot
Copy link
Member

llvmbot commented May 15, 2025

@llvm/pr-subscribers-llvm-transforms

Author: Amy Huang (amykhuang)

Changes

We should pass down the debug location to the generated strlen call because LLVM maintains
that calls to inlinable functions must have debug info.


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

2 Files Affected:

  • (modified) llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp (+3)
  • (modified) llvm/test/Transforms/LoopIdiom/strlen.ll (+48)
diff --git a/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp b/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
index 8f5d1ecba982d..2b94686ae7ba5 100644
--- a/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
@@ -1778,6 +1778,9 @@ bool LoopIdiomRecognize::recognizeAndInsertStrLen() {
   }
   assert(StrLenFunc && "Failed to emit strlen function.");
 
+  // Set debug location to the start of the loop.
+  cast<Instruction>(StrLenFunc)->setDebugLoc(CurLoop->getStartLoc());
+
   const SCEV *StrlenEv = SE->getSCEV(StrLenFunc);
   SmallVector<PHINode *, 4> Cleanup;
   for (PHINode &PN : LoopExitBB->phis()) {
diff --git a/llvm/test/Transforms/LoopIdiom/strlen.ll b/llvm/test/Transforms/LoopIdiom/strlen.ll
index 3b9d33ebdc74e..3d53b10be3e9b 100644
--- a/llvm/test/Transforms/LoopIdiom/strlen.ll
+++ b/llvm/test/Transforms/LoopIdiom/strlen.ll
@@ -612,3 +612,51 @@ while.end:
   ret i64 %sub.ptr.sub
 }
 
+define i64 @valid_basic_strlen_with_dbg(ptr %str) {
+; CHECK-LABEL: define i64 @valid_basic_strlen_with_dbg(
+; CHECK-SAME: ptr [[STR:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    [[STRLEN:%.*]] = call i64 @strlen(ptr [[STR]]), !dbg !{{[0-9]+}}
+; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i8, ptr [[STR]], i64 [[STRLEN]]
+; CHECK-NEXT:    br label %[[WHILE_COND:.*]]
+; CHECK:       [[WHILE_COND]]:
+; CHECK-NEXT:    [[STR_ADDR_0:%.*]] = phi ptr [ [[STR]], %[[ENTRY]] ], [ [[INCDEC_PTR:%.*]], %[[WHILE_COND]] ]
+; CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[STR_ADDR_0]], align 1
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i8 [[TMP0]], 0
+; CHECK-NEXT:    [[INCDEC_PTR]] = getelementptr i8, ptr [[STR_ADDR_0]], i64 1
+; CHECK-NEXT:    br i1 true, label %[[WHILE_END:.*]], label %[[WHILE_COND]]
+; CHECK:       [[WHILE_END]]:
+; CHECK-NEXT:    [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[SCEVGEP]] to i64
+; CHECK-NEXT:    [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[STR]] to i64
+; CHECK-NEXT:    [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]]
+; CHECK-NEXT:    ret i64 [[SUB_PTR_SUB]]
+;
+entry:
+  br label %while.cond
+
+while.cond:
+  %str.addr.0 = phi ptr [ %str, %entry ], [ %incdec.ptr, %while.cond ]
+  %0 = load i8, ptr %str.addr.0, align 1, !dbg !6
+  %cmp.not = icmp eq i8 %0, 0, !dbg !6
+  %incdec.ptr = getelementptr i8, ptr %str.addr.0, i64 1
+  br i1 %cmp.not, label %while.end, label %while.cond, !dbg !6
+
+while.end:
+  %sub.ptr.lhs.cast = ptrtoint ptr %str.addr.0 to i64
+  %sub.ptr.rhs.cast = ptrtoint ptr %str to i64
+  %sub.ptr.sub = sub i64 %sub.ptr.lhs.cast, %sub.ptr.rhs.cast
+  ret i64 %sub.ptr.sub
+}
+
+
+!llvm.module.flags = !{!7}
+!llvm.dbg.cu = !{!2}
+
+!0 = distinct !DISubprogram(name: "foo", line: 2, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !2, file: !1, scope: !1, type: !3)
+!1 = !DIFile(filename: "strlen.c", directory: "/tmp")
+!2 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang version 2.9 (trunk 127165:127174)", isOptimized: true, emissionKind: FullDebug, file: !1, enums: !4, retainedTypes: !4)
+!3 = !DISubroutineType(types: !4)
+!4 = !{}
+!5 = distinct !DILexicalBlock(line: 2, column: 21, file: !1, scope: !0)
+!6 = !DILocation(line: 3, column: 3, scope: !5)
+!7 = !{i32 1, !"Debug Info Version", i32 3}

@@ -1778,6 +1778,9 @@ bool LoopIdiomRecognize::recognizeAndInsertStrLen() {
}
assert(StrLenFunc && "Failed to emit strlen function.");

// Set debug location to the start of the loop.
cast<Instruction>(StrLenFunc)->setDebugLoc(CurLoop->getStartLoc());
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could the static type of StrLenFunc be updated to Instruction* so the cast isn't needed here?

Or, alternatively, perhaps it'd be better to set the debug location on the irbuilder, which will then be used for the instructions?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Changed to set the debug location on the IRbuilder.

; CHECK-LABEL: define i64 @valid_basic_strlen_with_dbg(
; CHECK-SAME: ptr [[STR:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*]]:
; CHECK-NEXT: [[STRLEN:%.*]] = call i64 @strlen(ptr [[STR]]), !dbg !{{[0-9]+}}
Copy link
Collaborator

Choose a reason for hiding this comment

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

It'd be good to test that the desired debug location was applied to the resulting strlen - might be this needs to be a test without autogenerated checks to do that.

(& what're all the other instructions here - are they instructions part of the transformation, but not part of the resulting strlen? Do any of those end up with the same location as the strlen and are they correct?)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Whoops, yeah, I put in the general match because opt was reordering the debug info metadata, but I just reordered it to the "correct" order.

Not sure about the other instructions; they look unchanged so I assume the debug info would remain unchangd as well. Looks like in this particular test case only the compare instruction got replaced with a strlen call. will add the code author too, just realized the change is fairly recent.

@amykhuang amykhuang requested a review from mustartt May 16, 2025 21:15
; CHECK-LABEL: define i64 @valid_basic_strlen_with_dbg(
; CHECK-SAME: ptr [[STR:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*]]:
; CHECK-NEXT: [[STRLEN:%.*]] = call i64 @strlen(ptr [[STR]]), !dbg !4
Copy link
Collaborator

Choose a reason for hiding this comment

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

The metadata numbering might not remain the same across the optimization, I think? - so might be worth matching the !dbg metadata number, then matching the definition of that metadata node/its contents.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Oh true, I did not think of matching the contents of the debug metadata. fixed

Copy link
Member

@mustartt mustartt left a comment

Choose a reason for hiding this comment

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

Thanks, LGTM

@amykhuang amykhuang merged commit 7175970 into llvm:main May 16, 2025
6 of 9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants
Morty Proxy This is a proxified and sanitized view of the page, visit original site.