
This patch updates ConstraintElimination to track uses of conditions in the worklist. This allows simplifying conditions using the context that holds directly at the condition, instead of where the condition is defined. This allows us to catch more cases in practice: there are multiple code-size changes for CTMark while compile-time remains unchanged: https://llvm-compile-time-tracker.com/compare.php?from=4b020cca9363bebab4643f89cfa92ab2fcc7976c&to=7a6e84b8f029713c137814cd46eec775d24a54a1&stat=instructions:u This should help to simplify D151799. Reviewed By: nikic Differential Revision: https://reviews.llvm.org/D153660
101 lines
3.0 KiB
LLVM
101 lines
3.0 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
|
|
; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s
|
|
|
|
declare i1 @cond()
|
|
declare void @clobber()
|
|
|
|
|
|
define void @test_unreachable_latch(ptr %start, ptr %b) {
|
|
; CHECK-LABEL: define void @test_unreachable_latch
|
|
; CHECK-SAME: (ptr [[START:%.*]], ptr [[B:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
|
|
; CHECK: loop.header:
|
|
; CHECK-NEXT: [[NODE_1:%.*]] = phi ptr [ [[START]], [[ENTRY:%.*]] ], [ null, [[LOOP_LATCH:%.*]] ]
|
|
; CHECK-NEXT: [[C_0:%.*]] = icmp ne ptr [[NODE_1]], null
|
|
; CHECK-NEXT: br i1 [[C_0]], label [[THEN:%.*]], label [[EXIT:%.*]]
|
|
; CHECK: loop.latch:
|
|
; CHECK-NEXT: call void @clobber()
|
|
; CHECK-NEXT: br label [[LOOP_HEADER]]
|
|
; CHECK: if:
|
|
; CHECK-NEXT: [[C_2:%.*]] = icmp ne ptr [[B]], null
|
|
; CHECK-NEXT: [[AND:%.*]] = and i1 [[C_2]], [[C_0]]
|
|
; CHECK-NEXT: br i1 [[AND]], label [[THEN]], label [[EXIT]]
|
|
; CHECK: then:
|
|
; CHECK-NEXT: call void @clobber()
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %loop.header
|
|
|
|
loop.header:
|
|
%node.1 = phi ptr [ %start, %entry ], [ null, %loop.latch ]
|
|
%c.0 = icmp ne ptr %node.1, null
|
|
br i1 %c.0, label %then, label %exit
|
|
|
|
loop.latch: ; No predecessors!
|
|
call void @clobber()
|
|
br label %loop.header
|
|
|
|
if:
|
|
%c.2 = icmp ne ptr %b, null
|
|
%and = and i1 %c.2, %c.0
|
|
br i1 %and, label %then, label %exit
|
|
|
|
then:
|
|
call void @clobber()
|
|
br label %exit
|
|
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
define void @test_cond_multi_use_with_one_use_simplified_before_adding_ne_fact(ptr %start, ptr %b) {
|
|
; CHECK-LABEL: define void @test_cond_multi_use_with_one_use_simplified_before_adding_ne_fact
|
|
; CHECK-SAME: (ptr [[START:%.*]], ptr [[B:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
|
|
; CHECK: loop.header:
|
|
; CHECK-NEXT: [[NODE_1:%.*]] = phi ptr [ [[START]], [[ENTRY:%.*]] ], [ null, [[LOOP_LATCH:%.*]] ]
|
|
; CHECK-NEXT: [[C_0:%.*]] = icmp ne ptr [[NODE_1]], null
|
|
; CHECK-NEXT: br i1 [[C_0]], label [[LOOP_LATCH]], label [[EXIT:%.*]]
|
|
; CHECK: loop.latch:
|
|
; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond()
|
|
; CHECK-NEXT: br i1 [[C_1]], label [[IF:%.*]], label [[LOOP_HEADER]]
|
|
; CHECK: if:
|
|
; CHECK-NEXT: [[C_2:%.*]] = icmp ne ptr [[B]], null
|
|
; CHECK-NEXT: [[AND:%.*]] = and i1 [[C_2]], true
|
|
; CHECK-NEXT: br i1 [[AND]], label [[THEN:%.*]], label [[EXIT]]
|
|
; CHECK: then:
|
|
; CHECK-NEXT: call void @clobber()
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %loop.header
|
|
|
|
loop.header:
|
|
%node.1 = phi ptr [ %start, %entry ], [ null, %loop.latch ]
|
|
%c.0 = icmp ne ptr %node.1, null
|
|
br i1 %c.0, label %loop.latch, label %exit
|
|
|
|
loop.latch:
|
|
%c.1 = call i1 @cond()
|
|
br i1 %c.1, label %if, label %loop.header
|
|
|
|
if:
|
|
%c.2 = icmp ne ptr %b, null
|
|
%and = and i1 %c.2, %c.0
|
|
br i1 %and, label %then, label %exit
|
|
|
|
then:
|
|
call void @clobber()
|
|
br label %exit
|
|
|
|
exit:
|
|
ret void
|
|
}
|