forked from OSchip/llvm-project
The patch fixes (base, index, offset) match.
Summary: Instead of matching: (a + i) + 1 -> (a + i, undef, 1) Now it matches: (a + i) + 1 -> (a, i, 1) Reviewers: rengolin Differential Revision: http://reviews.llvm.org/D26367 From: Evgeny Stupachenko <evstupac@gmail.com> llvm-svn: 291012
This commit is contained in:
parent
f51b0d5908
commit
c88697dc16
|
@ -4277,7 +4277,8 @@ struct BaseIndexOffset {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses tree in Ptr for base, index, offset addresses.
|
/// Parses tree in Ptr for base, index, offset addresses.
|
||||||
static BaseIndexOffset match(SDValue Ptr, SelectionDAG &DAG) {
|
static BaseIndexOffset match(SDValue Ptr, SelectionDAG &DAG,
|
||||||
|
int64_t PartialOffset = 0) {
|
||||||
bool IsIndexSignExt = false;
|
bool IsIndexSignExt = false;
|
||||||
|
|
||||||
// Split up a folded GlobalAddress+Offset into its component parts.
|
// Split up a folded GlobalAddress+Offset into its component parts.
|
||||||
|
@ -4286,7 +4287,7 @@ struct BaseIndexOffset {
|
||||||
return BaseIndexOffset(DAG.getGlobalAddress(GA->getGlobal(),
|
return BaseIndexOffset(DAG.getGlobalAddress(GA->getGlobal(),
|
||||||
SDLoc(GA),
|
SDLoc(GA),
|
||||||
GA->getValueType(0),
|
GA->getValueType(0),
|
||||||
/*Offset=*/0,
|
/*Offset=*/PartialOffset,
|
||||||
/*isTargetGA=*/false,
|
/*isTargetGA=*/false,
|
||||||
GA->getTargetFlags()),
|
GA->getTargetFlags()),
|
||||||
SDValue(),
|
SDValue(),
|
||||||
|
@ -4298,14 +4299,13 @@ struct BaseIndexOffset {
|
||||||
// instruction, then it could be just the BASE or everything else we don't
|
// 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.
|
// know how to handle. Just use Ptr as BASE and give up.
|
||||||
if (Ptr->getOpcode() != ISD::ADD)
|
if (Ptr->getOpcode() != ISD::ADD)
|
||||||
return BaseIndexOffset(Ptr, SDValue(), 0, IsIndexSignExt);
|
return BaseIndexOffset(Ptr, SDValue(), PartialOffset, IsIndexSignExt);
|
||||||
|
|
||||||
// We know that we have at least an ADD instruction. Try to pattern match
|
// We know that we have at least an ADD instruction. Try to pattern match
|
||||||
// the simple case of BASE + OFFSET.
|
// the simple case of BASE + OFFSET.
|
||||||
if (isa<ConstantSDNode>(Ptr->getOperand(1))) {
|
if (isa<ConstantSDNode>(Ptr->getOperand(1))) {
|
||||||
int64_t Offset = cast<ConstantSDNode>(Ptr->getOperand(1))->getSExtValue();
|
int64_t Offset = cast<ConstantSDNode>(Ptr->getOperand(1))->getSExtValue();
|
||||||
return BaseIndexOffset(Ptr->getOperand(0), SDValue(), Offset,
|
return match(Ptr->getOperand(0), DAG, Offset + PartialOffset);
|
||||||
IsIndexSignExt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inside a loop the current BASE pointer is calculated using an ADD and a
|
// Inside a loop the current BASE pointer is calculated using an ADD and a
|
||||||
|
@ -4314,7 +4314,7 @@ struct BaseIndexOffset {
|
||||||
// (i64 mul (i64 %induction_var)
|
// (i64 mul (i64 %induction_var)
|
||||||
// (i64 %element_size)))
|
// (i64 %element_size)))
|
||||||
if (Ptr->getOperand(1)->getOpcode() == ISD::MUL)
|
if (Ptr->getOperand(1)->getOpcode() == ISD::MUL)
|
||||||
return BaseIndexOffset(Ptr, SDValue(), 0, IsIndexSignExt);
|
return BaseIndexOffset(Ptr, SDValue(), PartialOffset, IsIndexSignExt);
|
||||||
|
|
||||||
// Look at Base + Index + Offset cases.
|
// Look at Base + Index + Offset cases.
|
||||||
SDValue Base = Ptr->getOperand(0);
|
SDValue Base = Ptr->getOperand(0);
|
||||||
|
@ -4328,14 +4328,14 @@ struct BaseIndexOffset {
|
||||||
|
|
||||||
// Either the case of Base + Index (no offset) or something else.
|
// Either the case of Base + Index (no offset) or something else.
|
||||||
if (IndexOffset->getOpcode() != ISD::ADD)
|
if (IndexOffset->getOpcode() != ISD::ADD)
|
||||||
return BaseIndexOffset(Base, IndexOffset, 0, IsIndexSignExt);
|
return BaseIndexOffset(Base, IndexOffset, PartialOffset, IsIndexSignExt);
|
||||||
|
|
||||||
// Now we have the case of Base + Index + offset.
|
// Now we have the case of Base + Index + offset.
|
||||||
SDValue Index = IndexOffset->getOperand(0);
|
SDValue Index = IndexOffset->getOperand(0);
|
||||||
SDValue Offset = IndexOffset->getOperand(1);
|
SDValue Offset = IndexOffset->getOperand(1);
|
||||||
|
|
||||||
if (!isa<ConstantSDNode>(Offset))
|
if (!isa<ConstantSDNode>(Offset))
|
||||||
return BaseIndexOffset(Ptr, SDValue(), 0, IsIndexSignExt);
|
return BaseIndexOffset(Ptr, SDValue(), PartialOffset, IsIndexSignExt);
|
||||||
|
|
||||||
// Ignore signextends.
|
// Ignore signextends.
|
||||||
if (Index->getOpcode() == ISD::SIGN_EXTEND) {
|
if (Index->getOpcode() == ISD::SIGN_EXTEND) {
|
||||||
|
@ -4344,7 +4344,7 @@ struct BaseIndexOffset {
|
||||||
} else IsIndexSignExt = false;
|
} else IsIndexSignExt = false;
|
||||||
|
|
||||||
int64_t Off = cast<ConstantSDNode>(Offset)->getSExtValue();
|
int64_t Off = cast<ConstantSDNode>(Offset)->getSExtValue();
|
||||||
return BaseIndexOffset(Base, Index, Off, IsIndexSignExt);
|
return BaseIndexOffset(Base, Index, Off + PartialOffset, IsIndexSignExt);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -370,6 +370,40 @@ define void @MergeLoadStoreBaseIndexOffset(i64* %a, i8* %b, i8* %c, i32 %n) {
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; Make sure that we merge the consecutive load/store sequence below and use a
|
||||||
|
; word (16 bit) instead of a byte copy for complicated address calculation.
|
||||||
|
; .
|
||||||
|
; CHECK-LABEL: MergeLoadStoreBaseIndexOffsetComplicated:
|
||||||
|
; BWON: movzwl (%{{.*}},%{{.*}}), %e[[REG:[a-z]+]]
|
||||||
|
; BWOFF: movw (%{{.*}},%{{.*}}), %[[REG:[a-z]+]]
|
||||||
|
; CHECK: movw %[[REG]], (%{{.*}})
|
||||||
|
define void @MergeLoadStoreBaseIndexOffsetComplicated(i8* %a, i8* %b, i8* %c, i64 %n) {
|
||||||
|
br label %1
|
||||||
|
|
||||||
|
; <label>:1
|
||||||
|
%.09 = phi i64 [ 0, %0 ], [ %13, %1 ]
|
||||||
|
%.08 = phi i8* [ %b, %0 ], [ %12, %1 ]
|
||||||
|
%2 = load i8, i8* %.08, align 1
|
||||||
|
%3 = sext i8 %2 to i64
|
||||||
|
%4 = getelementptr inbounds i8, i8* %c, i64 %3
|
||||||
|
%5 = load i8, i8* %4, align 1
|
||||||
|
%6 = add nsw i64 %3, 1
|
||||||
|
%7 = getelementptr inbounds i8, i8* %c, i64 %6
|
||||||
|
%8 = load i8, i8* %7, align 1
|
||||||
|
%9 = getelementptr inbounds i8, i8* %a, i64 %.09
|
||||||
|
store i8 %5, i8* %9, align 1
|
||||||
|
%10 = or i64 %.09, 1
|
||||||
|
%11 = getelementptr inbounds i8, i8* %a, i64 %10
|
||||||
|
store i8 %8, i8* %11, align 1
|
||||||
|
%12 = getelementptr inbounds i8, i8* %.08, i64 1
|
||||||
|
%13 = add nuw nsw i64 %.09, 2
|
||||||
|
%14 = icmp slt i64 %13, %n
|
||||||
|
br i1 %14, label %1, label %15
|
||||||
|
|
||||||
|
; <label>:15
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
; Make sure that we merge the consecutive load/store sequence below and use a
|
; Make sure that we merge the consecutive load/store sequence below and use a
|
||||||
; word (16 bit) instead of a byte copy even if there are intermediate sign
|
; word (16 bit) instead of a byte copy even if there are intermediate sign
|
||||||
; extensions.
|
; extensions.
|
||||||
|
|
Loading…
Reference in New Issue