[SCCP] Only handle unknown lattice values in resolvedUndefsIn()

This is a minor refinement of resolvedUndefsIn(), mostly for clarity.
If the value of an instruction is undef, then that's already a legal
final result -- we can safely rauw such an instruction with undef.
We only need to mark unknown values as overdefined, as that's the
result we get for an instruction that has not been processed because
it has an undef operand.

Differential Revision: https://reviews.llvm.org/D128251
This commit is contained in:
Nikita Popov 2022-06-21 10:34:41 +02:00
parent 4a78225212
commit 9b994593cc
3 changed files with 13 additions and 19 deletions

View File

@ -1456,7 +1456,7 @@ void SCCPInstVisitor::solve() {
/// However, if the operand remains undef when the solver returns, we do need
/// to assign some result to the instruction (otherwise we would treat it as
/// unreachable). For simplicity, we mark any instructions that are still
/// unknown/undef as overdefined.
/// unknown as overdefined.
bool SCCPInstVisitor::resolvedUndefsIn(Function &F) {
bool MadeChange = false;
for (BasicBlock &BB : F) {
@ -1485,7 +1485,7 @@ bool SCCPInstVisitor::resolvedUndefsIn(Function &F) {
// more precise than this but it isn't worth bothering.
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
ValueLatticeElement &LV = getStructValueState(&I, i);
if (LV.isUnknownOrUndef()) {
if (LV.isUnknown()) {
markOverdefined(LV, &I);
MadeChange = true;
}
@ -1494,7 +1494,7 @@ bool SCCPInstVisitor::resolvedUndefsIn(Function &F) {
}
ValueLatticeElement &LV = getValueState(&I);
if (!LV.isUnknownOrUndef())
if (!LV.isUnknown())
continue;
// There are two reasons a call can have an undef result

View File

@ -11,8 +11,7 @@ define void @fn2(i32* %P) {
; CHECK: for.cond1:
; CHECK-NEXT: unreachable
; CHECK: if.end:
; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* undef, align 4
; CHECK-NEXT: [[CALL:%.*]] = call i32 @fn1(i32 [[TMP0]])
; CHECK-NEXT: [[CALL:%.*]] = call i32 @fn1(i32 undef)
; CHECK-NEXT: store i32 [[CALL]], i32* [[P]], align 4
; CHECK-NEXT: br label [[FOR_COND1:%.*]]
;
@ -34,8 +33,8 @@ define internal i32 @fn1(i32 %p1) {
; CHECK-LABEL: define {{[^@]+}}@fn1
; CHECK-SAME: (i32 [[P1:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[P1]], 0
; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 [[P1]], i32 [[P1]]
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 undef, 0
; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 undef, i32 undef
; CHECK-NEXT: ret i32 [[COND]]
;
entry:
@ -52,8 +51,7 @@ define void @fn_no_null_opt(i32* %P) #0 {
; CHECK: for.cond1:
; CHECK-NEXT: unreachable
; CHECK: if.end:
; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* undef, align 4
; CHECK-NEXT: [[CALL:%.*]] = call i32 @fn0(i32 [[TMP0]])
; CHECK-NEXT: [[CALL:%.*]] = call i32 @fn0(i32 undef)
; CHECK-NEXT: store i32 [[CALL]], i32* [[P]], align 4
; CHECK-NEXT: br label [[FOR_COND1:%.*]]
;
@ -75,8 +73,8 @@ define internal i32 @fn0(i32 %p1) {
; CHECK-LABEL: define {{[^@]+}}@fn0
; CHECK-SAME: (i32 [[P1:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[P1]], 0
; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 [[P1]], i32 [[P1]]
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 undef, 0
; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 undef, i32 undef
; CHECK-NEXT: ret i32 [[COND]]
;
entry:

View File

@ -5,17 +5,13 @@ target triple = "x86_64-unknown-linux-gnu"
define void @test() {
; CHECK-LABEL: @test(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label %Flow5.pre
; CHECK-NEXT: br label [[FLOW5_PRE:%.*]]
; CHECK: Flow6:
; CHECK-NEXT: br i1 undef, label %end1, label %end2
; CHECK-NEXT: unreachable
; CHECK: Flow5.pre:
; CHECK-NEXT: br label %Flow5
; CHECK-NEXT: br label [[FLOW5:%.*]]
; CHECK: Flow5:
; CHECK-NEXT: br label %Flow6
; CHECK: end1:
; CHECK-NEXT: unreachable
; CHECK: end2:
; CHECK-NEXT: unreachable
; CHECK-NEXT: br label [[FLOW6:%.*]]
;
entry:
br i1 true, label %Flow5.pre, label %Flow5.pre.unreachable