llvm / llvm/llvm-project

[polly][clang] Feature Request: Function-level attribute to disable Polly parallel code generation

Open
#172,415 7 comments 0 reactions 0 assignees View on GitHub
clang:codegen polly
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

## Feature Request

### Summary
Request for a function-level attribute or pragma to selectively disable Polly's parallel code generation (`-mllvm -polly-parallel`) without disabling all optimizations.

### Motivation
Unless I'm mistaken, there's no way to disable Polly (or specific Polly passes) on a per-function basis. When compiling libspatialite with Polly enabled, specific functions trigger compiler crashes during parallel code generation:
```
#4 llvm::DominatorTreeBase::changeImmediateDominator
#5 polly::IslNodeBuilder::createIf
...
#9 polly::IslNodeBuilder::createForParallel
```

The crash occurs in `tsp_ga_random_mutation` function in `virtualrouting.c` when Polly attempts to generate parallel OpenMP code:
```c
static void
tsp_ga_random_mutation (sqlite3 * handle, TspGaPopulationPtr ga,
TspGaSolutionPtr mutant)
{
/* introducing a random mutation */
RouteNodePtr mutation;
int j;
int idx1;
int idx2;

/* applying a random mutation */
tsp_ga_random_interval (handle, ga, &idx1, &idx2);
mutation = *(mutant->CitiesFrom + idx1);
*(mutant->CitiesFrom + idx1) = *(mutant->CitiesFrom + idx2);
*(mutant->CitiesFrom + idx2) = mutation;

/* adjusting From/To */
for (j = 1; j < mutant->Cities; j++)
{
RouteNodePtr pFrom = *(mutant->CitiesFrom + j);
*(mutant->CitiesTo + j - 1) = pFrom;
}
*(mutant->CitiesTo + mutant->Cities - 1) = *(mutant->CitiesFrom + 0);

/* adjusting Costs */
mutant->TotalCost = 0.0;
for (j = 0; j < mutant->Cities; j++)
{
RouteNodePtr pFrom = *(mutant->CitiesFrom + j);
RouteNodePtr pTo = *(mutant->CitiesTo + j);
double cost = tsp_ga_find_distance (ga, pFrom, pTo);
tps_ga_chromosome_update (mutant, pFrom, pTo, cost);
*(mutant->Costs + j) = cost;
mutant->TotalCost += cost;
}
}
```

### Current Workarounds and Limitations

**Option 1: Disable all optimizations for the function** (Loses all optimizations (vectorization, inlining, etc.))
```c
#pragma clang optimize off
static void tsp_ga_random_mutation(...) { }
#pragma clang optimize on

// or

__attribute__(noinline)
static void tsp_ga_random_mutation(...) { }
```

**Option 2: Disable Polly for entire file** (Affects entire compilation unit)
```bash
-mllvm -polly=false
```

### Requested Feature

A function attribute to selectively disable Polly's parallel code generation:
```c
__attribute__((no_polly_parallel))
static void tsp_ga_random_mutation(...) {
// Polly still optimizes this, but doesn't generate parallel code
}
```

Or a more general approach:
```c
__attribute__((polly_disable("parallel")))
__attribute__((polly_disable("vectorizer")))
```

### Use Case

This would be valuable for:
1. **Working around compiler bugs** - disable problematic passes without losing other optimizations
2. **Performance tuning** - selectively disable parallelization where profiling shows it's counterproductive
3. **Debugging** - isolate which Polly optimization is causing issues

### Alternative Considered

Adding `#pragma clang loop` directives to disable parallelization:
```c
#pragma clang loop vectorize(disable) interleave(disable)
for (...) { }
```

However, this doesn't prevent Polly from attempting parallel code generation at the function level (and doesn't prevent the crash above)

### Environment
- Clang version: 20.0.0git (LLVM 20.0.0git)
- Target: aarch64-unknown-linux-gnu
- Flags: `-O3 -mllvm -polly -mllvm -polly-parallel -mllvm -polly-omp-backend=LLVM`

### Related

Similar fine-grained control exists for other passes:
- `__attribute__((noinline))` - disable inlining
- `__attribute__((no_sanitize(...)))` - disable specific sanitizers
- `#pragma clang loop` - control loop optimizations

Polly would benefit from similar granular control.

---

**CC:** @Meinersbur @grosser @jhuber6

Contributor guide

Open the contributing guide

Research direction

Start by reading Polly's parallel-generation path around polly::IslNodeBuilder::createForParallel and the handling of the -polly-parallel option. Determine how a function-level control could preserve other Polly optimizations, then add coverage showing that the requested function-level setting prevents parallel generation without disabling Polly generally.

Written by the indexing model from the issue text.

Assessment

Tech stack
c
Domain
compilers
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.