[PATCH] D89692: [SCEV] SCEVPtrToIntExpr simplifications

Roman Lebedev via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sun Oct 25 14:11:12 PDT 2020


lebedev.ri added a comment.

@efriedma does this look about right?

Speaking for myself, this isn't quite what i want to have in the end,
it should be closer to: (just so i don't loose the code)

  const SCEV *ScalarEvolution::getPtrToIntExpr(const SCEV *Op, Type *Ty,
                                               unsigned Depth) {
    assert(Ty->isIntegerTy() && "Target type must be an integer type!");
    assert(Depth <= 1 && "getPtrToIntExpr() should self-recurse at most once.");
  
    // We could be called with an integer-typed operands during SCEV rewrites.
    // Since the operand is an integer already, just perform zext/trunc/self cast.
    if (!Op->getType()->isPointerTy())
      return getTruncateOrZeroExtend(Op, Ty);
  
    // What would be an ID for such a SCEV cast expression?
    FoldingSetNodeID ID;
    ID.AddInteger(scPtrToInt);
    ID.AddPointer(Op);
  
    void *IP = nullptr;
  
    // Is there already an expression for such a cast?
    if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP))
      return getTruncateOrZeroExtend(S, Ty);
  
    // If not, is this expression something we can't reduce any further?
    if (isa<SCEVUnknown>(Op)) {
      // Create an explicit cast node.
      // We can reuse the existing insert position since if we get here,
      // we won't have made any changes which would invalidate it.
      Type *IntPtrTy = getDataLayout().getIntPtrType(Op->getType());
      assert(getDataLayout().getTypeSizeInBits(getEffectiveSCEVType(
                 Op->getType())) == getDataLayout().getTypeSizeInBits(IntPtrTy) &&
             "We can only model ptrtoint if SCEV's effective (integer) type is "
             "sufficiently wide to represent all possible pointer values.");
      SCEV *S = new (SCEVAllocator)
          SCEVPtrToIntExpr(ID.Intern(SCEVAllocator), Op, IntPtrTy);
      UniqueSCEVs.InsertNode(S, IP);
      addToLoopUseLists(S);
      return getTruncateOrZeroExtend(S, Ty);
    }
  
    assert(Depth == 0 &&
           "getPtrToIntExpr() should not self-recurse for non-SCEVUnknown's.");
  
    // Otherwise, we've got some expression that is more complex than just a
    // single SCEVUnknown. But we don't want to have a SCEVPtrToIntExpr of an
    // arbitrary expression, we want to have SCEVPtrToIntExpr of an SCEVUnknown
    // only, and the expressions must otherwise be integer-typed.
    // So sink the cast down to the SCEVUnknown's.
  
    /// The SCEVPtrToIntSinkingRewriter takes a scalar evolution expression,
    /// which computes a pointer-typed value, and rewrites the whole expression
    /// tree so that *all* the computations are done on integers, and the only
    /// pointer-typed operands in the expression are SCEVUnknown.
    class SCEVPtrToIntSinkingRewriter
        : public SCEVRewriteVisitor<SCEVPtrToIntSinkingRewriter> {
      using Base = SCEVRewriteVisitor<SCEVPtrToIntSinkingRewriter>;
  
    public:
      SCEVPtrToIntSinkingRewriter(ScalarEvolution &SE) : SCEVRewriteVisitor(SE) {}
  
      static const SCEV *rewrite(const SCEV *Scev, ScalarEvolution &SE) {
        SCEVPtrToIntSinkingRewriter Rewriter(SE);
        return Rewriter.visit(Scev);
      }
  
      const SCEV *visit(const SCEV *S) {
        Type *STy = S->getType();
        // If the expression is not pointer-typed, just keep it as-is.
        if (!STy->isPointerTy())
          return S;
        // Else, recursively sink the cast down into it.
        return Base::visit(S);
      }
  
      const SCEV *visitUnknown(const SCEVUnknown *Expr) {
        Type *ExprPtrTy = Expr->getType();
        assert(ExprPtrTy->isPointerTy() &&
               "Should only reach pointer-typed SCEVUnknown's.");
        Type *ExprIntPtrTy = SE.getDataLayout().getIntPtrType(ExprPtrTy);
        return SE.getPtrToIntExpr(Expr, ExprIntPtrTy, /*Depth=*/1);
      }
    };
  
    // And actually perform the cast sinking.
    const SCEV *IntOp = SCEVPtrToIntSinkingRewriter::rewrite(Op, *this);
    assert(IntOp->getType()->isIntegerTy() &&
           "We must have succeeded in sinking the cast, "
           "and ending up with an integer-typed expression!");
    return getTruncateOrZeroExtend(IntOp, Ty);
  }

... but that requires SCEVRewriteVisitor changes so it doesn't loose no-wrap flags on add/mul,
(unlike AddRec, where it already preserves them),
but i would imagine the approach to that refactoring to be non-obvious,
so i would prefer not to block this on that, and do that as a follow-up..


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D89692/new/

https://reviews.llvm.org/D89692



More information about the llvm-commits mailing list