From 650f363bd75a2c112e58a9c9efbe8ad52ba943c0 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Sun, 15 Mar 2020 10:35:39 +0000 Subject: [PATCH] [ValueLattice] Add singlecrfromundef lattice value. This patch adds a new singlecrfromundef lattice value, indicating a single element constant range which was merge with undef at some point. Merging it with another constant range results in overdefined, as we won't be able to replace all users with a single value. This patch uses a ConstantRange instead of a Constant*, because regular integer constants are represented as single element constant ranges as well and this allows the existing code working without additional changes. Reviewers: efriedma, nikic, reames, davide Reviewed By: efriedma Differential Revision: https://reviews.llvm.org/D75845 --- llvm/include/llvm/Analysis/ValueLattice.h | 52 ++++++++++++++++--- llvm/lib/Analysis/ValueLattice.cpp | 6 +++ .../merge-range-and-undef.ll | 3 +- 3 files changed, 53 insertions(+), 8 deletions(-) diff --git a/llvm/include/llvm/Analysis/ValueLattice.h b/llvm/include/llvm/Analysis/ValueLattice.h index a467a715fca8..225d5acb19d5 100644 --- a/llvm/include/llvm/Analysis/ValueLattice.h +++ b/llvm/include/llvm/Analysis/ValueLattice.h @@ -29,27 +29,48 @@ class ValueLatticeElement { /// producing instruction is dead. Caution: We use this as the starting /// state in our local meet rules. In this usage, it's taken to mean /// "nothing known yet". + /// Transition to any other state allowed. unknown, /// This Value is an UndefValue constant or produces undef. Undefined values /// can be merged with constants (or single element constant ranges), /// assuming all uses of the result will be replaced. + /// Transition allowed to the following states: + /// constant + /// singlecrfromundef + /// overdefined undef, - /// This Value has a specific constant value. (For constant integers, - /// constantrange is used instead. Integer typed constantexprs can appear - /// as constant.) + /// This Value has a specific constant value. The constant cannot be undef. + /// (For constant integers, constantrange is used instead. Integer typed + /// constantexprs can appear as constant.) + /// Transition allowed to the following states: + /// overdefined constant, - /// This Value is known to not have the specified value. (For constant + /// This Value is known to not have the specified value. (For constant /// integers, constantrange is used instead. As above, integer typed /// constantexprs can appear here.) + /// Transition allowed to the following states: + /// overdefined notconstant, /// The Value falls within this range. (Used only for integer typed values.) + /// Transition allowed to the following states: + /// constantrange (new range must be a superset of the existing range) + /// singlecrfromundef (range must stay a single element range) + /// overdefined constantrange, + /// This Value contains a single element constant range that was merged with + /// an Undef value. Merging it with other constant ranges results in + /// overdefined, unless they match the single element constant range. + /// Transition allowed to the following states: + /// overdefined + singlecrfromundef, + /// We can not precisely model the dynamic values this value might take. + /// No transitions are allowed after reaching overdefined. overdefined }; @@ -75,6 +96,7 @@ public: case unknown: case undef: case constant: + case singlecrfromundef: case notconstant: break; case constantrange: @@ -105,6 +127,7 @@ public: switch (Other.Tag) { case constantrange: + case singlecrfromundef: if (!isConstantRange()) new (&Range) ConstantRange(Other.Range); else @@ -155,8 +178,11 @@ public: bool isUnknown() const { return Tag == unknown; } bool isUnknownOrUndef() const { return Tag == unknown || Tag == undef; } bool isConstant() const { return Tag == constant; } + bool isSingleCRFromUndef() const { return Tag == singlecrfromundef; } bool isNotConstant() const { return Tag == notconstant; } - bool isConstantRange() const { return Tag == constantrange; } + bool isConstantRange() const { + return Tag == constantrange || Tag == singlecrfromundef; + } bool isOverdefined() const { return Tag == overdefined; } Constant *getConstant() const { @@ -251,6 +277,8 @@ public: if (getConstantRange() == NewR) return false; + assert(!isSingleCRFromUndef()); + if (NewR.isEmptySet()) return markOverdefined(); @@ -260,11 +288,11 @@ public: return true; } - assert(isUnknown() || isUndef()); + assert(isUnknown() || (isUndef() && NewR.isSingleElement())); if (NewR.isEmptySet()) return markOverdefined(); - Tag = constantrange; + Tag = isUnknown() ? constantrange : singlecrfromundef; new (&Range) ConstantRange(std::move(NewR)); return true; } @@ -322,7 +350,17 @@ public: markOverdefined(); return true; } + ConstantRange NewR = getConstantRange().unionWith(RHS.getConstantRange()); + + if (isSingleCRFromUndef() || RHS.isSingleCRFromUndef()) { + if (NewR.isSingleElement()) { + assert(getConstantRange() == NewR); + return false; + } + markOverdefined(); + return true; + } if (NewR.isFullSet()) return markOverdefined(); else if (NewR == getConstantRange()) diff --git a/llvm/lib/Analysis/ValueLattice.cpp b/llvm/lib/Analysis/ValueLattice.cpp index eaf8885cc14e..1a15605ce1e1 100644 --- a/llvm/lib/Analysis/ValueLattice.cpp +++ b/llvm/lib/Analysis/ValueLattice.cpp @@ -19,6 +19,12 @@ raw_ostream &operator<<(raw_ostream &OS, const ValueLatticeElement &Val) { if (Val.isNotConstant()) return OS << "notconstant<" << *Val.getNotConstant() << ">"; + + if (Val.isSingleCRFromUndef()) + return OS << "constantrange (from undef)<" + << Val.getConstantRange().getLower() << ", " + << Val.getConstantRange().getUpper() << ">"; + if (Val.isConstantRange()) return OS << "constantrange<" << Val.getConstantRange().getLower() << ", " << Val.getConstantRange().getUpper() << ">"; diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/merge-range-and-undef.ll b/llvm/test/Transforms/CorrelatedValuePropagation/merge-range-and-undef.ll index ffc92f5ab45c..271c52af779d 100644 --- a/llvm/test/Transforms/CorrelatedValuePropagation/merge-range-and-undef.ll +++ b/llvm/test/Transforms/CorrelatedValuePropagation/merge-range-and-undef.ll @@ -199,7 +199,8 @@ define i64 @constant_range_and_undef_3_incoming_v2(i1 %c1, i1 %c2, i64 %a) { ; CHECK-NEXT: br label [[BB4]] ; CHECK: bb4: ; CHECK-NEXT: [[P:%.*]] = phi i64 [ undef, [[BB1]] ], [ 10, [[BB2]] ], [ [[R]], [[BB3]] ] -; CHECK-NEXT: ret i64 [[P]] +; CHECK-NEXT: [[RES:%.*]] = and i64 [[P]], 255 +; CHECK-NEXT: ret i64 [[RES]] ; entry: br i1 %c1, label %bb1, label %bb2