mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 04:32:44 +01:00
[SCCP] Propagate inequalities
Teach SCCP to create notconstant lattice values from inequality assumes and nonnull metadata, and update getConstant() to make use of them. Additionally isOverdefined() needs to be changed to consider notconstant an overdefined value. Handling inequality branches is delayed until our branch on undef story in other passes has been improved. Differential Revision: https://reviews.llvm.org/D83643
This commit is contained in:
parent
a69cebb049
commit
a43b952b5a
@ -11,6 +11,7 @@
|
||||
|
||||
#include "llvm/IR/ConstantRange.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/Instructions.h"
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ValueLatticeElement
|
||||
@ -456,6 +457,16 @@ public:
|
||||
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())
|
||||
|
@ -104,8 +104,7 @@ bool isConstant(const ValueLatticeElement &LV) {
|
||||
// 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);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -1123,7 +1122,9 @@ static ValueLatticeElement getValueFromMetadata(const Instruction *I) {
|
||||
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();
|
||||
}
|
||||
|
||||
@ -1291,6 +1292,17 @@ void SCCPSolver::handleCallResult(CallBase &CB) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Actually filp MayIncludeUndef for the created range to false,
|
||||
// once most places in the optimizer respect the branches on
|
||||
// undef/poison are UB rule. The reason why the new range cannot be
|
||||
// undef is as follows below:
|
||||
// The new range is based on a branch condition. That guarantees that
|
||||
// neither of the compare operands can be undef in the branch targets,
|
||||
// unless we have conditions that are always true/false (e.g. icmp ule
|
||||
// i32, %a, i32_max). For the latter overdefined/empty range will be
|
||||
// inferred, but the branch will get folded accordingly anyways.
|
||||
bool MayIncludeUndef = !isa<PredicateAssume>(PI);
|
||||
|
||||
ValueLatticeElement CondVal = getValueState(OtherOp);
|
||||
ValueLatticeElement &IV = ValueState[&CB];
|
||||
if (CondVal.isConstantRange() || CopyOfVal.isConstantRange()) {
|
||||
@ -1316,18 +1328,9 @@ void SCCPSolver::handleCallResult(CallBase &CB) {
|
||||
NewCR = CopyOfCR;
|
||||
|
||||
addAdditionalUser(OtherOp, &CB);
|
||||
// TODO: Actually filp MayIncludeUndef for the created range to false,
|
||||
// once most places in the optimizer respect the branches on
|
||||
// undef/poison are UB rule. The reason why the new range cannot be
|
||||
// undef is as follows below:
|
||||
// The new range is based on a branch condition. That guarantees that
|
||||
// neither of the compare operands can be undef in the branch targets,
|
||||
// unless we have conditions that are always true/false (e.g. icmp ule
|
||||
// i32, %a, i32_max). For the latter overdefined/empty range will be
|
||||
// inferred, but the branch will get folded accordingly anyways.
|
||||
mergeInValue(
|
||||
IV, &CB,
|
||||
ValueLatticeElement::getRange(NewCR, /*MayIncludeUndef=*/true));
|
||||
ValueLatticeElement::getRange(NewCR, MayIncludeUndef));
|
||||
return;
|
||||
} else if (Pred == CmpInst::ICMP_EQ && CondVal.isConstant()) {
|
||||
// For non-integer values or integer constant expressions, only
|
||||
@ -1335,6 +1338,13 @@ void SCCPSolver::handleCallResult(CallBase &CB) {
|
||||
addAdditionalUser(OtherOp, &CB);
|
||||
mergeInValue(IV, &CB, CondVal);
|
||||
return;
|
||||
} else if (Pred == CmpInst::ICMP_NE && CondVal.isConstant() &&
|
||||
!MayIncludeUndef) {
|
||||
// Propagate inequalities.
|
||||
addAdditionalUser(OtherOp, &CB);
|
||||
mergeInValue(IV, &CB,
|
||||
ValueLatticeElement::getNot(CondVal.getConstant()));
|
||||
return;
|
||||
}
|
||||
|
||||
return (void)mergeInValue(IV, &CB, CopyOfVal);
|
||||
|
@ -51,14 +51,10 @@ define void @nonnull(i32* %v) {
|
||||
; CHECK-LABEL: @nonnull(
|
||||
; CHECK-NEXT: [[A:%.*]] = icmp ne i32* [[V:%.*]], null
|
||||
; CHECK-NEXT: call void @llvm.assume(i1 [[A]])
|
||||
; CHECK-NEXT: [[C1:%.*]] = icmp eq i32* [[V]], null
|
||||
; CHECK-NEXT: call void @use(i1 [[C1]])
|
||||
; CHECK-NEXT: [[C2:%.*]] = icmp ne i32* [[V]], null
|
||||
; CHECK-NEXT: call void @use(i1 [[C2]])
|
||||
; CHECK-NEXT: [[C3:%.*]] = icmp eq i32* null, [[V]]
|
||||
; CHECK-NEXT: call void @use(i1 [[C3]])
|
||||
; CHECK-NEXT: [[C4:%.*]] = icmp ne i32* null, [[V]]
|
||||
; CHECK-NEXT: call void @use(i1 [[C4]])
|
||||
; CHECK-NEXT: call void @use(i1 false)
|
||||
; CHECK-NEXT: call void @use(i1 true)
|
||||
; CHECK-NEXT: call void @use(i1 false)
|
||||
; CHECK-NEXT: call void @use(i1 true)
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%a = icmp ne i32* %v, null
|
||||
|
@ -48,14 +48,10 @@ define void @load_nonnull(i32** %p, i32** %p2) {
|
||||
; 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]]
|
||||
|
Loading…
Reference in New Issue
Block a user