forked from OSchip/llvm-project
[DAG] Move BaseIndexOffset into separate Libarary. NFC.
Move BaseIndexOffset analysis out of DAGCombiner for use in other files. llvm-svn: 305921
This commit is contained in:
parent
d1f8b8162b
commit
c1b6aa77bb
|
@ -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
|
|
@ -17,6 +17,7 @@ add_llvm_library(LLVMSelectionDAG
|
|||
ScheduleDAGVLIW.cpp
|
||||
SelectionDAGBuilder.cpp
|
||||
SelectionDAG.cpp
|
||||
SelectionDAGAddressAnalysis.cpp
|
||||
SelectionDAGDumper.cpp
|
||||
SelectionDAGISel.cpp
|
||||
SelectionDAGPrinter.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<GlobalAddressSDNode>(Base))
|
||||
if (GlobalAddressSDNode *B = dyn_cast<GlobalAddressSDNode>(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<ConstantSDNode>(Base->getOperand(1))) {
|
||||
int64_t POffset = cast<ConstantSDNode>(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<ConstantSDNode>(Index->getOperand(1)))
|
||||
return BaseIndexOffset(PotentialBase, Index, Offset, IsIndexSignExt);
|
||||
|
||||
Offset += cast<ConstantSDNode>(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.
|
||||
|
|
|
@ -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<GlobalAddressSDNode>(Base))
|
||||
if (GlobalAddressSDNode *B = dyn_cast<GlobalAddressSDNode>(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<ConstantSDNode>(Base->getOperand(1))) {
|
||||
int64_t POffset = cast<ConstantSDNode>(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<ConstantSDNode>(Index->getOperand(1)))
|
||||
return BaseIndexOffset(PotentialBase, Index, Offset, IsIndexSignExt);
|
||||
|
||||
Offset += cast<ConstantSDNode>(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
|
Loading…
Reference in New Issue