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.
|
||||
static BaseIndexOffset match(SDValue Ptr, SelectionDAG &DAG) {
|
||||
static BaseIndexOffset match(SDValue Ptr, SelectionDAG &DAG,
|
||||
int64_t PartialOffset = 0) {
|
||||
bool IsIndexSignExt = false;
|
||||
|
||||
// Split up a folded GlobalAddress+Offset into its component parts.
|
||||
|
@ -4286,7 +4287,7 @@ struct BaseIndexOffset {
|
|||
return BaseIndexOffset(DAG.getGlobalAddress(GA->getGlobal(),
|
||||
SDLoc(GA),
|
||||
GA->getValueType(0),
|
||||
/*Offset=*/0,
|
||||
/*Offset=*/PartialOffset,
|
||||
/*isTargetGA=*/false,
|
||||
GA->getTargetFlags()),
|
||||
SDValue(),
|
||||
|
@ -4298,14 +4299,13 @@ struct BaseIndexOffset {
|
|||
// 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);
|
||||
return BaseIndexOffset(Ptr, SDValue(), PartialOffset, 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);
|
||||
return match(Ptr->getOperand(0), DAG, Offset + PartialOffset);
|
||||
}
|
||||
|
||||
// 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 %element_size)))
|
||||
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.
|
||||
SDValue Base = Ptr->getOperand(0);
|
||||
|
@ -4328,14 +4328,14 @@ struct BaseIndexOffset {
|
|||
|
||||
// Either the case of Base + Index (no offset) or something else.
|
||||
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.
|
||||
SDValue Index = IndexOffset->getOperand(0);
|
||||
SDValue Offset = IndexOffset->getOperand(1);
|
||||
|
||||
if (!isa<ConstantSDNode>(Offset))
|
||||
return BaseIndexOffset(Ptr, SDValue(), 0, IsIndexSignExt);
|
||||
return BaseIndexOffset(Ptr, SDValue(), PartialOffset, IsIndexSignExt);
|
||||
|
||||
// Ignore signextends.
|
||||
if (Index->getOpcode() == ISD::SIGN_EXTEND) {
|
||||
|
@ -4344,7 +4344,7 @@ struct BaseIndexOffset {
|
|||
} else IsIndexSignExt = false;
|
||||
|
||||
int64_t Off = cast<ConstantSDNode>(Offset)->getSExtValue();
|
||||
return BaseIndexOffset(Base, Index, Off, IsIndexSignExt);
|
||||
return BaseIndexOffset(Base, Index, Off + PartialOffset, IsIndexSignExt);
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
|
|
|
@ -370,6 +370,40 @@ define void @MergeLoadStoreBaseIndexOffset(i64* %a, i8* %b, i8* %c, i32 %n) {
|
|||
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
|
||||
; word (16 bit) instead of a byte copy even if there are intermediate sign
|
||||
; extensions.
|
||||
|
|
Loading…
Reference in New Issue