Issue 61673
Summary [LoopPredication] Miscompile due to sinking of widenable condition into loop
Labels new issue
Assignees
Reporter max-quazan
    https://godbolt.org/z/8j953fhT6

Run `opt -passes=loop-predication` on the following IR:
```
define i32 @test() {
entry:
  %wc = call i1 @llvm.experimental.widenable.condition()
 br label %outer_loop

outer_backedge: ; preds = %always, %never
  call void @print()
  %cnt.next = add i32 %cnt, 1
  br label %outer_loop

outer_loop: ; preds = %outer_backedge, %entry
  %cnt = phi i32 [0, %entry], [%cnt.next, %outer_backedge]
  br i1 %wc, label %inner_loop.preheader, label %exit

inner_loop.preheader: ; preds = %outer_loop
  br label %inner_loop

inner_loop:                                       ; preds = %never, %inner_loop.preheader
  %iv = phi i32 [ %iv.next, %never ], [ 2, %inner_loop.preheader ]
  %iv.next = add nuw nsw i32 %iv, 1
  br i1 false, label %never, label %always

never: ; preds = %inner_loop
  %icmp = icmp ugt i32 %iv.next, 37
  br i1 %icmp, label %outer_backedge, label %inner_loop

exit: ; preds = %outer_loop
 %cnt.lcssa = phi i32 [%cnt, %outer_loop]
  ret i32 %cnt.lcssa

always:                                           ; preds = %inner_loop
  br label %outer_backedge
}

declare void @print()

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(inaccessiblemem: readwrite)
declare noundef i1 @llvm.experimental.widenable.condition() #0

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(inaccessiblemem: readwrite) }
```

Result:
```
; ModuleID = './reduced.ll'
source_filename = "./reduced.ll"

define void @test() {
entry:
  br label %outer_loop

outer_backedge.loopexit:                          ; preds = %never
  br label %outer_backedge

outer_backedge: ; preds = %outer_backedge.loopexit, %always
  br label %outer_loop

outer_loop:                                       ; preds = %outer_backedge, %entry
  %wc = call i1 @llvm.experimental.widenable.condition()
  br i1 %wc, label %inner_loop.preheader, label %exit

inner_loop.preheader: ; preds = %outer_loop
  br label %inner_loop

inner_loop:                                       ; preds = %never, %inner_loop.preheader
  %iv = phi i32 [ %iv.next, %never ], [ 2, %inner_loop.preheader ]
  %iv.next = add nuw nsw i32 %iv, 1
  br i1 false, label %never, label %always

never: ; preds = %inner_loop
  %icmp = icmp ugt i32 %iv.next, 37
  br i1 %icmp, label %outer_backedge.loopexit, label %inner_loop

exit:                                             ; preds = %outer_loop
  ret void

always: ; preds = %inner_loop
  br label %outer_backedge
}

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(inaccessiblemem: readwrite)
declare noundef i1 @llvm.experimental.widenable.condition() #0

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(inaccessiblemem: readwrite) }
```

The issue is similar to https://github.com/llvm/llvm-project/issues/60234 (but then it was in Guard Widening). We are not allowed to sink widenable conditions into loops. Here is why it is a miscompile:

The behavior of program before the transform is limited to 2 scenarios:
- If `%wc` is true, branch will always go into the inner loop, and the program will infinitely call `@print()`. Program never returns.
- If `%wc` is false, program returns `0`, and `@print()` is never called.

This allows us to optimize return value to `ret i32 0`  (IndVars actually does it, but it also eliminates some other code and breaks the example for unrelated reasons).

After the reansform, `%wc` is computed in the loop. It means that the legal scenario is that the program calls `@print()` 10 times and then exits, returning `9`. It was impossible scenario before the transform.

This code in Loop Predication is wrong: https://gitlab.azulsystems.com/dev/orca/-/blob/master/llvm/lib/Transforms/Scalar/LoopPredication.cpp#L1195

_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to