[llvm-branch-commits] [clang] [LifetimeSafety] Enhance benchmark script for ExpiredLoans analysis (PR #149577)

2025-07-19 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 edited https://github.com/llvm/llvm-project/pull/149577
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Enhance benchmark script for ExpiredLoans analysis (PR #149577)

2025-07-19 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 updated 
https://github.com/llvm/llvm-project/pull/149577

>From d4f54571c0c795d5296ef12cd055599490d14259 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Fri, 18 Jul 2025 19:16:43 +
Subject: [PATCH] add-loan-analysis-to-benchmark

---
 .../test/Analysis/LifetimeSafety/benchmark.py | 239 --
 1 file changed, 158 insertions(+), 81 deletions(-)

diff --git a/clang/test/Analysis/LifetimeSafety/benchmark.py 
b/clang/test/Analysis/LifetimeSafety/benchmark.py
index 9d5f36c51b9ee..2ade1716caff3 100644
--- a/clang/test/Analysis/LifetimeSafety/benchmark.py
+++ b/clang/test/Analysis/LifetimeSafety/benchmark.py
@@ -21,22 +21,12 @@ def generate_cpp_cycle_test(n: int) -> str:
 struct MyObj { int id; ~MyObj() {} };
 
 void long_cycle_4(bool condition) {
-MyObj v1{1};
-MyObj v2{1};
-MyObj v3{1};
-MyObj v4{1};
-
-MyObj* p1 = &v1;
-MyObj* p2 = &v2;
-MyObj* p3 = &v3;
-MyObj* p4 = &v4;
+MyObj v1{1}; MyObj v2{1}; MyObj v3{1}; MyObj v4{1};
+MyObj* p1 = &v1; MyObj* p2 = &v2; MyObj* p3 = &v3; MyObj* p4 = &v4;
 
 while (condition) {
 MyObj* temp = p1;
-p1 = p2;
-p2 = p3;
-p3 = p4;
-p4 = temp;
+p1 = p2; p2 = p3; p3 = p4; p4 = temp;
 }
 }
 """
@@ -99,28 +89,81 @@ def generate_cpp_merge_test(n: int) -> str:
 return cpp_code
 
 
-def analyze_trace_file(trace_path: str) -> tuple[float, float]:
+def generate_cpp_nested_loop_test(n: int) -> str:
 """
-Parses the -ftime-trace JSON output to find durations.
+Generates C++ code with N levels of nested loops.
+This pattern tests how analysis performance scales with loop nesting depth,
+which is a key factor in the complexity of dataflow analyses on structured
+control flow.
+
+Example (n=3):
+struct MyObj { int id; ~MyObj() {} };
+void nested_loops_3() {
+MyObj* p = nullptr;
+for(int i0=0; i0<2; ++i0) {
+MyObj s0; p = &s0;
+for(int i1=0; i1<2; ++i1) {
+MyObj s1; p = &s1;
+for(int i2=0; i2<2; ++i2) {
+MyObj s2; p = &s2;
+}
+}
+}
+}
+"""
+if n <= 0:
+return "// Nesting depth must be positive."
+
+cpp_code = "struct MyObj { int id; ~MyObj() {} };\n\n"
+cpp_code += f"void nested_loops_{n}() {{\n"
+cpp_code += "MyObj* p = nullptr;\n"
+
+for i in range(n):
+indent = "" * (i + 1)
+cpp_code += f"{indent}for(int i{i}=0; i{i}<2; ++i{i}) {{\n"
+cpp_code += f"{indent}MyObj s{i}; p = &s{i};\n"
+
+for i in range(n - 1, -1, -1):
+indent = "" * (i + 1)
+cpp_code += f"{indent}}}\n"
+
+cpp_code += "}\n"
+cpp_code += f"\nint main() {{ nested_loops_{n}(); return 0; }}\n"
+return cpp_code
+
 
-Returns:
-A tuple of (lifetime_analysis_duration_us, total_clang_duration_us).
+def analyze_trace_file(trace_path: str) -> dict:
 """
-lifetime_duration = 0.0
-total_duration = 0.0
+Parses the -ftime-trace JSON output to find durations for the lifetime
+analysis and its sub-phases.
+Returns a dictionary of durations in microseconds.
+"""
+durations = {
+"lifetime_us": 0.0,
+"total_us": 0.0,
+"fact_gen_us": 0.0,
+"loan_prop_us": 0.0,
+"expired_loans_us": 0.0,
+}
+event_name_map = {
+"LifetimeSafetyAnalysis": "lifetime_us",
+"ExecuteCompiler": "total_us",
+"FactGenerator": "fact_gen_us",
+"LoanPropagation": "loan_prop_us",
+"ExpiredLoans": "expired_loans_us",
+}
 try:
 with open(trace_path, "r") as f:
 trace_data = json.load(f)
 for event in trace_data.get("traceEvents", []):
-if event.get("name") == "LifetimeSafetyAnalysis":
-lifetime_duration += float(event.get("dur", 0))
-if event.get("name") == "ExecuteCompiler":
-total_duration += float(event.get("dur", 0))
-
+event_name = event.get("name")
+if event_name in event_name_map:
+key = event_name_map[event_name]
+durations[key] += float(event.get("dur", 0))
 except (IOError, json.JSONDecodeError) as e:
 print(f"Error reading or parsing trace file {trace_path}: {e}", 
file=sys.stderr)
-return 0.0, 0.0
-return lifetime_duration, total_duration
+return {key: 0.0 for key in durations}
+return durations
 
 
 def power_law(n, c, k):
@@ -135,8 +178,29 @@ def human_readable_time(ms: float) -> str:
 return f"{ms:.2f} ms"
 
 
+def calculate_complexity(n_data, y_data) -> tuple[float | None, 

[llvm-branch-commits] [clang] [LifetimeSafety] Enhance benchmark script for ExpiredLoans analysis (PR #149577)

2025-07-19 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 edited https://github.com/llvm/llvm-project/pull/149577
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Enhance benchmark script for ExpiredLoans analysis (PR #149577)

2025-07-19 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 edited https://github.com/llvm/llvm-project/pull/149577
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Enhance benchmark script for ExpiredLoans analysis (PR #149577)

2025-07-19 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 edited https://github.com/llvm/llvm-project/pull/149577
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Enhance benchmark script for ExpiredLoans analysis (PR #149577)

2025-07-19 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 edited https://github.com/llvm/llvm-project/pull/149577
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Enhance benchmark script for ExpiredLoans analysis (PR #149577)

2025-07-19 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 edited https://github.com/llvm/llvm-project/pull/149577
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Enhance benchmark script for ExpiredLoans analysis (PR #149577)

2025-07-19 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 updated 
https://github.com/llvm/llvm-project/pull/149577

>From 9e6a675838d87e79b39c74af81c359fab1190473 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Fri, 18 Jul 2025 19:16:43 +
Subject: [PATCH] add-loan-analysis-to-benchmark

---
 .../test/Analysis/LifetimeSafety/benchmark.py | 239 --
 1 file changed, 158 insertions(+), 81 deletions(-)

diff --git a/clang/test/Analysis/LifetimeSafety/benchmark.py 
b/clang/test/Analysis/LifetimeSafety/benchmark.py
index 9d5f36c51b9ee..2ade1716caff3 100644
--- a/clang/test/Analysis/LifetimeSafety/benchmark.py
+++ b/clang/test/Analysis/LifetimeSafety/benchmark.py
@@ -21,22 +21,12 @@ def generate_cpp_cycle_test(n: int) -> str:
 struct MyObj { int id; ~MyObj() {} };
 
 void long_cycle_4(bool condition) {
-MyObj v1{1};
-MyObj v2{1};
-MyObj v3{1};
-MyObj v4{1};
-
-MyObj* p1 = &v1;
-MyObj* p2 = &v2;
-MyObj* p3 = &v3;
-MyObj* p4 = &v4;
+MyObj v1{1}; MyObj v2{1}; MyObj v3{1}; MyObj v4{1};
+MyObj* p1 = &v1; MyObj* p2 = &v2; MyObj* p3 = &v3; MyObj* p4 = &v4;
 
 while (condition) {
 MyObj* temp = p1;
-p1 = p2;
-p2 = p3;
-p3 = p4;
-p4 = temp;
+p1 = p2; p2 = p3; p3 = p4; p4 = temp;
 }
 }
 """
@@ -99,28 +89,81 @@ def generate_cpp_merge_test(n: int) -> str:
 return cpp_code
 
 
-def analyze_trace_file(trace_path: str) -> tuple[float, float]:
+def generate_cpp_nested_loop_test(n: int) -> str:
 """
-Parses the -ftime-trace JSON output to find durations.
+Generates C++ code with N levels of nested loops.
+This pattern tests how analysis performance scales with loop nesting depth,
+which is a key factor in the complexity of dataflow analyses on structured
+control flow.
+
+Example (n=3):
+struct MyObj { int id; ~MyObj() {} };
+void nested_loops_3() {
+MyObj* p = nullptr;
+for(int i0=0; i0<2; ++i0) {
+MyObj s0; p = &s0;
+for(int i1=0; i1<2; ++i1) {
+MyObj s1; p = &s1;
+for(int i2=0; i2<2; ++i2) {
+MyObj s2; p = &s2;
+}
+}
+}
+}
+"""
+if n <= 0:
+return "// Nesting depth must be positive."
+
+cpp_code = "struct MyObj { int id; ~MyObj() {} };\n\n"
+cpp_code += f"void nested_loops_{n}() {{\n"
+cpp_code += "MyObj* p = nullptr;\n"
+
+for i in range(n):
+indent = "" * (i + 1)
+cpp_code += f"{indent}for(int i{i}=0; i{i}<2; ++i{i}) {{\n"
+cpp_code += f"{indent}MyObj s{i}; p = &s{i};\n"
+
+for i in range(n - 1, -1, -1):
+indent = "" * (i + 1)
+cpp_code += f"{indent}}}\n"
+
+cpp_code += "}\n"
+cpp_code += f"\nint main() {{ nested_loops_{n}(); return 0; }}\n"
+return cpp_code
+
 
-Returns:
-A tuple of (lifetime_analysis_duration_us, total_clang_duration_us).
+def analyze_trace_file(trace_path: str) -> dict:
 """
-lifetime_duration = 0.0
-total_duration = 0.0
+Parses the -ftime-trace JSON output to find durations for the lifetime
+analysis and its sub-phases.
+Returns a dictionary of durations in microseconds.
+"""
+durations = {
+"lifetime_us": 0.0,
+"total_us": 0.0,
+"fact_gen_us": 0.0,
+"loan_prop_us": 0.0,
+"expired_loans_us": 0.0,
+}
+event_name_map = {
+"LifetimeSafetyAnalysis": "lifetime_us",
+"ExecuteCompiler": "total_us",
+"FactGenerator": "fact_gen_us",
+"LoanPropagation": "loan_prop_us",
+"ExpiredLoans": "expired_loans_us",
+}
 try:
 with open(trace_path, "r") as f:
 trace_data = json.load(f)
 for event in trace_data.get("traceEvents", []):
-if event.get("name") == "LifetimeSafetyAnalysis":
-lifetime_duration += float(event.get("dur", 0))
-if event.get("name") == "ExecuteCompiler":
-total_duration += float(event.get("dur", 0))
-
+event_name = event.get("name")
+if event_name in event_name_map:
+key = event_name_map[event_name]
+durations[key] += float(event.get("dur", 0))
 except (IOError, json.JSONDecodeError) as e:
 print(f"Error reading or parsing trace file {trace_path}: {e}", 
file=sys.stderr)
-return 0.0, 0.0
-return lifetime_duration, total_duration
+return {key: 0.0 for key in durations}
+return durations
 
 
 def power_law(n, c, k):
@@ -135,8 +178,29 @@ def human_readable_time(ms: float) -> str:
 return f"{ms:.2f} ms"
 
 
+def calculate_complexity(n_data, y_data) -> tuple[float | None, 

[llvm-branch-commits] [clang] [LifetimeSafety] Enhance benchmark script for ExpiredLoans analysis (PR #149577)

2025-07-19 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 edited https://github.com/llvm/llvm-project/pull/149577
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Enhance benchmark script for ExpiredLoans analysis (PR #149577)

2025-07-18 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 edited https://github.com/llvm/llvm-project/pull/149577
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Enhance benchmark script for ExpiredLoans analysis (PR #149577)

2025-07-18 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 edited https://github.com/llvm/llvm-project/pull/149577
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Enhance benchmark script for ExpiredLoans analysis (PR #149577)

2025-07-18 Thread via llvm-branch-commits

github-actions[bot] wrote:




:warning: Python code formatter, darker found issues in your code. :warning:



You can test this locally with the following command:


``bash
darker --check --diff -r HEAD~1...HEAD 
clang/test/Analysis/LifetimeSafety/benchmark.py
``





View the diff from darker here.


``diff
--- benchmark.py2025-07-18 19:49:32.00 +
+++ benchmark.py2025-07-18 19:51:58.973643 +
@@ -115,20 +115,20 @@
 return "// Nesting depth must be positive."
 
 cpp_code = "struct MyObj { int id; ~MyObj() {} };\n\n"
 cpp_code += f"void nested_loops_{n}() {{\n"
 cpp_code += "MyObj* p = nullptr;\n"
-
+
 for i in range(n):
 indent = "" * (i + 1)
 cpp_code += f"{indent}for(int i{i}=0; i{i}<2; ++i{i}) {{\n"
 cpp_code += f"{indent}MyObj s{i}; p = &s{i};\n"
 
 for i in range(n - 1, -1, -1):
 indent = "" * (i + 1)
 cpp_code += f"{indent}}}\n"
-
+
 cpp_code += "}\n"
 cpp_code += f"\nint main() {{ nested_loops_{n}(); return 0; }}\n"
 return cpp_code
 
 
@@ -238,18 +238,18 @@
 report.append(" ".join(row))
 
 report.append("\n**Complexity Analysis:**\n")
 report.append("| Analysis Phase| Complexity O(nk) |")
 report.append("|:--|:--|")
-
+
 analysis_phases = {
 "Total Analysis": data["lifetime_ms"],
 "FactGenerator": data["fact_gen_ms"],
 "LoanPropagation": data["loan_prop_ms"],
 "ExpiredLoans": data["expired_loans_ms"],
 }
-
+
 for phase_name, y_data in analysis_phases.items():
 k, delta = calculate_complexity(n_data, np.array(y_data))
 if k is not None and delta is not None:
 complexity_str = f"O(n{k:.2f} ± {delta:.2f})"
 else:
@@ -291,11 +291,13 @@
 print(f"Compilation failed for N={n}!", file=sys.stderr)
 print(result.stderr, file=sys.stderr)
 return {}
 
 durations_us = analyze_trace_file(trace_file)
-return {key.replace('_us', '_ms'): value / 1000.0 for key, value in 
durations_us.items()}
+return {
+key.replace("_us", "_ms"): value / 1000.0 for key, value in 
durations_us.items()
+}
 
 
 if __name__ == "__main__":
 parser = argparse.ArgumentParser(
 description="Generate, compile, and benchmark C++ test cases for 
Clang's lifetime analysis."
@@ -360,11 +362,11 @@
 )
 if durations_ms:
 results[test_name]["n"].append(n)
 for key, value in durations_ms.items():
 results[test_name][key].append(value)
-
+
 print(
 f"Total Analysis: 
{human_readable_time(durations_ms['lifetime_ms'])} | "
 f"FactGen: 
{human_readable_time(durations_ms['fact_gen_ms'])} | "
 f"LoanProp: 
{human_readable_time(durations_ms['loan_prop_ms'])} | "
 f"ExpiredLoans: 
{human_readable_time(durations_ms['expired_loans_ms'])}"
@@ -374,10 +376,10 @@
 print("Generating Markdown Report...")
 print("=" * 80 + "\n")
 
 markdown_report = generate_markdown_report(results)
 print(markdown_report)
-
+
 report_filename = os.path.join(args.output_dir, "performance_report.md")
 with open(report_filename, "w") as f:
 f.write(markdown_report)
 print(f"Report saved to: {report_filename}")

``




https://github.com/llvm/llvm-project/pull/149577
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Enhance benchmark script for ExpiredLoans analysis (PR #149577)

2025-07-18 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 edited https://github.com/llvm/llvm-project/pull/149577
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits