forked from OSchip/llvm-project
Move BaseIndexOffset in DAGCombiner.cpp so it will be available for the upcoming user
llvm-svn: 289537
This commit is contained in:
parent
de82a65053
commit
01e86444a0
|
@ -4236,6 +4236,110 @@ 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)))))
|
||||
struct BaseIndexOffset {
|
||||
SDValue Base;
|
||||
SDValue Index;
|
||||
int64_t Offset;
|
||||
bool IsIndexSignExt;
|
||||
|
||||
BaseIndexOffset() : Offset(0), IsIndexSignExt(false) {}
|
||||
|
||||
BaseIndexOffset(SDValue Base, SDValue Index, int64_t Offset,
|
||||
bool IsIndexSignExt) :
|
||||
Base(Base), Index(Index), Offset(Offset), IsIndexSignExt(IsIndexSignExt) {}
|
||||
|
||||
bool equalBaseIndex(const BaseIndexOffset &Other) {
|
||||
return Other.Base == Base && Other.Index == Index &&
|
||||
Other.IsIndexSignExt == IsIndexSignExt;
|
||||
}
|
||||
|
||||
/// Parses tree in Ptr for base, index, offset addresses.
|
||||
static BaseIndexOffset match(SDValue Ptr, SelectionDAG &DAG) {
|
||||
bool IsIndexSignExt = false;
|
||||
|
||||
// Split up a folded GlobalAddress+Offset into its component parts.
|
||||
if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Ptr))
|
||||
if (GA->getOpcode() == ISD::GlobalAddress && GA->getOffset() != 0) {
|
||||
return BaseIndexOffset(DAG.getGlobalAddress(GA->getGlobal(),
|
||||
SDLoc(GA),
|
||||
GA->getValueType(0),
|
||||
/*Offset=*/0,
|
||||
/*isTargetGA=*/false,
|
||||
GA->getTargetFlags()),
|
||||
SDValue(),
|
||||
GA->getOffset(),
|
||||
IsIndexSignExt);
|
||||
}
|
||||
|
||||
// We only can pattern match BASE + INDEX + OFFSET. If Ptr is not an ADD
|
||||
// instruction, then it could be just the BASE or everything else we don't
|
||||
// know how to handle. Just use Ptr as BASE and give up.
|
||||
if (Ptr->getOpcode() != ISD::ADD)
|
||||
return BaseIndexOffset(Ptr, SDValue(), 0, IsIndexSignExt);
|
||||
|
||||
// We know that we have at least an ADD instruction. Try to pattern match
|
||||
// the simple case of BASE + OFFSET.
|
||||
if (isa<ConstantSDNode>(Ptr->getOperand(1))) {
|
||||
int64_t Offset = cast<ConstantSDNode>(Ptr->getOperand(1))->getSExtValue();
|
||||
return BaseIndexOffset(Ptr->getOperand(0), SDValue(), Offset,
|
||||
IsIndexSignExt);
|
||||
}
|
||||
|
||||
// Inside a loop the current BASE pointer is calculated using an ADD and a
|
||||
// MUL instruction. In this case Ptr is the actual BASE pointer.
|
||||
// (i64 add (i64 %array_ptr)
|
||||
// (i64 mul (i64 %induction_var)
|
||||
// (i64 %element_size)))
|
||||
if (Ptr->getOperand(1)->getOpcode() == ISD::MUL)
|
||||
return BaseIndexOffset(Ptr, SDValue(), 0, IsIndexSignExt);
|
||||
|
||||
// Look at Base + Index + Offset cases.
|
||||
SDValue Base = Ptr->getOperand(0);
|
||||
SDValue IndexOffset = Ptr->getOperand(1);
|
||||
|
||||
// Skip signextends.
|
||||
if (IndexOffset->getOpcode() == ISD::SIGN_EXTEND) {
|
||||
IndexOffset = IndexOffset->getOperand(0);
|
||||
IsIndexSignExt = true;
|
||||
}
|
||||
|
||||
// Either the case of Base + Index (no offset) or something else.
|
||||
if (IndexOffset->getOpcode() != ISD::ADD)
|
||||
return BaseIndexOffset(Base, IndexOffset, 0, IsIndexSignExt);
|
||||
|
||||
// Now we have the case of Base + Index + offset.
|
||||
SDValue Index = IndexOffset->getOperand(0);
|
||||
SDValue Offset = IndexOffset->getOperand(1);
|
||||
|
||||
if (!isa<ConstantSDNode>(Offset))
|
||||
return BaseIndexOffset(Ptr, SDValue(), 0, IsIndexSignExt);
|
||||
|
||||
// Ignore signextends.
|
||||
if (Index->getOpcode() == ISD::SIGN_EXTEND) {
|
||||
Index = Index->getOperand(0);
|
||||
IsIndexSignExt = true;
|
||||
} else IsIndexSignExt = false;
|
||||
|
||||
int64_t Off = cast<ConstantSDNode>(Offset)->getSExtValue();
|
||||
return BaseIndexOffset(Base, Index, Off, IsIndexSignExt);
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
|
||||
SDValue DAGCombiner::visitXOR(SDNode *N) {
|
||||
SDValue N0 = N->getOperand(0);
|
||||
SDValue N1 = N->getOperand(1);
|
||||
|
@ -11217,110 +11321,6 @@ SDValue DAGCombiner::TransformFPLoadStorePair(SDNode *N) {
|
|||
return SDValue();
|
||||
}
|
||||
|
||||
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)))))
|
||||
struct BaseIndexOffset {
|
||||
SDValue Base;
|
||||
SDValue Index;
|
||||
int64_t Offset;
|
||||
bool IsIndexSignExt;
|
||||
|
||||
BaseIndexOffset() : Offset(0), IsIndexSignExt(false) {}
|
||||
|
||||
BaseIndexOffset(SDValue Base, SDValue Index, int64_t Offset,
|
||||
bool IsIndexSignExt) :
|
||||
Base(Base), Index(Index), Offset(Offset), IsIndexSignExt(IsIndexSignExt) {}
|
||||
|
||||
bool equalBaseIndex(const BaseIndexOffset &Other) {
|
||||
return Other.Base == Base && Other.Index == Index &&
|
||||
Other.IsIndexSignExt == IsIndexSignExt;
|
||||
}
|
||||
|
||||
/// Parses tree in Ptr for base, index, offset addresses.
|
||||
static BaseIndexOffset match(SDValue Ptr, SelectionDAG &DAG) {
|
||||
bool IsIndexSignExt = false;
|
||||
|
||||
// Split up a folded GlobalAddress+Offset into its component parts.
|
||||
if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Ptr))
|
||||
if (GA->getOpcode() == ISD::GlobalAddress && GA->getOffset() != 0) {
|
||||
return BaseIndexOffset(DAG.getGlobalAddress(GA->getGlobal(),
|
||||
SDLoc(GA),
|
||||
GA->getValueType(0),
|
||||
/*Offset=*/0,
|
||||
/*isTargetGA=*/false,
|
||||
GA->getTargetFlags()),
|
||||
SDValue(),
|
||||
GA->getOffset(),
|
||||
IsIndexSignExt);
|
||||
}
|
||||
|
||||
// We only can pattern match BASE + INDEX + OFFSET. If Ptr is not an ADD
|
||||
// instruction, then it could be just the BASE or everything else we don't
|
||||
// know how to handle. Just use Ptr as BASE and give up.
|
||||
if (Ptr->getOpcode() != ISD::ADD)
|
||||
return BaseIndexOffset(Ptr, SDValue(), 0, IsIndexSignExt);
|
||||
|
||||
// We know that we have at least an ADD instruction. Try to pattern match
|
||||
// the simple case of BASE + OFFSET.
|
||||
if (isa<ConstantSDNode>(Ptr->getOperand(1))) {
|
||||
int64_t Offset = cast<ConstantSDNode>(Ptr->getOperand(1))->getSExtValue();
|
||||
return BaseIndexOffset(Ptr->getOperand(0), SDValue(), Offset,
|
||||
IsIndexSignExt);
|
||||
}
|
||||
|
||||
// Inside a loop the current BASE pointer is calculated using an ADD and a
|
||||
// MUL instruction. In this case Ptr is the actual BASE pointer.
|
||||
// (i64 add (i64 %array_ptr)
|
||||
// (i64 mul (i64 %induction_var)
|
||||
// (i64 %element_size)))
|
||||
if (Ptr->getOperand(1)->getOpcode() == ISD::MUL)
|
||||
return BaseIndexOffset(Ptr, SDValue(), 0, IsIndexSignExt);
|
||||
|
||||
// Look at Base + Index + Offset cases.
|
||||
SDValue Base = Ptr->getOperand(0);
|
||||
SDValue IndexOffset = Ptr->getOperand(1);
|
||||
|
||||
// Skip signextends.
|
||||
if (IndexOffset->getOpcode() == ISD::SIGN_EXTEND) {
|
||||
IndexOffset = IndexOffset->getOperand(0);
|
||||
IsIndexSignExt = true;
|
||||
}
|
||||
|
||||
// Either the case of Base + Index (no offset) or something else.
|
||||
if (IndexOffset->getOpcode() != ISD::ADD)
|
||||
return BaseIndexOffset(Base, IndexOffset, 0, IsIndexSignExt);
|
||||
|
||||
// Now we have the case of Base + Index + offset.
|
||||
SDValue Index = IndexOffset->getOperand(0);
|
||||
SDValue Offset = IndexOffset->getOperand(1);
|
||||
|
||||
if (!isa<ConstantSDNode>(Offset))
|
||||
return BaseIndexOffset(Ptr, SDValue(), 0, IsIndexSignExt);
|
||||
|
||||
// Ignore signextends.
|
||||
if (Index->getOpcode() == ISD::SIGN_EXTEND) {
|
||||
Index = Index->getOperand(0);
|
||||
IsIndexSignExt = true;
|
||||
} else IsIndexSignExt = false;
|
||||
|
||||
int64_t Off = cast<ConstantSDNode>(Offset)->getSExtValue();
|
||||
return BaseIndexOffset(Base, Index, Off, IsIndexSignExt);
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
|
||||
// This is a helper function for visitMUL to check the profitability
|
||||
// of folding (mul (add x, c1), c2) -> (add (mul x, c2), c1*c2).
|
||||
// MulNode is the original multiply, AddNode is (add x, c1),
|
||||
|
|
Loading…
Reference in New Issue