Table of Contents
Fetching ...

Iterating Pointers: Enabling Static Analysis for Loop-based Pointers

Andrea Lepori, Alexandru Calotoiu, Torsten Hoefler

TL;DR

Pointer-based data accesses in C complicate static analysis and automatic parallelization. The authors introduce pointer disaggregation, a transformation that splits a pointer into a data container and an offset (adjunct), making memory accesses explicit and enabling stronger data-dependency analysis. Their source-to-source implementation uses libclang to generate adjuncts and integrate with data-centric compilers like DaCe, unlocking parallelization opportunities in real codes such as PBKDF2 and HPCCG, with substantial speedups in some cases. Across OpenSSL PBKDF2, Mantevo HPCCG, and LZO benchmarks, the approach yields automatic parallelization when possible and notable performance improvements, demonstrating practical impact for pointer-heavy C programs. The work positions pointer-aware transformations as a principled path to leverage modern parallelizing frameworks for codes traditionally resistant to static optimization.

Abstract

Pointers are an integral part of C and other programming languages. They enable substantial flexibility from the programmer's standpoint, allowing the user fine, unmediated control over data access patterns. However, accesses done through pointers are often hard to track, and challenging to understand for optimizers, compilers, and sometimes, even for the developers themselves because of the direct memory access they provide. We alleviate this problem by exposing additional information to analyzers and compilers. By separating the concept of a pointer into a data container and an offset, we can optimize C programs beyond what other state-of-the-art approaches are capable of, in some cases even enabling auto-parallelization. Using this process, we are able to successfully analyze and optimize code from OpenSSL, the Mantevo benchmark suite, and the Lempel-Ziv-Oberhumer compression algorithm. We provide the only automatic approach able to find all parallelization opportunities in the HPCCG benchmark from the Mantevo suite the developers identified and even outperform the reference implementation by up to 18%, as well as speed up the PBKDF2 algorithm implementation from OpenSSL by up to 11x.

Iterating Pointers: Enabling Static Analysis for Loop-based Pointers

TL;DR

Pointer-based data accesses in C complicate static analysis and automatic parallelization. The authors introduce pointer disaggregation, a transformation that splits a pointer into a data container and an offset (adjunct), making memory accesses explicit and enabling stronger data-dependency analysis. Their source-to-source implementation uses libclang to generate adjuncts and integrate with data-centric compilers like DaCe, unlocking parallelization opportunities in real codes such as PBKDF2 and HPCCG, with substantial speedups in some cases. Across OpenSSL PBKDF2, Mantevo HPCCG, and LZO benchmarks, the approach yields automatic parallelization when possible and notable performance improvements, demonstrating practical impact for pointer-heavy C programs. The work positions pointer-aware transformations as a principled path to leverage modern parallelizing frameworks for codes traditionally resistant to static optimization.

Abstract

Pointers are an integral part of C and other programming languages. They enable substantial flexibility from the programmer's standpoint, allowing the user fine, unmediated control over data access patterns. However, accesses done through pointers are often hard to track, and challenging to understand for optimizers, compilers, and sometimes, even for the developers themselves because of the direct memory access they provide. We alleviate this problem by exposing additional information to analyzers and compilers. By separating the concept of a pointer into a data container and an offset, we can optimize C programs beyond what other state-of-the-art approaches are capable of, in some cases even enabling auto-parallelization. Using this process, we are able to successfully analyze and optimize code from OpenSSL, the Mantevo benchmark suite, and the Lempel-Ziv-Oberhumer compression algorithm. We provide the only automatic approach able to find all parallelization opportunities in the HPCCG benchmark from the Mantevo suite the developers identified and even outperform the reference implementation by up to 18%, as well as speed up the PBKDF2 algorithm implementation from OpenSSL by up to 11x.

Paper Structure

This paper contains 30 sections, 14 equations, 18 figures, 2 tables.

Figures (18)

  • Figure 1: Two example codes where we can have false positives and negatives with pointer accesses
  • Figure 2: Representation of data access patterns with pointer movement (left) and static accesses with adjunct (right). Annotated with the accessed memory locations and pointer values. In the case of pointer movements the pointer is both the container and the offset while with the adjunct the pointer is only the container.
  • Figure 3: Difference in the assembly representation (compiled with gcc 12.2 and -O2) between a code using pointer movement and one with static access after the adjunct is introduced.
  • Figure 4: Transformation summary to improve pointer analyzability. Both p and q are int pointers (int* p, q), x is an int expression and $\diamond$ is any integer binary operator. Note that the data-type int is only for explanation purposes and can be substituted with any other type. The adjunct-type int can be interchanged with any integer type that fits the size of the data-container.
  • Figure 5: Left side: example code using pointer movements where the points-to analysis inside GCC is unable to ensure non-aliasing accesses. Right side: code after adjunct transformation where GCC is able statically decide non-aliasing using points-to analysis and integer analysis. Note the difference in the CFG of the resulting assembly code.
  • ...and 13 more figures