Index: llvm/include/llvm/Analysis/ValueLattice.h =================================================================== --- llvm/include/llvm/Analysis/ValueLattice.h +++ llvm/include/llvm/Analysis/ValueLattice.h @@ -11,6 +11,7 @@ #include "llvm/IR/ConstantRange.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/Instructions.h" // //===----------------------------------------------------------------------===// // ValueLatticeElement @@ -456,6 +457,16 @@ if (isConstant() && Other.isConstant()) return ConstantExpr::getCompare(Pred, getConstant(), Other.getConstant()); + if (ICmpInst::isEquality(Pred)) { + // not(C) != C => true, not(C) == C => false. + if ((isNotConstant() && Other.isConstant() && + getNotConstant() == Other.getConstant()) || + (isConstant() && Other.isNotConstant() && + getConstant() == Other.getNotConstant())) + return Pred == ICmpInst::ICMP_NE + ? ConstantInt::getTrue(Ty) : ConstantInt::getFalse(Ty); + } + // Integer constants are represented as ConstantRanges with single // elements. if (!isConstantRange() || !Other.isConstantRange()) Index: llvm/lib/Transforms/Scalar/SCCP.cpp =================================================================== --- llvm/lib/Transforms/Scalar/SCCP.cpp +++ llvm/lib/Transforms/Scalar/SCCP.cpp @@ -103,8 +103,7 @@ // ValueLatticeElement::isOverdefined() and is intended to be used in the // transition to ValueLatticeElement. bool isOverdefined(const ValueLatticeElement &LV) { - return LV.isOverdefined() || - (LV.isConstantRange() && !LV.getConstantRange().isSingleElement()); + return !LV.isUnknownOrUndef() && !isConstant(LV); } //===----------------------------------------------------------------------===// @@ -1109,7 +1108,9 @@ if (I->getType()->isIntegerTy()) return ValueLatticeElement::getRange( getConstantRangeFromMetadata(*Ranges)); - // TODO: Also handle MD_nonnull. + if (I->hasMetadata(LLVMContext::MD_nonnull)) + return ValueLatticeElement::getNot( + ConstantPointerNull::get(cast<PointerType>(I->getType()))); return ValueLatticeElement::getOverdefined(); } @@ -1319,6 +1320,12 @@ addAdditionalUser(OtherOp, &CB); mergeInValue(IV, &CB, CondVal); return; + } else if (Pred == CmpInst::ICMP_NE && CondVal.isConstant()) { + // Propagate inequalities. + addAdditionalUser(OtherOp, &CB); + mergeInValue(IV, &CB, + ValueLatticeElement::getNot(CondVal.getConstant())); + return; } return (void)mergeInValue(IV, &CB, CopyOfVal); Index: llvm/test/Transforms/SCCP/conditions-ranges.ll =================================================================== --- llvm/test/Transforms/SCCP/conditions-ranges.ll +++ llvm/test/Transforms/SCCP/conditions-ranges.ll @@ -85,7 +85,6 @@ ret void } -; TODO: Use information %a != 0 in false branch. define void @f2_ptr(i8* %a, i8* %b) { ; CHECK-LABEL: @f2_ptr( ; CHECK-NEXT: entry: @@ -98,10 +97,8 @@ ; CHECK-NEXT: call void @use(i1 [[C_1]]) ; CHECK-NEXT: ret void ; CHECK: false: -; CHECK-NEXT: [[F_2:%.*]] = icmp eq i8* [[A]], null -; CHECK-NEXT: call void @use(i1 [[F_2]]) -; CHECK-NEXT: [[T_2:%.*]] = icmp ne i8* [[A]], null -; CHECK-NEXT: call void @use(i1 [[T_2]]) +; CHECK-NEXT: call void @use(i1 false) +; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: [[C_2:%.*]] = icmp eq i8* [[A]], [[B]] ; CHECK-NEXT: call void @use(i1 [[C_2]]) ; CHECK-NEXT: ret void @@ -236,7 +233,7 @@ ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: ret void ; CHECK: true: -; CHECK-NEXT: store i32 [[B:%.*]], i32* [[A]] +; CHECK-NEXT: store i32 [[B:%.*]], i32* [[A]], align 4 ; CHECK-NEXT: ret void ; entry: Index: llvm/test/Transforms/SCCP/metadata.ll =================================================================== --- llvm/test/Transforms/SCCP/metadata.ll +++ llvm/test/Transforms/SCCP/metadata.ll @@ -48,14 +48,10 @@ ; CHECK-LABEL: @load_nonnull( ; CHECK-NEXT: [[V:%.*]] = load i32*, i32** [[P:%.*]], align 8, !nonnull !2 ; CHECK-NEXT: [[V2:%.*]] = load i32*, i32** [[P2:%.*]], align 8, !nonnull !2 -; CHECK-NEXT: [[C1:%.*]] = icmp ne i32* [[V]], null -; CHECK-NEXT: call void @use(i1 [[C1]]) -; CHECK-NEXT: [[C2:%.*]] = icmp eq i32* [[V]], null -; CHECK-NEXT: call void @use(i1 [[C2]]) -; CHECK-NEXT: [[C3:%.*]] = icmp ne i32* null, [[V]] -; CHECK-NEXT: call void @use(i1 [[C3]]) -; CHECK-NEXT: [[C4:%.*]] = icmp eq i32* null, [[V]] -; CHECK-NEXT: call void @use(i1 [[C4]]) +; CHECK-NEXT: call void @use(i1 true) +; CHECK-NEXT: call void @use(i1 false) +; CHECK-NEXT: call void @use(i1 true) +; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: [[C5:%.*]] = icmp eq i32* [[V]], [[V2]] ; CHECK-NEXT: call void @use(i1 [[C5]]) ; CHECK-NEXT: [[C6:%.*]] = icmp ne i32* [[V]], [[V2]]