
Remove compares after replacing all uses. Cleaning dead compares can enable additional simplifications when adjusting the position of the pass slightly. In particular, it seems like the additional dead instructions may prevent SimplifyCFG performing some folds. Reviewed By: nikic Differential Revision: https://reviews.llvm.org/D158760
253 lines
7.2 KiB
LLVM
253 lines
7.2 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s
|
|
|
|
declare void @use(i1)
|
|
declare void @llvm.assume(i1)
|
|
|
|
define void @phi_loop_1(i8 %x) {
|
|
; CHECK-LABEL: @phi_loop_1(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[C_0:%.*]] = icmp uge i8 [[X:%.*]], 10
|
|
; CHECK-NEXT: br i1 [[C_0]], label [[LOOP:%.*]], label [[EXIT:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[C_PHI:%.*]] = phi i1 [ false, [[ENTRY]] ], [ true, [[LOOP]] ]
|
|
; CHECK-NEXT: call void @use(i1 true)
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1
|
|
; CHECK-NEXT: [[EC:%.*]] = icmp ult i8 [[IV_NEXT]], 3
|
|
; CHECK-NEXT: br i1 [[EC]], label [[LOOP]], label [[LOOP_EXIT:%.*]]
|
|
; CHECK: loop.exit:
|
|
; CHECK-NEXT: call void @use(i1 [[C_PHI]])
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%c.0 = icmp uge i8 %x, 10
|
|
br i1 %c.0, label %loop, label %exit
|
|
|
|
loop:
|
|
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
|
|
%c.phi = phi i1 [ false, %entry ], [ %t.1, %loop ]
|
|
%t.1 = icmp uge i8 %x, 8
|
|
call void @use(i1 %t.1)
|
|
%iv.next = add i8 %iv, 1
|
|
%ec = icmp ult i8 %iv.next, 3
|
|
br i1 %ec, label %loop, label %loop.exit
|
|
|
|
loop.exit:
|
|
call void @use(i1 %c.phi)
|
|
br label %exit
|
|
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
define void @phi_loop_2(i8 %x) {
|
|
; CHECK-LABEL: @phi_loop_2(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[C_0:%.*]] = icmp uge i8 [[X:%.*]], 10
|
|
; CHECK-NEXT: br i1 [[C_0]], label [[LOOP_1_HEADER:%.*]], label [[EXIT:%.*]]
|
|
; CHECK: loop.1.header:
|
|
; CHECK-NEXT: [[C_PHI:%.*]] = phi i1 [ false, [[ENTRY:%.*]] ], [ true, [[LOOP_1_LATCH:%.*]] ]
|
|
; CHECK-NEXT: br label [[LOOP_2:%.*]]
|
|
; CHECK: loop.2:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ 0, [[LOOP_1_HEADER]] ], [ [[IV_NEXT:%.*]], [[LOOP_2]] ]
|
|
; CHECK-NEXT: call void @use(i1 true)
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1
|
|
; CHECK-NEXT: [[EC:%.*]] = icmp ult i8 [[IV_NEXT]], 3
|
|
; CHECK-NEXT: br i1 [[EC]], label [[LOOP_2]], label [[LOOP_1_LATCH]]
|
|
; CHECK: loop.1.latch:
|
|
; CHECK-NEXT: br i1 false, label [[LOOP_1_HEADER]], label [[LOOP_1_EXIT:%.*]]
|
|
; CHECK: loop.1.exit:
|
|
; CHECK-NEXT: call void @use(i1 [[C_PHI]])
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%c.0 = icmp uge i8 %x, 10
|
|
br i1 %c.0, label %loop.1.header, label %exit
|
|
|
|
loop.1.header:
|
|
%c.phi = phi i1 [ false, %entry ], [ %t.1, %loop.1.latch ]
|
|
br label %loop.2
|
|
|
|
loop.2:
|
|
%iv = phi i8 [ 0, %loop.1.header ], [ %iv.next, %loop.2 ]
|
|
%t.1 = icmp uge i8 %x, 8
|
|
call void @use(i1 %t.1)
|
|
%iv.next = add i8 %iv, 1
|
|
%ec = icmp ult i8 %iv.next, 3
|
|
br i1 %ec, label %loop.2, label %loop.1.latch
|
|
|
|
loop.1.latch:
|
|
br i1 false, label %loop.1.header, label %loop.1.exit
|
|
|
|
loop.1.exit:
|
|
call void @use(i1 %c.phi)
|
|
br label %exit
|
|
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
define void @phi_loop_3(i8 %x, i1 %c) {
|
|
; CHECK-LABEL: @phi_loop_3(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[C_0:%.*]] = icmp uge i8 [[X:%.*]], 10
|
|
; CHECK-NEXT: br i1 [[C_0]], label [[LOOP:%.*]], label [[EXIT:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
|
|
; CHECK-NEXT: [[C_PHI:%.*]] = phi i1 [ false, [[ENTRY]] ], [ true, [[LOOP_LATCH]] ]
|
|
; CHECK-NEXT: br i1 [[C:%.*]], label [[LOOP_LATCH]], label [[LOOP_EXIT:%.*]]
|
|
; CHECK: loop.latch:
|
|
; CHECK-NEXT: call void @use(i1 true)
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1
|
|
; CHECK-NEXT: [[EC:%.*]] = icmp ult i8 [[IV_NEXT]], 3
|
|
; CHECK-NEXT: br i1 [[EC]], label [[LOOP]], label [[LOOP_EXIT]]
|
|
; CHECK: loop.exit:
|
|
; CHECK-NEXT: call void @use(i1 [[C_PHI]])
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%c.0 = icmp uge i8 %x, 10
|
|
br i1 %c.0, label %loop, label %exit
|
|
|
|
loop:
|
|
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop.latch ]
|
|
%c.phi = phi i1 [ false, %entry ], [ %t.1, %loop.latch ]
|
|
br i1 %c, label %loop.latch, label %loop.exit
|
|
|
|
loop.latch:
|
|
%t.1 = icmp uge i8 %x, 8
|
|
call void @use(i1 %t.1)
|
|
%iv.next = add i8 %iv, 1
|
|
%ec = icmp ult i8 %iv.next, 3
|
|
br i1 %ec, label %loop, label %loop.exit
|
|
|
|
loop.exit:
|
|
call void @use(i1 %c.phi)
|
|
br label %exit
|
|
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
define i1 @test_if_then_1(i8 %x) {
|
|
; CHECK-LABEL: @test_if_then_1(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i8 [[X:%.*]], 1
|
|
; CHECK-NEXT: br i1 [[CMP1]], label [[IF:%.*]], label [[JOIN:%.*]]
|
|
; CHECK: if:
|
|
; CHECK-NEXT: br label [[JOIN]]
|
|
; CHECK: join:
|
|
; CHECK-NEXT: [[PHI:%.*]] = phi i1 [ true, [[IF]] ], [ false, [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: ret i1 [[PHI]]
|
|
;
|
|
entry:
|
|
%cmp1 = icmp sgt i8 %x, 1
|
|
br i1 %cmp1, label %if, label %join
|
|
|
|
if:
|
|
%cmp2 = icmp sgt i8 %x, 0
|
|
br label %join
|
|
|
|
join:
|
|
%phi = phi i1 [ %cmp2, %if ], [ false, %entry ]
|
|
ret i1 %phi
|
|
}
|
|
|
|
|
|
define i1 @test_if_then_2(i1 %c, i8 %x) {
|
|
; CHECK-LABEL: @test_if_then_2(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[JOIN:%.*]]
|
|
; CHECK: if:
|
|
; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i8 [[X:%.*]], 1
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP1]])
|
|
; CHECK-NEXT: br label [[JOIN]]
|
|
; CHECK: join:
|
|
; CHECK-NEXT: [[PHI:%.*]] = phi i1 [ true, [[IF]] ], [ false, [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: ret i1 [[PHI]]
|
|
;
|
|
entry:
|
|
%cmp2 = icmp sgt i8 %x, 0
|
|
br i1 %c, label %if, label %join
|
|
|
|
if:
|
|
%cmp1 = icmp sgt i8 %x, 1
|
|
call void @llvm.assume(i1 %cmp1)
|
|
br label %join
|
|
|
|
join:
|
|
%phi = phi i1 [ %cmp2, %if ], [ false, %entry ]
|
|
ret i1 %phi
|
|
}
|
|
|
|
define i1 @test_if_then_3(i1 %c.0, i8 %x) {
|
|
; CHECK-LABEL: @test_if_then_3(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br i1 [[C_0:%.*]], label [[IF:%.*]], label [[JOIN:%.*]]
|
|
; CHECK: if:
|
|
; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i8 [[X:%.*]], 1
|
|
; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i8 [[X]], 1
|
|
; CHECK-NEXT: br i1 [[CMP1]], label [[THEN_1:%.*]], label [[JOIN]]
|
|
; CHECK: then.1:
|
|
; CHECK-NEXT: br label [[JOIN]]
|
|
; CHECK: join:
|
|
; CHECK-NEXT: [[PHI:%.*]] = phi i1 [ [[CMP2]], [[IF]] ], [ true, [[THEN_1]] ], [ false, [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: ret i1 [[PHI]]
|
|
;
|
|
entry:
|
|
br i1 %c.0, label %if, label %join
|
|
|
|
if:
|
|
%cmp1 = icmp sgt i8 %x, 1
|
|
%cmp2 = icmp sgt i8 %x, 1
|
|
br i1 %cmp1, label %then.1, label %join
|
|
|
|
then.1:
|
|
br label %join
|
|
|
|
join:
|
|
%phi = phi i1 [ %cmp2, %if ], [ %cmp2, %then.1 ], [ false, %entry ]
|
|
ret i1 %phi
|
|
}
|
|
|
|
define i1 @test_if_then_4(i1 %c.0, i8 %x) {
|
|
; CHECK-LABEL: @test_if_then_4(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br i1 [[C_0:%.*]], label [[IF:%.*]], label [[JOIN:%.*]]
|
|
; CHECK: if:
|
|
; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i8 [[X:%.*]], 1
|
|
; CHECK-NEXT: br i1 [[CMP1]], label [[THEN_1:%.*]], label [[ELSE_1:%.*]]
|
|
; CHECK: then.1:
|
|
; CHECK-NEXT: br label [[JOIN]]
|
|
; CHECK: else.1:
|
|
; CHECK-NEXT: br label [[JOIN]]
|
|
; CHECK: join:
|
|
; CHECK-NEXT: [[PHI:%.*]] = phi i1 [ false, [[ELSE_1]] ], [ true, [[THEN_1]] ], [ false, [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: ret i1 [[PHI]]
|
|
;
|
|
entry:
|
|
br i1 %c.0, label %if, label %join
|
|
|
|
if:
|
|
%cmp1 = icmp sgt i8 %x, 1
|
|
%cmp2 = icmp sgt i8 %x, 1
|
|
br i1 %cmp1, label %then.1, label %else.1
|
|
|
|
then.1:
|
|
br label %join
|
|
|
|
else.1:
|
|
br label %join
|
|
|
|
join:
|
|
%phi = phi i1 [ %cmp2, %else.1 ], [ %cmp2, %then.1 ], [ false, %entry ]
|
|
ret i1 %phi
|
|
}
|