diff options
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 18 | ||||
-rw-r--r-- | llvm/test/CodeGen/X86/MergeConsecutiveStores.ll | 34 |
2 files changed, 43 insertions, 9 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index b4b41c3d001..4632484055d 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -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 diff --git a/llvm/test/CodeGen/X86/MergeConsecutiveStores.ll b/llvm/test/CodeGen/X86/MergeConsecutiveStores.ll index b50253bf2b0..4d7cb765d7b 100644 --- a/llvm/test/CodeGen/X86/MergeConsecutiveStores.ll +++ b/llvm/test/CodeGen/X86/MergeConsecutiveStores.ll @@ -371,6 +371,40 @@ define void @MergeLoadStoreBaseIndexOffset(i64* %a, i8* %b, i8* %c, i32 %n) { } ; 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. ; CHECK-LABEL: MergeLoadStoreBaseIndexOffsetSext: |