xref: /llvm-project/llvm/test/Transforms/LoopIdiom/memcpy-intrinsic-different-types.ll (revision 055fb7795aa219a3d274d280ec9129784f169f56)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes=loop-idiom < %s -S | FileCheck %s
3
4; #include <vector>
5;
6; class SDValue {
7;     int A;
8;     int B;
9;     unsigned C;
10; };
11;
12; class SDUse {
13;     SDValue Val;
14;     SDUse **Prev = nullptr;
15;     SDUse *Next = nullptr;
16;
17; public:
18;     operator const SDValue&() const { return Val; }
19; };
20;
21; void foo(SDUse *S, int N) {
22;     // Should not hoist memcpy because source and destination are of different types
23;     std::vector<SDValue> Ops(S, S + N);
24; }
25
26; ModuleID = 'different_types.cpp'
27source_filename = "different_types.cpp"
28target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
29target triple = "x86_64-unknown-linux-gnu"
30
31%class.SDUse = type { %class.SDValue, ptr, ptr }
32%class.SDValue = type { i32, i32, i32 }
33
34declare dso_local i32 @__gxx_personality_v0(...)
35
36; Function Attrs: uwtable mustprogress
37define linkonce_odr dso_local ptr @_ZNSt20__uninitialized_copyILb0EE13__uninit_copyIP5SDUseP7SDValueEET0_T_S7_S6_(ptr %__first, ptr %__last, ptr %__result) local_unnamed_addr #0  align 2 personality ptr @__gxx_personality_v0 {
38; CHECK-LABEL: @_ZNSt20__uninitialized_copyILb0EE13__uninit_copyIP5SDUseP7SDValueEET0_T_S7_S6_(
39; CHECK-NEXT:  entry:
40; CHECK-NEXT:    [[CMP_NOT15:%.*]] = icmp eq ptr [[__FIRST:%.*]], [[__LAST:%.*]]
41; CHECK-NEXT:    br i1 [[CMP_NOT15]], label [[FOR_END:%.*]], label [[FOR_INC_PREHEADER:%.*]]
42; CHECK:       for.inc.preheader:
43; CHECK-NEXT:    br label [[FOR_INC:%.*]]
44; CHECK:       for.inc:
45; CHECK-NEXT:    [[__CUR_017:%.*]] = phi ptr [ [[INCDEC_PTR1:%.*]], [[FOR_INC]] ], [ [[__RESULT:%.*]], [[FOR_INC_PREHEADER]] ]
46; CHECK-NEXT:    [[__FIRST_ADDR_016:%.*]] = phi ptr [ [[INCDEC_PTR:%.*]], [[FOR_INC]] ], [ [[__FIRST]], [[FOR_INC_PREHEADER]] ]
47; CHECK-NEXT:    tail call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 4 dereferenceable(12) [[__CUR_017]], ptr noundef nonnull align 8 dereferenceable(12) [[__FIRST_ADDR_016]], i64 12, i1 false)
48; CHECK-NEXT:    [[INCDEC_PTR]] = getelementptr inbounds [[CLASS_SDUSE:%.*]], ptr [[__FIRST_ADDR_016]], i64 1
49; CHECK-NEXT:    [[INCDEC_PTR1]] = getelementptr inbounds [[CLASS_SDVALUE:%.*]], ptr [[__CUR_017]], i64 1
50; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq ptr [[INCDEC_PTR]], [[__LAST]]
51; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_INC]]
52; CHECK:       for.end.loopexit:
53; CHECK-NEXT:    [[INCDEC_PTR1_LCSSA:%.*]] = phi ptr [ [[INCDEC_PTR1]], [[FOR_INC]] ]
54; CHECK-NEXT:    br label [[FOR_END]]
55; CHECK:       for.end:
56; CHECK-NEXT:    [[__CUR_0_LCSSA:%.*]] = phi ptr [ [[__RESULT]], [[ENTRY:%.*]] ], [ [[INCDEC_PTR1_LCSSA]], [[FOR_END_LOOPEXIT]] ]
57; CHECK-NEXT:    ret ptr [[__CUR_0_LCSSA]]
58;
59entry:
60  %cmp.not15 = icmp eq ptr %__first, %__last
61  br i1 %cmp.not15, label %for.end, label %for.inc.preheader
62
63for.inc.preheader:                                ; preds = %entry
64  br label %for.inc
65
66for.inc:                                          ; preds = %for.inc.preheader, %for.inc
67  %__cur.017 = phi ptr [ %incdec.ptr1, %for.inc ], [ %__result, %for.inc.preheader ]
68  %__first.addr.016 = phi ptr [ %incdec.ptr, %for.inc ], [ %__first, %for.inc.preheader ]
69  tail call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 4 dereferenceable(12) %__cur.017, ptr noundef nonnull align 8 dereferenceable(12) %__first.addr.016, i64 12, i1 false)
70  %incdec.ptr = getelementptr inbounds %class.SDUse, ptr %__first.addr.016, i64 1
71  %incdec.ptr1 = getelementptr inbounds %class.SDValue, ptr %__cur.017, i64 1
72  %cmp.not = icmp eq ptr %incdec.ptr, %__last
73  br i1 %cmp.not, label %for.end.loopexit, label %for.inc
74
75for.end.loopexit:                                 ; preds = %for.inc
76  %incdec.ptr1.lcssa = phi ptr [ %incdec.ptr1, %for.inc ]
77  br label %for.end
78
79for.end:                                          ; preds = %for.end.loopexit, %entry
80  %__cur.0.lcssa = phi ptr [ %__result, %entry ], [ %incdec.ptr1.lcssa, %for.end.loopexit ]
81  ret ptr %__cur.0.lcssa
82}
83
84; Function Attrs: argmemonly nofree nosync nounwind willreturn
85declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg) #1
86