Issue 90937
Summary Miscompile loop-interchange pass because of GEP delinealization.
Labels new issue
Assignees
Reporter sanggyu-shin
    Following code is loop interchangable but current llvm can't do it.
```
for (int i = 0; i < LEN_2D; ++i)
 for (int j = 1; j < LEN_2D; j++)
        aa[j][i] = aa[j - 1][i] + bb[j][i];
```
I found that there is a problem about delinealization after LICM pass.
Here is llvm ir after LICM pass:
```
define dso_local void @func(ptr nocapture noundef %aa, ptr nocapture noundef readonly %bb) local_unnamed_addr #0 {
entry:
  %invariant.gep = getelementptr i8, ptr %aa, i64 -8000
  br label %for.cond1.preheader

for.cond1.preheader: ; preds = %entry, %for.cond.cleanup3
  %indvars.iv31 = phi i64 [ 0, %entry ], [ %indvars.iv.next32, %for.cond.cleanup3 ]
  %invariant.gep27 = getelementptr [1000 x double], ptr %invariant.gep, i64 0, i64 %indvars.iv31
  br label %for.body4

for.cond.cleanup: ; preds = %for.cond.cleanup3
  ret void

for.cond.cleanup3:                                ; preds = %for.body4
  %indvars.iv.next32 = add nuw nsw i64 %indvars.iv31, 1
 %exitcond33 = icmp ne i64 %indvars.iv.next32, 1000
  br i1 %exitcond33, label %for.cond1.preheader, label %for.cond.cleanup

for.body4: ; preds = %for.cond1.preheader, %for.body4
 %indvars.iv = phi i64 [ 1, %for.cond1.preheader ], [ %indvars.iv.next, %for.body4 ]
  %gep28 = getelementptr [1000 x double], ptr %invariant.gep27, i64 %indvars.iv
  %0 = load double, ptr %gep28, align 8
  %arrayidx10 = getelementptr inbounds [1000 x double], ptr %bb, i64 %indvars.iv, i64 %indvars.iv31
  %1 = load double, ptr %arrayidx10, align 8
  %add = fadd double %0, %1
  %arrayidx14 = getelementptr inbounds [1000 x double], ptr %aa, i64 %indvars.iv, i64 %indvars.iv31
  store double %add, ptr %arrayidx14, align 8
  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
  %exitcond = icmp ne i64 %indvars.iv.next, 1000
  br i1 %exitcond, label %for.body4, label %for.cond.cleanup3
}
```
run commend: 
```
$ opt loop-interchange.bc -debug -passes=loop-interchange -pass-remarks-missed='loop-interchange' -o test.bc
remark: <unknown>:0:0: Cannot interchange loops due to dependences.
```
Debug print out:
```
Delinearizing:   %0 = load double, ptr %gep28, align 8
  In Loop 'for.body4', AccessFn: {{0,+,8}<nuw><nsw><%for.cond1.preheader>,+,8000}<%for.body4>
Strides:
8000
8
Terms:
 ERROR: failed to delinearize reference
```

Delinealization got faild when the source is from multiple GEP. 
For example, in ```%0 = load``` in ```for.body4```, the source is ```%gep28```.
But, the problem is that the source of ```gep28``` is also GEP(```$invariant.gep27```)
Actually, the original gep (before LICM) had two indices but gep28 has only one index after LICM.
Current delinealization can't track the recursive gep instructions. So, it can't know exact subscripts.

I would like to discuss the root cause and what part should be modified because I'm not an expert of LLVM.
I think there are two approaches to fix this problem.
1) Modify delinealization - support recursive GEP.
2) Modify LICM.

Please give me an idea if you have any suggestions.

_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to