[PATCH] D24964: TargetLowering: Add SimplifyDemandedBits() helper to TargetLoweringOpt
Justin Bogner via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 30 14:22:09 PDT 2016
Tom Stellard <thomas.stellard at amd.com> writes:
> tstellarAMD created this revision.
> tstellarAMD added reviewers: bogner, arsenm.
> tstellarAMD added a subscriber: llvm-commits.
> Herald added a subscriber: wdng.
>
> The main purpose of this new helper is to enable simplifying operations that
> have multiple uses. SimplifyDemandedBits does not handle multiple uses
> currently, and this new function makes it possible to optimize:
>
> and v1, v0, 0xffffff
> mul24 v2, v1, v1 ; Multiply ignoring high 8-bits.
>
> To:
>
> mul24 v2, v0, v0
>
> Where before this would not be optimized, because v1 has multiple uses.
This seems basically reasonable. LGTM after fixing a couple of nitpicks.
> https://reviews.llvm.org/D24964
>
> Files:
> include/llvm/Target/TargetLowering.h
> lib/CodeGen/SelectionDAG/TargetLowering.cpp
>
> Index: lib/CodeGen/SelectionDAG/TargetLowering.cpp
> ===================================================================
> --- lib/CodeGen/SelectionDAG/TargetLowering.cpp
> +++ lib/CodeGen/SelectionDAG/TargetLowering.cpp
> @@ -418,6 +418,58 @@
> return false;
> }
>
> +bool
> +TargetLowering::TargetLoweringOpt::SimplifyDemandedBits(SDNode *User,
> + unsigned OpIdx,
> + const APInt &Demanded,
> + DAGCombinerInfo &DCI) {
> + const TargetLowering &TLI = DAG.getTargetLoweringInfo();
> + SDValue Op = User->getOperand(OpIdx);
> + APInt KnownZero, KnownOne;
> +
> + if (!TLI.SimplifyDemandedBits(Op, Demanded, KnownZero, KnownOne,
> + *this, 0, true))
Best to comment the arguments that aren't obvious from context, ie,
if (!TLI.SimplifyDemandedBits(Op, Demanded, KnownZero, KnownOne,
*this, /*Depth=*/0, /*AssumeSingleUse=*/true))
> + return false;
> +
> +
> + // Old will not always be the same as Op. For example:
> + //
> + // Demanded = 0xffffff
> + // Op = i64 truncate (i32 and x, 0xffffff)
> + // In this case simplify demand bits will want to replace the 'and' node
> + // with the value 'x', which will give us:
> + // Old = i32 and x, 0xffffff
> + // New = x
> + if (Old.hasOneUse()) {
> + // For the one use case, we just commit the change.
> + DCI.CommitTargetLoweringOpt(*this);
> + return true;
> + }
> +
> + // If Old has more than one use then it must be Op, because the
> + // AssumeSingleUse flag is not propogated to recursive calls of
> + // SimplifyDemanded bits, so the only node with multiple use that
> + // it will attempt to combine will be opt.
> + assert(Old == Op);
Please add a brief message to the assert.
> +
> + SmallVector <SDValue, 4> NewOps;
> + for (unsigned i = 0, e = User->getNumOperands(); i != e; ++i) {
LLVM style says these should be called I and E.
> + if (i == OpIdx) {
> + NewOps.push_back(New);
> + continue;
> + }
> + NewOps.push_back(User->getOperand(i));
> + }
> + DAG.UpdateNodeOperands(User, NewOps);
> + // Op has less users now, so we may be able to perform additional combines
> + // with it.
> + DCI.AddToWorklist(Op.getNode());
> + // User's operands have been updated, so we may be able to do new combines
> + // with it.
> + DCI.AddToWorklist(User);
> + return true;
> +}
> +
> /// Look at Op. At this point, we know that only the DemandedMask bits of the
> /// result of Op are ever used downstream. If we can use this information to
> /// simplify Op, create a new simplified DAG node and return true, returning the
> @@ -430,7 +482,8 @@
> APInt &KnownZero,
> APInt &KnownOne,
> TargetLoweringOpt &TLO,
> - unsigned Depth) const {
> + unsigned Depth,
> + bool AssumeSingleUse) const {
> unsigned BitWidth = DemandedMask.getBitWidth();
> assert(Op.getScalarValueSizeInBits() == BitWidth &&
> "Mask size mismatches value type size!");
> @@ -442,7 +495,7 @@
> KnownZero = KnownOne = APInt(BitWidth, 0);
>
> // Other users may use these bits.
> - if (!Op.getNode()->hasOneUse()) {
> + if (!Op.getNode()->hasOneUse() && !AssumeSingleUse) {
> if (Depth != 0) {
> // If not at the root, Just compute the KnownZero/KnownOne bits to
> // simplify things downstream.
> Index: include/llvm/Target/TargetLowering.h
> ===================================================================
> --- include/llvm/Target/TargetLowering.h
> +++ include/llvm/Target/TargetLowering.h
> @@ -2180,6 +2180,8 @@
> void operator=(const TargetLowering&) = delete;
>
> public:
> + struct DAGCombinerInfo;
> +
> /// NOTE: The TargetMachine owns TLOF.
> explicit TargetLowering(const TargetMachine &TM);
>
> @@ -2292,6 +2294,16 @@
> /// generalized for targets with other types of implicit widening casts.
> bool ShrinkDemandedOp(SDValue Op, unsigned BitWidth, const APInt &Demanded,
> const SDLoc &dl);
> +
> + /// Helper for SimplifyDemandedBits that can simplify an operation with
> + /// multiple uses. This function uses TLI.SimplifyDemandedBits to
> + /// simplify Operand \p OpIdx of \p User and then updated \p User with
> + /// the simplified version. No other uses of \p OpIdx are updated.
> + /// If \p User is the only user of \p OpIdx, this function behaves exactly
> + /// like TLI.SimplifyDemandedBits except that it also updates the DAG by
> + /// calling DCI.CommitTargetLoweringOpt.
> + bool SimplifyDemandedBits(SDNode *User, unsigned OpIdx,
> + const APInt &Demanded, DAGCombinerInfo &DCI);
> };
>
> /// Look at Op. At this point, we know that only the DemandedMask bits of the
> @@ -2301,9 +2313,17 @@
> /// expression and return a mask of KnownOne and KnownZero bits for the
> /// expression (used to simplify the caller). The KnownZero/One bits may only
> /// be accurate for those bits in the DemandedMask.
> + /// \p AssumeSingleUse When this paramater is true, this function will
> + /// attempt to simplify \p Op even if there are multiple uses.
> + /// Callers are responsible for correctly updating the DAG based on the
> + /// results of this function, because simply replacing replacing TLO.Old
> + /// with TLO.New will be incorrect when this paramater is true and TLO.Old
> + /// has multiple uses.
> bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedMask,
> APInt &KnownZero, APInt &KnownOne,
> - TargetLoweringOpt &TLO, unsigned Depth = 0) const;
> + TargetLoweringOpt &TLO,
> + unsigned Depth = 0,
> + bool AssumeSingleUse = false) const;
>
> /// Determine which of the bits specified in Mask are known to be either zero
> /// or one and return them in the KnownZero/KnownOne bitsets.
More information about the llvm-commits
mailing list