Loop predication can insert assumes to preserve knowledge about some facts that may otherwise be lost, because loop predication is a lossy transform. When a guard is represented as branch by widenable condition, it should insert it in the guarded block. However, if the guarded block has other predecessors than the guard block, then the condition might not dominate it. Currently we generate invalid code here. One possible fix here is to split critical edge and insert the assume there, but in this case we should modify CFG, which Loop Predication is not currently doing, and we want to keep it that way. The fix is to handle this case by inserting a Phi which takes `Cond` as input from the guard block and `true` from any other blocks. This is valid in terms of IR and does not introduce any new knowledge if we came from another block. Differential Revision: https://reviews.llvm.org/D144859 Reviewed By: nikic, skatkov
67 lines
2.6 KiB
LLVM
67 lines
2.6 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt -S -passes=loop-predication < %s 2>&1 | FileCheck %s
|
|
|
|
declare void @llvm.experimental.deoptimize.isVoid(...)
|
|
|
|
define void @test_01(i1 %cond) {
|
|
; CHECK-LABEL: @test_01(
|
|
; CHECK-NEXT: bb:
|
|
; CHECK-NEXT: [[INST:%.*]] = call i1 @llvm.experimental.widenable.condition()
|
|
; CHECK-NEXT: [[TMP0:%.*]] = and i1 true, [[INST]]
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: unreached:
|
|
; CHECK-NEXT: unreachable
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[INST3:%.*]] = phi i32 [ 0, [[BB:%.*]] ], [ [[INST4:%.*]], [[BACKEDGE:%.*]] ]
|
|
; CHECK-NEXT: [[INST4]] = add nsw i32 [[INST3]], 1
|
|
; CHECK-NEXT: br i1 [[COND:%.*]], label [[BACKEDGE]], label [[GUARD_BLOCK:%.*]]
|
|
; CHECK: normal_ret:
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: backedge:
|
|
; CHECK-NEXT: [[ASSUME_COND:%.*]] = phi i1 [ [[INST9:%.*]], [[GUARD_BLOCK]] ], [ true, [[LOOP]] ]
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[ASSUME_COND]])
|
|
; CHECK-NEXT: [[INST7:%.*]] = icmp sgt i32 [[INST3]], 137
|
|
; CHECK-NEXT: br i1 [[INST7]], label [[UNREACHED:%.*]], label [[LOOP]]
|
|
; CHECK: guard_block:
|
|
; CHECK-NEXT: [[INST9]] = icmp ult i32 [[INST4]], 10000
|
|
; CHECK-NEXT: br i1 [[TMP0]], label [[BACKEDGE]], label [[DEOPT:%.*]]
|
|
; CHECK: deopt:
|
|
; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid(i32 13) [ "deopt"() ]
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: done:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
bb:
|
|
%inst = call i1 @llvm.experimental.widenable.condition()
|
|
br label %loop
|
|
|
|
unreached: ; preds = %backedge
|
|
unreachable
|
|
|
|
loop: ; preds = %backedge, %bb
|
|
%inst3 = phi i32 [ 0, %bb ], [ %inst4, %backedge ]
|
|
%inst4 = add nsw i32 %inst3, 1
|
|
br i1 %cond, label %backedge, label %guard_block
|
|
|
|
normal_ret: ; preds = %loop
|
|
ret void
|
|
|
|
backedge: ; preds = %guard_block, %loop
|
|
%inst7 = icmp sgt i32 %inst3, 137
|
|
br i1 %inst7, label %unreached, label %loop
|
|
|
|
guard_block: ; preds = %loop, %loop
|
|
%inst9 = icmp ult i32 %inst4, 10000
|
|
%inst10 = and i1 %inst9, %inst
|
|
br i1 %inst10, label %backedge, label %deopt
|
|
|
|
deopt: ; preds = %guard_block
|
|
call void (...) @llvm.experimental.deoptimize.isVoid(i32 13) [ "deopt"() ]
|
|
ret void
|
|
|
|
done: ; preds = %loop
|
|
ret void
|
|
}
|
|
|
|
declare i1 @llvm.experimental.widenable.condition()
|