diff --git a/llvm/lib/Analysis/LazyValueInfo.cpp b/llvm/lib/Analysis/LazyValueInfo.cpp --- a/llvm/lib/Analysis/LazyValueInfo.cpp +++ b/llvm/lib/Analysis/LazyValueInfo.cpp @@ -129,6 +129,21 @@ B.isConstantRangeIncludingUndef()); } +static ValueLatticeElement inverse(const ValueLatticeElement &A) +{ + if (A.isUnknown() || A.isUndef() || A.isOverdefined()) + return A; + + if (A.isConstant()) + return ValueLatticeElement::getNot(A.getConstant()); + + if (A.isNotConstant()) + return ValueLatticeElement::get(A.getNotConstant()); + + ConstantRange Range = A.getConstantRange().inverse(); + return ValueLatticeElement::getRange(Range, A.isConstantRangeIncludingUndef()); +} + //===----------------------------------------------------------------------===// // LazyValueInfoCache Decl //===----------------------------------------------------------------------===// @@ -1181,6 +1196,16 @@ return getValueFromOverflowCondition(Val, WO, isTrueDest); } + Value *N; + if (match(Cond, m_Not(m_Value(N)))) { + auto NV = Visited.find(N); + if (NV == Visited.end()) { + Worklist.push_back(N); + return std::nullopt; + } + return inverse(NV->second); + } + Value *L, *R; bool IsAnd; if (match(Cond, m_LogicalAnd(m_Value(L), m_Value(R)))) diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/basic.ll b/llvm/test/Transforms/CorrelatedValuePropagation/basic.ll --- a/llvm/test/Transforms/CorrelatedValuePropagation/basic.ll +++ b/llvm/test/Transforms/CorrelatedValuePropagation/basic.ll @@ -1853,6 +1853,28 @@ ret void } +define i1 @xor_neg_cond(i32 %a) { +; CHECK-LABEL: @xor_neg_cond( +; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], 10 +; CHECK-NEXT: [[XOR:%.*]] = xor i1 [[CMP1]], true +; CHECK-NEXT: br i1 [[XOR]], label [[EXIT:%.*]], label [[GUARD:%.*]] +; CHECK: guard: +; CHECK-NEXT: ret i1 true +; CHECK: exit: +; CHECK-NEXT: ret i1 false +; + %cmp1 = icmp eq i32 %a, 10 + %xor = xor i1 %cmp1, true + br i1 %xor, label %exit, label %guard + +guard: + %cmp2 = icmp eq i32 %a, 10 + ret i1 %cmp2 + +exit: + ret i1 false +} + declare i32 @llvm.uadd.sat.i32(i32, i32) declare i32 @llvm.usub.sat.i32(i32, i32) declare i32 @llvm.sadd.sat.i32(i32, i32)