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:
Evgeny Stupachenko 2017-01-04 21:43:39 +00:00
parent f51b0d5908
commit c88697dc16
2 changed files with 43 additions and 9 deletions

View File

@ -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

View File

@ -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.