diff options
author | Johannes Doerfert <johannes@jdoerfert.de> | 2020-02-09 20:14:35 -0600 |
---|---|---|
committer | Johannes Doerfert <johannes@jdoerfert.de> | 2020-02-10 00:55:10 -0600 |
commit | 8155439331ac8f85be54adbd053c100567927d7c (patch) | |
tree | 408cfb9df8622b6545fbe3dd6b27f0b7f7003f30 /llvm/lib | |
parent | 63adbb9a0ed9a40fc47c72502754d88d04ede1e0 (diff) | |
download | llvm-8155439331ac8f85be54adbd053c100567927d7c.zip llvm-8155439331ac8f85be54adbd053c100567927d7c.tar.gz llvm-8155439331ac8f85be54adbd053c100567927d7c.tar.bz2 |
[Attributor] Allow PHI nodes in AAValueConstantRangeFloating
Traversing PHI nodes is natural with the genericValueTraversal but also
a bit tricky. The problem is similar to the ones we have seen in AAAlign
and AADereferenceable, namely that we continue to increase the range in
each iteration. We use a pessimistic approach here to stop the
iterations. Nevertheless, optimistic information can now be propagated
through a PHI node.
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Transforms/IPO/Attributor.cpp | 58 |
1 files changed, 43 insertions, 15 deletions
diff --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp index da5260b..91eb561 100644 --- a/llvm/lib/Transforms/IPO/Attributor.cpp +++ b/llvm/lib/Transforms/IPO/Attributor.cpp @@ -6187,9 +6187,9 @@ struct AAValueConstantRangeFloating : AAValueConstantRangeImpl { if (CI->getOperand(0)->getType()->isIntegerTy()) return; - // We can work with select instruction as we traverse their operands + // We can work with PHI and select instruction as we traverse their operands // during update. - if (isa<SelectInst>(V)) + if (isa<SelectInst>(V) || isa<PHINode>(V)) return; // Otherwise we give up. @@ -6199,17 +6199,21 @@ struct AAValueConstantRangeFloating : AAValueConstantRangeImpl { << getAssociatedValue() << "\n"); } - bool calculateBinaryOperator(Attributor &A, BinaryOperator *BinOp, - IntegerRangeState &T, Instruction *CtxI) { + bool calculateBinaryOperator( + Attributor &A, BinaryOperator *BinOp, IntegerRangeState &T, + Instruction *CtxI, + SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) { Value *LHS = BinOp->getOperand(0); Value *RHS = BinOp->getOperand(1); auto &LHSAA = A.getAAFor<AAValueConstantRange>(*this, IRPosition::value(*LHS)); + QuerriedAAs.push_back(&LHSAA); auto LHSAARange = LHSAA.getAssumedConstantRange(A, CtxI); auto &RHSAA = A.getAAFor<AAValueConstantRange>(*this, IRPosition::value(*RHS)); + QuerriedAAs.push_back(&RHSAA); auto RHSAARange = RHSAA.getAssumedConstantRange(A, CtxI); auto AssumedRange = LHSAARange.binaryOp(BinOp->getOpcode(), RHSAARange); @@ -6221,8 +6225,9 @@ struct AAValueConstantRangeFloating : AAValueConstantRangeImpl { return T.isValidState(); } - bool calculateCastInst(Attributor &A, CastInst *CastI, IntegerRangeState &T, - Instruction *CtxI) { + bool calculateCastInst( + Attributor &A, CastInst *CastI, IntegerRangeState &T, Instruction *CtxI, + SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) { assert(CastI->getNumOperands() == 1 && "Expected cast to be unary!"); // TODO: Allow non integers as well. Value &OpV = *CastI->getOperand(0); @@ -6230,20 +6235,25 @@ struct AAValueConstantRangeFloating : AAValueConstantRangeImpl { auto &OpAA = A.getAAFor<AAValueConstantRange>(*this, IRPosition::value(OpV)); + QuerriedAAs.push_back(&OpAA); T.unionAssumed( OpAA.getAssumed().castOp(CastI->getOpcode(), getState().getBitWidth())); return T.isValidState(); } - bool calculateCmpInst(Attributor &A, CmpInst *CmpI, IntegerRangeState &T, - Instruction *CtxI) { + bool + calculateCmpInst(Attributor &A, CmpInst *CmpI, IntegerRangeState &T, + Instruction *CtxI, + SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) { Value *LHS = CmpI->getOperand(0); Value *RHS = CmpI->getOperand(1); auto &LHSAA = A.getAAFor<AAValueConstantRange>(*this, IRPosition::value(*LHS)); + QuerriedAAs.push_back(&LHSAA); auto &RHSAA = A.getAAFor<AAValueConstantRange>(*this, IRPosition::value(*RHS)); + QuerriedAAs.push_back(&RHSAA); auto LHSAARange = LHSAA.getAssumedConstantRange(A, CtxI); auto RHSAARange = RHSAA.getAssumedConstantRange(A, CtxI); @@ -6301,19 +6311,37 @@ struct AAValueConstantRangeFloating : AAValueConstantRangeImpl { return T.isValidState(); } - if (auto *BinOp = dyn_cast<BinaryOperator>(I)) - return calculateBinaryOperator(A, BinOp, T, CtxI); - else if (auto *CmpI = dyn_cast<CmpInst>(I)) - return calculateCmpInst(A, CmpI, T, CtxI); - else if (auto *CastI = dyn_cast<CastInst>(I)) - return calculateCastInst(A, CastI, T, CtxI); - else { + SmallVector<const AAValueConstantRange *, 4> QuerriedAAs; + if (auto *BinOp = dyn_cast<BinaryOperator>(I)) { + if (!calculateBinaryOperator(A, BinOp, T, CtxI, QuerriedAAs)) + return false; + } else if (auto *CmpI = dyn_cast<CmpInst>(I)) { + if (!calculateCmpInst(A, CmpI, T, CtxI, QuerriedAAs)) + return false; + } else if (auto *CastI = dyn_cast<CastInst>(I)) { + if (!calculateCastInst(A, CastI, T, CtxI, QuerriedAAs)) + return false; + } else { // Give up with other instructions. // TODO: Add other instructions T.indicatePessimisticFixpoint(); return false; } + + // Catch circular reasoning in a pessimistic way for now. + // TODO: Check how the range evolves and if we stripped anything, see also + // AADereferenceable or AAAlign for similar situations. + for (const AAValueConstantRange *QueriedAA : QuerriedAAs) { + if (QueriedAA != this) + continue; + // If we are in a stady state we do not need to worry. + if (T.getAssumed() == getState().getAssumed()) + continue; + T.indicatePessimisticFixpoint(); + } + + return T.isValidState(); }; IntegerRangeState T(getBitWidth()); |