Florian Hahn 13ffde316a
[ConstraintElim] Remove dead compares after simplification.
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
2023-08-24 22:12:57 +01:00

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
}