From: Nirav Dave Date: Wed, 21 Jun 2017 15:40:43 +0000 (+0000) Subject: [DAG] Move BaseIndexOffset into separate Libarary. NFC. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=34e56f0bf7465484547a73fe38de1aacfc8d97eb;p=llvm [DAG] Move BaseIndexOffset into separate Libarary. NFC. Move BaseIndexOffset analysis out of DAGCombiner for use in other files. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@305921 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/CodeGen/SelectionDAGAddressAnalysis.h b/include/llvm/CodeGen/SelectionDAGAddressAnalysis.h new file mode 100644 index 00000000000..d82ab7d647e --- /dev/null +++ b/include/llvm/CodeGen/SelectionDAGAddressAnalysis.h @@ -0,0 +1,64 @@ +//===-- llvm/CodeGen/SelectionDAGAddressAnalysis.h ------- DAG Address Analysis +//---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// + +#ifndef LLVM_CODEGEN_SELECTIONDAGADDRESSANALYSIS_H +#define LLVM_CODEGEN_SELECTIONDAGADDRESSANALYSIS_H + +#include "llvm/CodeGen/ISDOpcodes.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/SelectionDAGNodes.h" + +namespace llvm { +/// Helper struct to parse and store a memory address as base + index + offset. +/// We ignore sign extensions when it is safe to do so. +/// The following two expressions are not equivalent. To differentiate we need +/// to store whether there was a sign extension involved in the index +/// computation. +/// (load (i64 add (i64 copyfromreg %c) +/// (i64 signextend (add (i8 load %index) +/// (i8 1)))) +/// vs +/// +/// (load (i64 add (i64 copyfromreg %c) +/// (i64 signextend (i32 add (i32 signextend (i8 load %index)) +/// (i32 1))))) +class BaseIndexOffset { +private: + SDValue Base; + SDValue Index; + int64_t Offset; + bool IsIndexSignExt; + +public: + BaseIndexOffset() : Offset(0), IsIndexSignExt(false) {} + + BaseIndexOffset(SDValue Base, SDValue Index, int64_t Offset, + bool IsIndexSignExt) + : Base(Base), Index(Index), Offset(Offset), + IsIndexSignExt(IsIndexSignExt) {} + + SDValue getBase() { return Base; } + SDValue getIndex() { return Index; } + + bool equalBaseIndex(BaseIndexOffset &Other, const SelectionDAG &DAG) { + int64_t Off; + return equalBaseIndex(Other, DAG, Off); + } + + bool equalBaseIndex(BaseIndexOffset &Other, const SelectionDAG &DAG, + int64_t &Off); + + /// Parses tree in Ptr for base, index, offset addresses. + static BaseIndexOffset match(SDValue Ptr); +}; +} // namespace llvm + +#endif diff --git a/lib/CodeGen/SelectionDAG/CMakeLists.txt b/lib/CodeGen/SelectionDAG/CMakeLists.txt index a668ddb7389..ae9c5adb039 100644 --- a/lib/CodeGen/SelectionDAG/CMakeLists.txt +++ b/lib/CodeGen/SelectionDAG/CMakeLists.txt @@ -17,6 +17,7 @@ add_llvm_library(LLVMSelectionDAG ScheduleDAGVLIW.cpp SelectionDAGBuilder.cpp SelectionDAG.cpp + SelectionDAGAddressAnalysis.cpp SelectionDAGDumper.cpp SelectionDAGISel.cpp SelectionDAGPrinter.cpp diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 0e092927974..14a722a59e8 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -25,6 +25,7 @@ #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/SelectionDAGAddressAnalysis.h" #include "llvm/CodeGen/SelectionDAGTargetInfo.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" @@ -4694,120 +4695,6 @@ SDNode *DAGCombiner::MatchRotate(SDValue LHS, SDValue RHS, const SDLoc &DL) { return nullptr; } -namespace { -/// Helper struct to parse and store a memory address as base + index + offset. -/// We ignore sign extensions when it is safe to do so. -/// The following two expressions are not equivalent. To differentiate we need -/// to store whether there was a sign extension involved in the index -/// computation. -/// (load (i64 add (i64 copyfromreg %c) -/// (i64 signextend (add (i8 load %index) -/// (i8 1)))) -/// vs -/// -/// (load (i64 add (i64 copyfromreg %c) -/// (i64 signextend (i32 add (i32 signextend (i8 load %index)) -/// (i32 1))))) -class BaseIndexOffset { -private: - SDValue Base; - SDValue Index; - int64_t Offset; - bool IsIndexSignExt; - -public: - BaseIndexOffset() : Offset(0), IsIndexSignExt(false) {} - - BaseIndexOffset(SDValue Base, SDValue Index, int64_t Offset, - bool IsIndexSignExt) : - Base(Base), Index(Index), Offset(Offset), IsIndexSignExt(IsIndexSignExt) {} - - SDValue getBase() { return Base; } - SDValue getIndex() { return Index; } - - bool equalBaseIndex(BaseIndexOffset &Other, const SelectionDAG &DAG) { - int64_t Off; - return equalBaseIndex(Other, DAG, Off); - } - - bool equalBaseIndex(BaseIndexOffset &Other, const SelectionDAG &DAG, - int64_t &Off) { - // Obvious equivalent - Off = Other.Offset - Offset; - if (Other.Base == Base && Other.Index == Index && - Other.IsIndexSignExt == IsIndexSignExt) - return true; - - // Match GlobalAddresses - if (Index == Other.Index) - if (GlobalAddressSDNode *A = dyn_cast(Base)) - if (GlobalAddressSDNode *B = dyn_cast(Other.Base)) - if (A->getGlobal() == B->getGlobal()) { - Off += B->getOffset() - A->getOffset(); - return true; - } - - // TODO: we should be able to add FrameIndex analysis improvements here. - - return false; - } - - /// Parses tree in Ptr for base, index, offset addresses. - static BaseIndexOffset match(SDValue Ptr) { - // (((B + I*M) + c)) + c ... - SDValue Base = Ptr; - SDValue Index = SDValue(); - int64_t Offset = 0; - bool IsIndexSignExt = false; - - //Consume constant adds - while (Base->getOpcode() == ISD::ADD && - isa(Base->getOperand(1))) { - int64_t POffset = cast(Base->getOperand(1))->getSExtValue(); - Offset += POffset; - Base = Base->getOperand(0); - } - - if (Base->getOpcode() == ISD::ADD) { - // TODO: The following code appears to be needless as it just - // bails on some Ptrs early, reducing the cases where we - // find equivalence. We should be able to remove this. - // Inside a loop the current BASE pointer is calculated using an ADD and a - // MUL instruction. In this case Base is the actual BASE pointer. - // (i64 add (i64 %array_ptr) - // (i64 mul (i64 %induction_var) - // (i64 %element_size))) - if (Base->getOperand(1)->getOpcode() == ISD::MUL) - return BaseIndexOffset(Base, Index, Offset, IsIndexSignExt); - - // Look at Base + Index + Offset cases. - Index = Base->getOperand(1); - SDValue PotentialBase = Base->getOperand(0); - - // Skip signextends. - if (Index->getOpcode() == ISD::SIGN_EXTEND) { - Index = Index->getOperand(0); - IsIndexSignExt = true; - } - - // Check if Index Offset pattern - if (Index->getOpcode() != ISD::ADD || - !isa(Index->getOperand(1))) - return BaseIndexOffset(PotentialBase, Index, Offset, IsIndexSignExt); - - Offset += cast(Index->getOperand(1))->getSExtValue(); - Index = Index->getOperand(0); - if (Index->getOpcode() == ISD::SIGN_EXTEND) { - Index = Index->getOperand(0); - IsIndexSignExt = true; - } else IsIndexSignExt = false; - Base = PotentialBase; - } - return BaseIndexOffset(Base, Index, Offset, IsIndexSignExt); - } -}; -} // namespace - namespace { /// Represents known origin of an individual byte in load combine pattern. The /// value of the byte is either constant zero or comes from memory. diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGAddressAnalysis.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGAddressAnalysis.cpp new file mode 100644 index 00000000000..d2e0dbbf88e --- /dev/null +++ b/lib/CodeGen/SelectionDAG/SelectionDAGAddressAnalysis.cpp @@ -0,0 +1,95 @@ +//===-- llvm/CodeGen/SelectionDAGAddressAnalysis.cpp ------- DAG Address +//Analysis ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// + +#include "llvm/CodeGen/SelectionDAGAddressAnalysis.h" +#include "llvm/CodeGen/ISDOpcodes.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/SelectionDAGNodes.h" + +namespace llvm { + +bool BaseIndexOffset::equalBaseIndex(BaseIndexOffset &Other, + const SelectionDAG &DAG, int64_t &Off) { + // Obvious equivalent + Off = Other.Offset - Offset; + if (Other.Base == Base && Other.Index == Index && + Other.IsIndexSignExt == IsIndexSignExt) + return true; + + // Match GlobalAddresses + if (Index == Other.Index) + if (GlobalAddressSDNode *A = dyn_cast(Base)) + if (GlobalAddressSDNode *B = dyn_cast(Other.Base)) + if (A->getGlobal() == B->getGlobal()) { + Off += B->getOffset() - A->getOffset(); + return true; + } + + // TODO: we should be able to add FrameIndex analysis improvements here. + + return false; +} + +/// Parses tree in Ptr for base, index, offset addresses. +BaseIndexOffset BaseIndexOffset::match(SDValue Ptr) { + // (((B + I*M) + c)) + c ... + SDValue Base = Ptr; + SDValue Index = SDValue(); + int64_t Offset = 0; + bool IsIndexSignExt = false; + + // Consume constant adds + while (Base->getOpcode() == ISD::ADD && + isa(Base->getOperand(1))) { + int64_t POffset = cast(Base->getOperand(1))->getSExtValue(); + Offset += POffset; + Base = Base->getOperand(0); + } + + if (Base->getOpcode() == ISD::ADD) { + // TODO: The following code appears to be needless as it just + // bails on some Ptrs early, reducing the cases where we + // find equivalence. We should be able to remove this. + // Inside a loop the current BASE pointer is calculated using an ADD and a + // MUL instruction. In this case Base is the actual BASE pointer. + // (i64 add (i64 %array_ptr) + // (i64 mul (i64 %induction_var) + // (i64 %element_size))) + if (Base->getOperand(1)->getOpcode() == ISD::MUL) + return BaseIndexOffset(Base, Index, Offset, IsIndexSignExt); + + // Look at Base + Index + Offset cases. + Index = Base->getOperand(1); + SDValue PotentialBase = Base->getOperand(0); + + // Skip signextends. + if (Index->getOpcode() == ISD::SIGN_EXTEND) { + Index = Index->getOperand(0); + IsIndexSignExt = true; + } + + // Check if Index Offset pattern + if (Index->getOpcode() != ISD::ADD || + !isa(Index->getOperand(1))) + return BaseIndexOffset(PotentialBase, Index, Offset, IsIndexSignExt); + + Offset += cast(Index->getOperand(1))->getSExtValue(); + Index = Index->getOperand(0); + if (Index->getOpcode() == ISD::SIGN_EXTEND) { + Index = Index->getOperand(0); + IsIndexSignExt = true; + } else + IsIndexSignExt = false; + Base = PotentialBase; + } + return BaseIndexOffset(Base, Index, Offset, IsIndexSignExt); +} +} // end namespace llvm