Skip to content

Commit e044cc5

Browse files
authored
[GVN] Handle not in equality propagation (#151942)
Look through `not` when propagating equalities in GVN. Usually these will be canonicalized away, but they may be retained due to multi-use or involvement in logical expressions. Fixes #143529.
1 parent 8f7dfc6 commit e044cc5

File tree

2 files changed

+87
-0
lines changed

2 files changed

+87
-0
lines changed

llvm/lib/Transforms/Scalar/GVN.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2683,6 +2683,11 @@ bool GVNPass::propagateEquality(Value *LHS, Value *RHS,
26832683
Worklist.emplace_back(A, ConstantInt::get(A->getType(), IsKnownTrue));
26842684
continue;
26852685
}
2686+
2687+
if (match(LHS, m_Not(m_Value(A)))) {
2688+
Worklist.emplace_back(A, ConstantInt::get(A->getType(), !IsKnownTrue));
2689+
continue;
2690+
}
26862691
}
26872692

26882693
return Changed;

llvm/test/Transforms/GVN/condprop.ll

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -999,5 +999,87 @@ loop.latch:
999999
br label %loop
10001000
}
10011001

1002+
define i1 @not_cond(i1 %c) {
1003+
; CHECK-LABEL: @not_cond(
1004+
; CHECK-NEXT: [[C_NOT:%.*]] = xor i1 [[C:%.*]], true
1005+
; CHECK-NEXT: br i1 [[C_NOT]], label [[IF:%.*]], label [[ELSE:%.*]]
1006+
; CHECK: if:
1007+
; CHECK-NEXT: ret i1 false
1008+
; CHECK: else:
1009+
; CHECK-NEXT: ret i1 true
1010+
;
1011+
%c.not = xor i1 %c, true
1012+
br i1 %c.not, label %if, label %else
1013+
1014+
if:
1015+
ret i1 %c
1016+
1017+
else:
1018+
ret i1 %c
1019+
}
1020+
1021+
define i32 @not_cond_icmp(i32 %x) {
1022+
; CHECK-LABEL: @not_cond_icmp(
1023+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], 42
1024+
; CHECK-NEXT: [[CMP_NOT:%.*]] = xor i1 [[CMP]], true
1025+
; CHECK-NEXT: br i1 [[CMP_NOT]], label [[IF:%.*]], label [[ELSE:%.*]]
1026+
; CHECK: if:
1027+
; CHECK-NEXT: ret i32 [[X]]
1028+
; CHECK: else:
1029+
; CHECK-NEXT: ret i32 42
1030+
;
1031+
%cmp = icmp eq i32 %x, 42
1032+
%cmp.not = xor i1 %cmp, true
1033+
br i1 %cmp.not, label %if, label %else
1034+
1035+
if:
1036+
ret i32 %x
1037+
1038+
else:
1039+
ret i32 %x
1040+
}
1041+
1042+
define i1 @not_cond_logic1(i1 %c, i1 %d) {
1043+
; CHECK-LABEL: @not_cond_logic1(
1044+
; CHECK-NEXT: [[C_NOT:%.*]] = xor i1 [[C:%.*]], true
1045+
; CHECK-NEXT: [[AND:%.*]] = and i1 [[C_NOT]], [[D:%.*]]
1046+
; CHECK-NEXT: br i1 [[AND]], label [[IF:%.*]], label [[ELSE:%.*]]
1047+
; CHECK: if:
1048+
; CHECK-NEXT: ret i1 false
1049+
; CHECK: else:
1050+
; CHECK-NEXT: ret i1 [[C]]
1051+
;
1052+
%c.not = xor i1 %c, true
1053+
%and = and i1 %c.not, %d
1054+
br i1 %and, label %if, label %else
1055+
1056+
if:
1057+
ret i1 %c
1058+
1059+
else:
1060+
ret i1 %c
1061+
}
1062+
1063+
define i1 @not_cond_logic2(i1 %c, i1 %d) {
1064+
; CHECK-LABEL: @not_cond_logic2(
1065+
; CHECK-NEXT: [[C_NOT:%.*]] = xor i1 [[C:%.*]], true
1066+
; CHECK-NEXT: [[AND:%.*]] = or i1 [[C_NOT]], [[D:%.*]]
1067+
; CHECK-NEXT: br i1 [[AND]], label [[IF:%.*]], label [[ELSE:%.*]]
1068+
; CHECK: if:
1069+
; CHECK-NEXT: ret i1 [[C]]
1070+
; CHECK: else:
1071+
; CHECK-NEXT: ret i1 true
1072+
;
1073+
%c.not = xor i1 %c, true
1074+
%or = or i1 %c.not, %d
1075+
br i1 %or, label %if, label %else
1076+
1077+
if:
1078+
ret i1 %c
1079+
1080+
else:
1081+
ret i1 %c
1082+
}
1083+
10021084
declare void @use_bool(i1)
10031085
declare void @use_ptr(ptr)

0 commit comments

Comments
 (0)