Motivation
Many C and C++ applications contain loops that are inherently data-parallel but remain sequential because developers are unaware that the iterations are independent. While LLVM already performs sophisticated analyses for optimisation (such as dependence analysis and loop vectorisation), these analyses are primarily used internally by optimisation passes and are not exposed as developer-facing diagnostics for identifying potential parallelisation opportunities.
The goal of this proposal is to introduce a static analysis that identifies loops whose iterations appear independent and may therefore be suitable for data-parallel execution (e.g., SIMD vectorisation or OpenMP parallelisation).
Problem Statement
Consider the following example:
#include <cmath>
void compute(float *data, int N) {
for (int i = 0; i < N; ++i) {
data[i] = std::sin(data[i]) + std::cos(data[i]);
}
}
Each iteration only accesses data[i].
There are no loop-carried dependencies, making the loop a good candidate for data-parallel execution.
However, Clang currently does not provide a developer-facing diagnostic explicitly identifying such opportunities.
Proposal
Introduce a static analysis capable of identifying loops whose iterations appear independent.
The analysis would:
- Identify loops within each function.
- Analyse memory accesses and loop-carried dependencies.
- Detect element-wise computations over independent data.
- Emit diagnostics explaining why a loop is considered data-parallel.
Example diagnostic:
Function 'compute':
Loop beginning at line 12 appears data-parallel.
Reason:
• Independent array accesses
• No detected loop-carried dependencies
Prototype Implementation
To better illustrate the proposal, I have implemented a prototype demonstrating this analysis.
Reference Pull Request: Add Static Analysis for Identifying Data Parallelism Using LLVM/Clang by HITESH-S-P · Pull Request #190511 · llvm/llvm-project · GitHub
The current implementation is intended as a proof of concept and demonstrates:
- Detection of loops with independent iterations.
- Basic identification of data-parallel patterns.
- Emission of developer-facing diagnostics.
- Integration with the Clang tooling infrastructure used in the prototype.
The purpose of this implementation is to facilitate discussion around the design and feasibility of the proposal. I fully expect that the implementation may need to evolve based on community feedback, including changes to its architecture or integration point within the LLVM ecosystem.
Feedback on both the overall direction and the implementation approach would be greatly appreciated.
Possible Integration Points
The current prototype was implemented as a standalone analysis to explore the idea with minimal impact on existing infrastructure.
However, I would appreciate guidance from the community regarding the most appropriate long-term integration point. Possible options include:
- a new
clang-tidyperformance check - an LLVM analysis pass
- optimisation remarks
- another existing Clang/LLVM framework
I do not have a strong preference and would like to follow the direction that best aligns with LLVM’s architecture and long-term maintainability.
Open Questions
I would appreciate feedback on the following:
- Does this analysis provide sufficient value to justify inclusion in LLVM/Clang?
- Which existing framework would be the most appropriate integration point?
- Are there existing analyses that should be reused rather than introducing new logic?
- Would such a feature be acceptable if implemented using existing LLVM infrastructure?