brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.1 KiB · 44a4721 Raw
288 lines · plain
1; RUN: opt -passes='print<access-info>' -disable-output  < %s 2>&1 | FileCheck %s2 3target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"4target triple = "aarch64"5 6; 3 reads and 3 writes should need 12 memchecks7; CHECK: function 'testf':8; CHECK: Memory dependences are safe with run-time checks9 10; Memory dependencies have labels starting from 0, so in11; order to verify that we have n checks, we look for12; (n-1): and not n:.13 14; CHECK: Run-time memory checks:15; CHECK-NEXT: Check 0:16; CHECK: Check 11:17; CHECK-NOT: Check 12:18 19define void @testf(ptr %a,20               ptr %b,21               ptr %c,22               ptr %d,23               ptr %e,24               ptr %f) {25entry:26  br label %for.body27 28for.body:                                         ; preds = %for.body, %entry29  %ind = phi i64 [ 0, %entry ], [ %add, %for.body ]30 31  %add = add nuw nsw i64 %ind, 132 33  %arrayidxA = getelementptr inbounds i16, ptr %a, i64 %ind34  %loadA = load i16, ptr %arrayidxA, align 235 36  %arrayidxB = getelementptr inbounds i16, ptr %b, i64 %ind37  %loadB = load i16, ptr %arrayidxB, align 238 39  %arrayidxC = getelementptr inbounds i16, ptr %c, i64 %ind40  %loadC = load i16, ptr %arrayidxC, align 241 42  %mul = mul i16 %loadB, %loadA43  %mul1 = mul i16 %mul, %loadC44 45  %arrayidxD = getelementptr inbounds i16, ptr %d, i64 %ind46  store i16 %mul1, ptr %arrayidxD, align 247 48  %arrayidxE = getelementptr inbounds i16, ptr %e, i64 %ind49  store i16 %mul, ptr %arrayidxE, align 250 51  %arrayidxF = getelementptr inbounds i16, ptr %f, i64 %ind52  store i16 %mul1, ptr %arrayidxF, align 253 54  %exitcond = icmp eq i64 %add, 2055  br i1 %exitcond, label %for.end, label %for.body56 57for.end:                                          ; preds = %for.body58  ret void59}60 61; The following (testg and testh) check that we can group62; memory checks of accesses which differ by a constant value.63; Both tests are based on the following C code:64;65; void testh(short *a, short *b, short *c) {66;   unsigned long ind = 0;67;   for (unsigned long ind = 0; ind < 20; ++ind) {68;     c[2 * ind] = a[ind] * a[ind + 1];69;     c[2 * ind + 1] = a[ind] * a[ind] * b[ind];70;   }71; }72;73; It is sufficient to check the intervals74; [a, a + 21], [b, b + 20] against [c, c + 41].75 76; 3 reads and 2 writes - two of the reads can be merged,77; and the writes can be merged as well. This gives us a78; total of 2 memory checks.79 80; CHECK: function 'testg':81 82; CHECK: Run-time memory checks:83; CHECK-NEXT:   Check 0:84; CHECK-NEXT:     Comparing group GRP0:85; CHECK-NEXT:       %arrayidxC1 = getelementptr inbounds i16, ptr %c, i64 %store_ind_inc86; CHECK-NEXT:       %arrayidxC = getelementptr inbounds i16, ptr %c, i64 %store_ind87; CHECK-NEXT:     Against group GRP1:88; CHECK-NEXT:       %arrayidxA1 = getelementptr inbounds i16, ptr %a, i64 %add89; CHECK-NEXT:       %arrayidxA = getelementptr inbounds i16, ptr %a, i64 %ind90; CHECK-NEXT:   Check 1:91; CHECK-NEXT:     Comparing group GRP0:92; CHECK-NEXT:       %arrayidxC1 = getelementptr inbounds i16, ptr %c, i64 %store_ind_inc93; CHECK-NEXT:       %arrayidxC = getelementptr inbounds i16, ptr %c, i64 %store_ind94; CHECK-NEXT:     Against group GRP2:95; CHECK-NEXT:       %arrayidxB = getelementptr inbounds i16, ptr %b, i64 %ind96; CHECK-NEXT:   Grouped accesses:97; CHECK-NEXT:    Group GRP0:98; CHECK-NEXT:       (Low: %c High: (80 + %c))99; CHECK-NEXT:         Member: {(2 + %c)<nuw>,+,4}100; CHECK-NEXT:         Member: {%c,+,4}101; CHECK-NEXT:     Group GRP1:102; CHECK-NEXT:       (Low: %a High: (42 + %a))103; CHECK-NEXT:         Member: {(2 + %a)<nuw>,+,2}104; CHECK-NEXT:         Member: {%a,+,2}105; CHECK-NEXT:     Group GRP2:106; CHECK-NEXT:       (Low: %b High: (40 + %b))107; CHECK-NEXT:         Member: {%b,+,2}108 109define void @testg(ptr %a,110               ptr %b,111               ptr %c) {112entry:113  br label %for.body114 115for.body:                                         ; preds = %for.body, %entry116  %ind = phi i64 [ 0, %entry ], [ %add, %for.body ]117  %store_ind = phi i64 [ 0, %entry ], [ %store_ind_next, %for.body ]118 119  %add = add nuw nsw i64 %ind, 1120  %store_ind_inc = add nuw nsw i64 %store_ind, 1121  %store_ind_next = add nuw nsw i64 %store_ind_inc, 1122 123  %arrayidxA = getelementptr inbounds i16, ptr %a, i64 %ind124  %loadA = load i16, ptr %arrayidxA, align 2125 126  %arrayidxA1 = getelementptr inbounds i16, ptr %a, i64 %add127  %loadA1 = load i16, ptr %arrayidxA1, align 2128 129  %arrayidxB = getelementptr inbounds i16, ptr %b, i64 %ind130  %loadB = load i16, ptr %arrayidxB, align 2131 132  %mul = mul i16 %loadA, %loadA1133  %mul1 = mul i16 %mul, %loadB134 135  %arrayidxC = getelementptr inbounds i16, ptr %c, i64 %store_ind136  store i16 %mul1, ptr %arrayidxC, align 2137 138  %arrayidxC1 = getelementptr inbounds i16, ptr %c, i64 %store_ind_inc139  store i16 %mul, ptr %arrayidxC1, align 2140 141  %exitcond = icmp eq i64 %add, 20142  br i1 %exitcond, label %for.end, label %for.body143 144for.end:                                          ; preds = %for.body145  ret void146}147 148; 3 reads and 2 writes - the writes can be merged into a single149; group, but the GEPs used for the reads are not marked as inbounds.150; We can still merge them because we are using a unit stride for151; accesses, so we cannot overflow the GEPs.152 153; CHECK: function 'testh':154; CHECK: Run-time memory checks:155; CHECK-NEXT:   Check 0:156; CHECK-NEXT:     Comparing group GRP0:157; CHECK-NEXT:         %arrayidxC1 = getelementptr inbounds i16, ptr %c, i64 %store_ind_inc158; CHECK-NEXT:         %arrayidxC = getelementptr inbounds i16, ptr %c, i64 %store_ind159; CHECK-NEXT:     Against group GRP1:160; CHECK-NEXT:         %arrayidxA1 = getelementptr i16, ptr %a, i64 %add161; CHECK-NEXT:         %arrayidxA = getelementptr i16, ptr %a, i64 %ind162; CHECK-NEXT:   Check 1:163; CHECK-NEXT:     Comparing group GRP0:164; CHECK-NEXT:         %arrayidxC1 = getelementptr inbounds i16, ptr %c, i64 %store_ind_inc165; CHECK-NEXT:         %arrayidxC = getelementptr inbounds i16, ptr %c, i64 %store_ind166; CHECK-NEXT:     Against group GRP2:167; CHECK-NEXT:         %arrayidxB = getelementptr i16, ptr %b, i64 %ind168; CHECK-NEXT:   Grouped accesses:169; CHECK-NEXT:     Group GRP0:170; CHECK-NEXT:       (Low: %c High: (80 + %c))171; CHECK-NEXT:         Member: {(2 + %c)<nuw>,+,4}172; CHECK-NEXT:         Member: {%c,+,4}173; CHECK-NEXT:     Group GRP1:174; CHECK-NEXT:       (Low: %a High: (42 + %a))175; CHECK-NEXT:         Member: {(2 + %a),+,2}176; CHECK-NEXT:         Member: {%a,+,2}177; CHECK-NEXT:     Group GRP2:178; CHECK-NEXT:       (Low: %b High: (40 + %b))179; CHECK-NEXT:         Member: {%b,+,2}180 181define void @testh(ptr %a,182               ptr %b,183               ptr %c) {184entry:185  br label %for.body186 187for.body:                                         ; preds = %for.body, %entry188  %ind = phi i64 [ 0, %entry ], [ %add, %for.body ]189  %store_ind = phi i64 [ 0, %entry ], [ %store_ind_next, %for.body ]190 191  %add = add nuw nsw i64 %ind, 1192  %store_ind_inc = add nuw nsw i64 %store_ind, 1193  %store_ind_next = add nuw nsw i64 %store_ind_inc, 1194 195  %arrayidxA = getelementptr i16, ptr %a, i64 %ind196  %loadA = load i16, ptr %arrayidxA, align 2197 198  %arrayidxA1 = getelementptr i16, ptr %a, i64 %add199  %loadA1 = load i16, ptr %arrayidxA1, align 2200 201  %arrayidxB = getelementptr i16, ptr %b, i64 %ind202  %loadB = load i16, ptr %arrayidxB, align 2203 204  %mul = mul i16 %loadA, %loadA1205  %mul1 = mul i16 %mul, %loadB206 207  %arrayidxC = getelementptr inbounds i16, ptr %c, i64 %store_ind208  store i16 %mul1, ptr %arrayidxC, align 2209 210  %arrayidxC1 = getelementptr inbounds i16, ptr %c, i64 %store_ind_inc211  store i16 %mul, ptr %arrayidxC1, align 2212 213  %exitcond = icmp eq i64 %add, 20214  br i1 %exitcond, label %for.end, label %for.body215 216for.end:                                          ; preds = %for.body217  ret void218}219 220; Don't merge pointers if we need to perform a check against a pointer221; to the same underlying object (doing so would emit a check that could be222; falsely invalidated) For example, in the following loop:223;224; for (i = 0; i < 5000; ++i)225;   a[i + offset] = a[i] + a[i + 10000]226;227; we should not merge the intervals associated with the reads (0,5000) and228; (10000, 15000) into (0, 15000) as this will pottentially fail the check229; against the interval associated with the write.230;231; We cannot have this check unless ShouldRetryWithRuntimeCheck is set,232; and therefore the grouping algorithm would create a separate group for233; each pointer.234 235; CHECK: function 'testi':236; CHECK: Run-time memory checks:237; CHECK-NEXT:   Check 0:238; CHECK-NEXT:     Comparing group GRP0:239; CHECK-NEXT:       %storeidx = getelementptr inbounds i16, ptr %a, i64 %store_ind240; CHECK-NEXT:     Against group GRP1:241; CHECK-NEXT:       %arrayidxA1 = getelementptr i16, ptr %a, i64 %ind242; CHECK-NEXT:   Check 1:243; CHECK-NEXT:     Comparing group GRP0:244; CHECK-NEXT:       %storeidx = getelementptr inbounds i16, ptr %a, i64 %store_ind245; CHECK-NEXT:     Against group GRP2:246; CHECK-NEXT:       %arrayidxA2 = getelementptr i16, ptr %a, i64 %ind2247; CHECK-NEXT:   Grouped accesses:248; CHECK-NEXT:     Group GRP0:249; CHECK-NEXT:       (Low: ((2 * %offset) + %a) High: (10000 + (2 * %offset) + %a))250; CHECK-NEXT:         Member: {((2 * %offset) + %a),+,2}<%for.body>251; CHECK-NEXT:     Group GRP1:252; CHECK-NEXT:       (Low: %a High: (10000 + %a))253; CHECK-NEXT:         Member: {%a,+,2}<nw><%for.body>254; CHECK-NEXT:     Group GRP2:255; CHECK-NEXT:       (Low: (20000 + %a) High: (30000 + %a))256; CHECK-NEXT:         Member: {(20000 + %a),+,2}<nw><%for.body>257 258define void @testi(ptr %a,259                   i64 %offset) {260entry:261  br label %for.body262 263for.body:                                         ; preds = %for.body, %entry264  %ind = phi i64 [ 0, %entry ], [ %add, %for.body ]265  %store_ind = phi i64 [ %offset, %entry ], [ %store_ind_inc, %for.body ]266 267  %add = add nuw nsw i64 %ind, 1268  %store_ind_inc = add nuw nsw i64 %store_ind, 1269 270  %arrayidxA1 = getelementptr i16, ptr %a, i64 %ind271  %ind2 = add nuw nsw i64 %ind, 10000272  %arrayidxA2 = getelementptr i16, ptr %a, i64 %ind2273 274  %loadA1 = load i16, ptr %arrayidxA1, align 2275  %loadA2 = load i16, ptr %arrayidxA2, align 2276 277  %addres = add i16 %loadA1, %loadA2278 279  %storeidx = getelementptr inbounds i16, ptr %a, i64 %store_ind280  store i16 %addres, ptr %storeidx, align 2281 282  %exitcond = icmp eq i64 %add, 5000283  br i1 %exitcond, label %for.end, label %for.body284 285for.end:                                          ; preds = %for.body286  ret void287}288