[llvm-branch-commits] [clang] [LifetimeSafety] Enhance benchmark script for new sub analyses (PR #149577)

2025-08-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 new sub analyses (PR #149577)

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

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

>From d21e733fa41cb0141e78053cc6ff1a757c1d9eec Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Sat, 19 Jul 2025 15:40:36 +
Subject: [PATCH] add live origins

---
 .../test/Analysis/LifetimeSafety/benchmark.py | 230 +-
 1 file changed, 165 insertions(+), 65 deletions(-)

diff --git a/clang/test/Analysis/LifetimeSafety/benchmark.py 
b/clang/test/Analysis/LifetimeSafety/benchmark.py
index 9d5f36c51b9ee..1ab89d107a238 100644
--- a/clang/test/Analysis/LifetimeSafety/benchmark.py
+++ b/clang/test/Analysis/LifetimeSafety/benchmark.py
@@ -99,28 +99,86 @@ 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.
 
-Returns:
-A tuple of (lifetime_analysis_duration_us, total_clang_duration_us).
+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
+
+
+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,
+"live_origins_us": 0.0,
+}
+event_name_map = {
+"LifetimeSafetyAnalysis": "lifetime_us",
+"ExecuteCompiler": "total_us",
+"FactGenerator": "fact_gen_us",
+"LoanPropagation": "loan_prop_us",
+"ExpiredLoans": "expired_loans_us",
+"LiveOrigins": "live_origins_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 +193,29 @@ def human_readable_time(ms: float) -> str:
 return f"{ms:.2f} ms"
 
 
+def calculate_complexity(n_data, y_data) -> tuple[float | None, float | None]:
+"""
+Calculates the exponent 'k' for the power law fit y = c * n^k.
+Returns a tuple of (k, k_standard_error).
+"""
+try:
+if len(n_data) < 3 or np.all(y_data < 1e-6) or np.var(y_data) < 1e-6:
+return None, None
+
+non_zero_indices = y_data > 0
+if np.sum(non_zero_indices) < 3:
+return None, None
+
+n_fit, y_fit = n_data[non_zero_indices], y_data[non_zero_indices]
+popt, pcov = curve_fit(power_law, n_fit, y_fit, p0=[0, 1], maxfev=5000)
+k_stderr = np.sqrt(np.diag(pcov))[1]
+return popt[1], k_stderr
+except (RuntimeError, ValueError):
+return None, N

[llvm-branch-commits] [clang] [LifetimeSafety] Enhance benchmark script for new sub analyses (PR #149577)

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

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

>From cf062ae3984d8cf78b15c9274658024cd78fb4e8 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Sat, 19 Jul 2025 15:40:36 +
Subject: [PATCH] add live origins

---
 .../test/Analysis/LifetimeSafety/benchmark.py | 230 +-
 1 file changed, 165 insertions(+), 65 deletions(-)

diff --git a/clang/test/Analysis/LifetimeSafety/benchmark.py 
b/clang/test/Analysis/LifetimeSafety/benchmark.py
index 9d5f36c51b9ee..1ab89d107a238 100644
--- a/clang/test/Analysis/LifetimeSafety/benchmark.py
+++ b/clang/test/Analysis/LifetimeSafety/benchmark.py
@@ -99,28 +99,86 @@ 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.
 
-Returns:
-A tuple of (lifetime_analysis_duration_us, total_clang_duration_us).
+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
+
+
+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,
+"live_origins_us": 0.0,
+}
+event_name_map = {
+"LifetimeSafetyAnalysis": "lifetime_us",
+"ExecuteCompiler": "total_us",
+"FactGenerator": "fact_gen_us",
+"LoanPropagation": "loan_prop_us",
+"ExpiredLoans": "expired_loans_us",
+"LiveOrigins": "live_origins_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 +193,29 @@ def human_readable_time(ms: float) -> str:
 return f"{ms:.2f} ms"
 
 
+def calculate_complexity(n_data, y_data) -> tuple[float | None, float | None]:
+"""
+Calculates the exponent 'k' for the power law fit y = c * n^k.
+Returns a tuple of (k, k_standard_error).
+"""
+try:
+if len(n_data) < 3 or np.all(y_data < 1e-6) or np.var(y_data) < 1e-6:
+return None, None
+
+non_zero_indices = y_data > 0
+if np.sum(non_zero_indices) < 3:
+return None, None
+
+n_fit, y_fit = n_data[non_zero_indices], y_data[non_zero_indices]
+popt, pcov = curve_fit(power_law, n_fit, y_fit, p0=[0, 1], maxfev=5000)
+k_stderr = np.sqrt(np.diag(pcov))[1]
+return popt[1], k_stderr
+except (RuntimeError, ValueError):
+return None, N

[llvm-branch-commits] [clang] [LifetimeSafety] Enhance benchmark script for new sub analyses (PR #149577)

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

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

>From c55a8f92f55c932b5f334b681986397d639f6826 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Sat, 19 Jul 2025 15:40:36 +
Subject: [PATCH] add live origins

---
 .../test/Analysis/LifetimeSafety/benchmark.py | 230 +-
 1 file changed, 165 insertions(+), 65 deletions(-)

diff --git a/clang/test/Analysis/LifetimeSafety/benchmark.py 
b/clang/test/Analysis/LifetimeSafety/benchmark.py
index 9d5f36c51b9ee..1ab89d107a238 100644
--- a/clang/test/Analysis/LifetimeSafety/benchmark.py
+++ b/clang/test/Analysis/LifetimeSafety/benchmark.py
@@ -99,28 +99,86 @@ 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.
 
-Returns:
-A tuple of (lifetime_analysis_duration_us, total_clang_duration_us).
+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
+
+
+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,
+"live_origins_us": 0.0,
+}
+event_name_map = {
+"LifetimeSafetyAnalysis": "lifetime_us",
+"ExecuteCompiler": "total_us",
+"FactGenerator": "fact_gen_us",
+"LoanPropagation": "loan_prop_us",
+"ExpiredLoans": "expired_loans_us",
+"LiveOrigins": "live_origins_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 +193,29 @@ def human_readable_time(ms: float) -> str:
 return f"{ms:.2f} ms"
 
 
+def calculate_complexity(n_data, y_data) -> tuple[float | None, float | None]:
+"""
+Calculates the exponent 'k' for the power law fit y = c * n^k.
+Returns a tuple of (k, k_standard_error).
+"""
+try:
+if len(n_data) < 3 or np.all(y_data < 1e-6) or np.var(y_data) < 1e-6:
+return None, None
+
+non_zero_indices = y_data > 0
+if np.sum(non_zero_indices) < 3:
+return None, None
+
+n_fit, y_fit = n_data[non_zero_indices], y_data[non_zero_indices]
+popt, pcov = curve_fit(power_law, n_fit, y_fit, p0=[0, 1], maxfev=5000)
+k_stderr = np.sqrt(np.diag(pcov))[1]
+return popt[1], k_stderr
+except (RuntimeError, ValueError):
+return None, N

[llvm-branch-commits] [clang] [LifetimeSafety] Enhance benchmark script for new sub analyses (PR #149577)

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

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

>From c55a8f92f55c932b5f334b681986397d639f6826 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Sat, 19 Jul 2025 15:40:36 +
Subject: [PATCH] add live origins

---
 .../test/Analysis/LifetimeSafety/benchmark.py | 230 +-
 1 file changed, 165 insertions(+), 65 deletions(-)

diff --git a/clang/test/Analysis/LifetimeSafety/benchmark.py 
b/clang/test/Analysis/LifetimeSafety/benchmark.py
index 9d5f36c51b9ee..1ab89d107a238 100644
--- a/clang/test/Analysis/LifetimeSafety/benchmark.py
+++ b/clang/test/Analysis/LifetimeSafety/benchmark.py
@@ -99,28 +99,86 @@ 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.
 
-Returns:
-A tuple of (lifetime_analysis_duration_us, total_clang_duration_us).
+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
+
+
+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,
+"live_origins_us": 0.0,
+}
+event_name_map = {
+"LifetimeSafetyAnalysis": "lifetime_us",
+"ExecuteCompiler": "total_us",
+"FactGenerator": "fact_gen_us",
+"LoanPropagation": "loan_prop_us",
+"ExpiredLoans": "expired_loans_us",
+"LiveOrigins": "live_origins_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 +193,29 @@ def human_readable_time(ms: float) -> str:
 return f"{ms:.2f} ms"
 
 
+def calculate_complexity(n_data, y_data) -> tuple[float | None, float | None]:
+"""
+Calculates the exponent 'k' for the power law fit y = c * n^k.
+Returns a tuple of (k, k_standard_error).
+"""
+try:
+if len(n_data) < 3 or np.all(y_data < 1e-6) or np.var(y_data) < 1e-6:
+return None, None
+
+non_zero_indices = y_data > 0
+if np.sum(non_zero_indices) < 3:
+return None, None
+
+n_fit, y_fit = n_data[non_zero_indices], y_data[non_zero_indices]
+popt, pcov = curve_fit(power_law, n_fit, y_fit, p0=[0, 1], maxfev=5000)
+k_stderr = np.sqrt(np.diag(pcov))[1]
+return popt[1], k_stderr
+except (RuntimeError, ValueError):
+return None, N

[llvm-branch-commits] [clang] [LifetimeSafety] Enhance benchmark script for new sub analyses (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 6cb36540be595794914faa992e59be07e7cede9a Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Sat, 19 Jul 2025 15:40:36 +
Subject: [PATCH] add live origins

---
 .../test/Analysis/LifetimeSafety/benchmark.py | 230 +-
 1 file changed, 165 insertions(+), 65 deletions(-)

diff --git a/clang/test/Analysis/LifetimeSafety/benchmark.py 
b/clang/test/Analysis/LifetimeSafety/benchmark.py
index 9d5f36c51b9ee..1ab89d107a238 100644
--- a/clang/test/Analysis/LifetimeSafety/benchmark.py
+++ b/clang/test/Analysis/LifetimeSafety/benchmark.py
@@ -99,28 +99,86 @@ 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.
 
-Returns:
-A tuple of (lifetime_analysis_duration_us, total_clang_duration_us).
+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
+
+
+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,
+"live_origins_us": 0.0,
+}
+event_name_map = {
+"LifetimeSafetyAnalysis": "lifetime_us",
+"ExecuteCompiler": "total_us",
+"FactGenerator": "fact_gen_us",
+"LoanPropagation": "loan_prop_us",
+"ExpiredLoans": "expired_loans_us",
+"LiveOrigins": "live_origins_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 +193,29 @@ def human_readable_time(ms: float) -> str:
 return f"{ms:.2f} ms"
 
 
+def calculate_complexity(n_data, y_data) -> tuple[float | None, float | None]:
+"""
+Calculates the exponent 'k' for the power law fit y = c * n^k.
+Returns a tuple of (k, k_standard_error).
+"""
+try:
+if len(n_data) < 3 or np.all(y_data < 1e-6) or np.var(y_data) < 1e-6:
+return None, None
+
+non_zero_indices = y_data > 0
+if np.sum(non_zero_indices) < 3:
+return None, None
+
+n_fit, y_fit = n_data[non_zero_indices], y_data[non_zero_indices]
+popt, pcov = curve_fit(power_law, n_fit, y_fit, p0=[0, 1], maxfev=5000)
+k_stderr = np.sqrt(np.diag(pcov))[1]
+return popt[1], k_stderr
+except (RuntimeError, ValueError):
+return None, N

[llvm-branch-commits] [clang] [LifetimeSafety] Enhance benchmark script for new sub analyses (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