brintos

brintos / llvm-project-archived public Read only

0
0
Text · 19.7 KiB · a32c53a Raw
531 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 32; RUN: llc -mtriple=aarch64-linux-gnu < %s | FileCheck %s3 4; One dimensional loop with load that can be hoisted outside of loop5;   for (int i = 0; i < N; ++i)6;     if (!memcmp(a[i], b, 4))7;       sum += 1;8;9define i64 @one_dimensional(ptr %a, ptr %b, i64 %N) {10; CHECK-LABEL: one_dimensional:11; CHECK:       // %bb.0: // %entry12; CHECK-NEXT:    ldr w9, [x1]13; CHECK-NEXT:    mov x8, xzr14; CHECK-NEXT:  .LBB0_1: // %for.body15; CHECK-NEXT:    // =>This Inner Loop Header: Depth=116; CHECK-NEXT:    ldr x10, [x0], #817; CHECK-NEXT:    ldr w10, [x10]18; CHECK-NEXT:    cmp w10, w919; CHECK-NEXT:    cinc x8, x8, eq20; CHECK-NEXT:    subs x2, x2, #121; CHECK-NEXT:    b.ne .LBB0_122; CHECK-NEXT:  // %bb.2: // %for.exit23; CHECK-NEXT:    mov x0, x824; CHECK-NEXT:    ret25entry:26  br label %for.body27 28for.body:                                         ; preds = %entry, %for.body29  %i.06 = phi i64 [ %inc, %for.body ], [ 0, %entry ]30  %sum.05 = phi i64 [ %spec.select, %for.body ], [ 0, %entry ]31  %arrayidx = getelementptr inbounds ptr, ptr %a, i64 %i.0632  %0 = load ptr, ptr %arrayidx, align 833  %bcmp = tail call i32 @bcmp(ptr %0, ptr %b, i64 4)34  %tobool = icmp eq i32 %bcmp, 035  %add = zext i1 %tobool to i6436  %spec.select = add i64 %sum.05, %add37  %inc = add nuw i64 %i.06, 138  %exitcond = icmp eq i64 %inc, %N39  br i1 %exitcond, label %for.exit, label %for.body40 41for.exit:                                 ; preds = %for.body42  ret i64 %spec.select43}44 45; Same but loop is two dimensional. Load is hosted outside of both loops46;   for (int i = 0; i < N; ++i)47;     for (int j = 0; j < M; ++j)48;       if (!memcmp(a[i][j], b, 4))49;         sum += 1;50;51define i64 @two_dimensional(ptr %a, ptr %b, i64 %N, i64 %M) {52; CHECK-LABEL: two_dimensional:53; CHECK:       // %bb.0: // %entry54; CHECK-NEXT:    ldr w10, [x1]55; CHECK-NEXT:    mov x9, xzr56; CHECK-NEXT:    mov x8, xzr57; CHECK-NEXT:  .LBB1_1: // %for.cond1.preheader58; CHECK-NEXT:    // =>This Loop Header: Depth=159; CHECK-NEXT:    // Child Loop BB1_2 Depth 260; CHECK-NEXT:    ldr x11, [x0, x9, lsl #3]61; CHECK-NEXT:    mov x12, x362; CHECK-NEXT:  .LBB1_2: // %for.body463; CHECK-NEXT:    // Parent Loop BB1_1 Depth=164; CHECK-NEXT:    // => This Inner Loop Header: Depth=265; CHECK-NEXT:    ldr x13, [x11], #866; CHECK-NEXT:    ldr w13, [x13]67; CHECK-NEXT:    cmp w13, w1068; CHECK-NEXT:    cinc x8, x8, eq69; CHECK-NEXT:    subs x12, x12, #170; CHECK-NEXT:    b.ne .LBB1_271; CHECK-NEXT:  // %bb.3: // %for.cond1.for.exit3_crit_edge72; CHECK-NEXT:    // in Loop: Header=BB1_1 Depth=173; CHECK-NEXT:    add x9, x9, #174; CHECK-NEXT:    cmp x9, x275; CHECK-NEXT:    b.ne .LBB1_176; CHECK-NEXT:  // %bb.4: // %for.exit77; CHECK-NEXT:    mov x0, x878; CHECK-NEXT:    ret79entry:80  br label %for.cond1.preheader81 82for.cond1.preheader:                           ; preds = %entry, %for.cond1.for.exit3_crit_edge83  %i.019 = phi i64 [ %inc7, %for.cond1.for.exit3_crit_edge ], [ 0, %entry ]84  %sum.018 = phi i64 [ %spec.select, %for.cond1.for.exit3_crit_edge ], [ 0, %entry ]85  %arrayidx = getelementptr inbounds ptr, ptr %a, i64 %i.01986  %0 = load ptr, ptr %arrayidx, align 887  br label %for.body488 89for.body4:                                     ; preds = %for.cond1.preheader, %for.body490  %j.016 = phi i64 [ 0, %for.cond1.preheader ], [ %inc, %for.body4 ]91  %sum.115 = phi i64 [ %sum.018, %for.cond1.preheader ], [ %spec.select, %for.body4 ]92  %arrayidx5 = getelementptr inbounds ptr, ptr %0, i64 %j.01693  %1 = load ptr, ptr %arrayidx5, align 894  %bcmp = tail call i32 @bcmp(ptr %1, ptr %b, i64 4)95  %tobool = icmp eq i32 %bcmp, 096  %add = zext i1 %tobool to i6497  %spec.select = add i64 %sum.115, %add98  %inc = add nuw i64 %j.016, 199  %exitcond = icmp eq i64 %inc, %M100  br i1 %exitcond, label %for.cond1.for.exit3_crit_edge, label %for.body4101 102for.cond1.for.exit3_crit_edge:         ; preds = %for.body4103  %inc7 = add nuw i64 %i.019, 1104  %exitcond22 = icmp eq i64 %inc7, %N105  br i1 %exitcond22, label %for.exit, label %for.cond1.preheader106 107for.exit:                                 ; preds = %for.cond1.for.exit3_crit_edge108  ret i64 %spec.select109}110 111; Same but loop is three dimensional. Load is hosted outside of all three loops112;   for (int i = 0; i < N; ++i)113;     for (int j = 0; j < M; ++j)114;       for (int k = 0; k < K; ++k)115;         if (!memcmp(a[i][j][k], b, 4))116;           sum += 1;117;118define i64 @three_dimensional(ptr %a, ptr %b, i64 %N, i64 %M, i64 %K) {119; CHECK-LABEL: three_dimensional:120; CHECK:       // %bb.0: // %entry121; CHECK-NEXT:    ldr w10, [x1]122; CHECK-NEXT:    mov x9, xzr123; CHECK-NEXT:    mov x8, xzr124; CHECK-NEXT:  .LBB2_1: // %for.cond1.preheader125; CHECK-NEXT:    // =>This Loop Header: Depth=1126; CHECK-NEXT:    // Child Loop BB2_2 Depth 2127; CHECK-NEXT:    // Child Loop BB2_3 Depth 3128; CHECK-NEXT:    ldr x11, [x0, x9, lsl #3]129; CHECK-NEXT:    mov x12, xzr130; CHECK-NEXT:  .LBB2_2: // %for.cond5.preheader131; CHECK-NEXT:    // Parent Loop BB2_1 Depth=1132; CHECK-NEXT:    // => This Loop Header: Depth=2133; CHECK-NEXT:    // Child Loop BB2_3 Depth 3134; CHECK-NEXT:    ldr x13, [x11, x12, lsl #3]135; CHECK-NEXT:    mov x14, x4136; CHECK-NEXT:  .LBB2_3: // %for.body8137; CHECK-NEXT:    // Parent Loop BB2_1 Depth=1138; CHECK-NEXT:    // Parent Loop BB2_2 Depth=2139; CHECK-NEXT:    // => This Inner Loop Header: Depth=3140; CHECK-NEXT:    ldr x15, [x13], #8141; CHECK-NEXT:    ldr w15, [x15]142; CHECK-NEXT:    cmp w15, w10143; CHECK-NEXT:    cinc x8, x8, eq144; CHECK-NEXT:    subs x14, x14, #1145; CHECK-NEXT:    b.ne .LBB2_3146; CHECK-NEXT:  // %bb.4: // %for.cond5.for.cond147; CHECK-NEXT:    // in Loop: Header=BB2_2 Depth=2148; CHECK-NEXT:    add x12, x12, #1149; CHECK-NEXT:    cmp x12, x3150; CHECK-NEXT:    b.ne .LBB2_2151; CHECK-NEXT:  // %bb.5: // %for.cond1.for.cond152; CHECK-NEXT:    // in Loop: Header=BB2_1 Depth=1153; CHECK-NEXT:    add x9, x9, #1154; CHECK-NEXT:    cmp x9, x2155; CHECK-NEXT:    b.ne .LBB2_1156; CHECK-NEXT:  // %bb.6: // %for.exit157; CHECK-NEXT:    mov x0, x8158; CHECK-NEXT:    ret159entry:160  br label %for.cond1.preheader161 162for.cond1.preheader:                        ; preds = %entry, %for.cond1.for.cond163  %i.033 = phi i64 [ %inc15, %for.cond1.for.cond ], [ 0, %entry ]164  %sum.032 = phi i64 [ %spec.select, %for.cond1.for.cond ], [ 0, %entry ]165  %arrayidx = getelementptr inbounds ptr, ptr %a, i64 %i.033166  %0 = load ptr, ptr %arrayidx, align 8167  br label %for.cond5.preheader168 169for.cond5.preheader:                     ; preds = %for.cond5.for.cond, %for.cond1.preheader170  %j.029 = phi i64 [ 0, %for.cond1.preheader ], [ %inc12, %for.cond5.for.cond ]171  %sum.128 = phi i64 [ %sum.032, %for.cond1.preheader ], [ %spec.select, %for.cond5.for.cond ]172  %arrayidx9 = getelementptr inbounds ptr, ptr %0, i64 %j.029173  %1 = load ptr, ptr %arrayidx9, align 8174  br label %for.body8175 176for.body8:                               ; preds = %for.body8, %for.cond5.preheader177  %k.026 = phi i64 [ 0, %for.cond5.preheader ], [ %inc, %for.body8 ]178  %sum.225 = phi i64 [ %sum.128, %for.cond5.preheader ], [ %spec.select, %for.body8 ]179  %arrayidx10 = getelementptr inbounds ptr, ptr %1, i64 %k.026180  %2 = load ptr, ptr %arrayidx10, align 8181  %bcmp = tail call i32 @bcmp(ptr %2, ptr %b, i64 4)182  %tobool = icmp eq i32 %bcmp, 0183  %add = zext i1 %tobool to i64184  %spec.select = add i64 %sum.225, %add185  %inc = add nuw i64 %k.026, 1186  %exitcond = icmp eq i64 %inc, %K187  br i1 %exitcond, label %for.cond5.for.cond, label %for.body8188 189for.cond5.for.cond:   ; preds = %for.body8190  %inc12 = add nuw i64 %j.029, 1191  %exitcond44 = icmp eq i64 %inc12, %M192  br i1 %exitcond44, label %for.cond1.for.cond, label %for.cond5.preheader193 194for.cond1.for.cond: ; preds = %for.cond5.for.cond195  %inc15 = add nuw i64 %i.033, 1196  %exitcond45 = icmp eq i64 %inc15, %N197  br i1 %exitcond45, label %for.exit, label %for.cond1.preheader198 199for.exit:                                 ; preds = %for.cond1.for.cond200  ret i64 %spec.select201}202 203; Three dimensional loop but `b` is invariant only relatively to the inner loop.204; Make sure that load is hoisted only outside of first loop205;   for (int i = 0; i < N; ++i)206;     for (int j = 0; j < M; ++j)207;       for (int k = 0; k < K; ++k)208;         if (!memcmp(a[i][j][k], b[j], 4))209;           sum += 1;210;211define i64 @three_dimensional_middle(ptr %a, ptr %b, i64 %N, i64 %M, i64 %K) {212; CHECK-LABEL: three_dimensional_middle:213; CHECK:       // %bb.0: // %entry214; CHECK-NEXT:    mov x9, xzr215; CHECK-NEXT:    mov x8, xzr216; CHECK-NEXT:  .LBB3_1: // %for.cond1.preheader217; CHECK-NEXT:    // =>This Loop Header: Depth=1218; CHECK-NEXT:    // Child Loop BB3_2 Depth 2219; CHECK-NEXT:    // Child Loop BB3_3 Depth 3220; CHECK-NEXT:    ldr x10, [x0, x9, lsl #3]221; CHECK-NEXT:    mov x11, xzr222; CHECK-NEXT:  .LBB3_2: // %for.cond5.preheader223; CHECK-NEXT:    // Parent Loop BB3_1 Depth=1224; CHECK-NEXT:    // => This Loop Header: Depth=2225; CHECK-NEXT:    // Child Loop BB3_3 Depth 3226; CHECK-NEXT:    ldr x13, [x1, x11, lsl #3]227; CHECK-NEXT:    ldr x12, [x10, x11, lsl #3]228; CHECK-NEXT:    mov x14, x4229; CHECK-NEXT:    ldr w13, [x13]230; CHECK-NEXT:  .LBB3_3: // %for.body8231; CHECK-NEXT:    // Parent Loop BB3_1 Depth=1232; CHECK-NEXT:    // Parent Loop BB3_2 Depth=2233; CHECK-NEXT:    // => This Inner Loop Header: Depth=3234; CHECK-NEXT:    ldr x15, [x12], #8235; CHECK-NEXT:    ldr w15, [x15]236; CHECK-NEXT:    cmp w15, w13237; CHECK-NEXT:    cinc x8, x8, eq238; CHECK-NEXT:    subs x14, x14, #1239; CHECK-NEXT:    b.ne .LBB3_3240; CHECK-NEXT:  // %bb.4: // %for.cond5.for.cond241; CHECK-NEXT:    // in Loop: Header=BB3_2 Depth=2242; CHECK-NEXT:    add x11, x11, #1243; CHECK-NEXT:    cmp x11, x3244; CHECK-NEXT:    b.ne .LBB3_2245; CHECK-NEXT:  // %bb.5: // %for.cond1.for.cond246; CHECK-NEXT:    // in Loop: Header=BB3_1 Depth=1247; CHECK-NEXT:    add x9, x9, #1248; CHECK-NEXT:    cmp x9, x2249; CHECK-NEXT:    b.ne .LBB3_1250; CHECK-NEXT:  // %bb.6: // %for.exit251; CHECK-NEXT:    mov x0, x8252; CHECK-NEXT:    ret253entry:254  br label %for.cond1.preheader255 256for.cond1.preheader:                        ; preds = %entry, %for.cond1.for.cond257  %i.035 = phi i64 [ %inc16, %for.cond1.for.cond ], [ 0, %entry ]258  %sum.034 = phi i64 [ %spec.select, %for.cond1.for.cond ], [ 0, %entry ]259  %arrayidx = getelementptr inbounds ptr, ptr %a, i64 %i.035260  %0 = load ptr, ptr %arrayidx, align 8261  br label %for.cond5.preheader262 263for.cond5.preheader:                     ; preds = %for.cond5.for.cond, %for.cond1.preheader264  %j.031 = phi i64 [ 0, %for.cond1.preheader ], [ %inc13, %for.cond5.for.cond ]265  %sum.130 = phi i64 [ %sum.034, %for.cond1.preheader ], [ %spec.select, %for.cond5.for.cond ]266  %arrayidx9 = getelementptr inbounds ptr, ptr %0, i64 %j.031267  %1 = load ptr, ptr %arrayidx9, align 8268  %arrayidx11 = getelementptr inbounds ptr, ptr %b, i64 %j.031269  %2 = load ptr, ptr %arrayidx11, align 8270  br label %for.body8271 272for.body8:                               ; preds = %for.body8, %for.cond5.preheader273  %k.028 = phi i64 [ 0, %for.cond5.preheader ], [ %inc, %for.body8 ]274  %sum.227 = phi i64 [ %sum.130, %for.cond5.preheader ], [ %spec.select, %for.body8 ]275  %arrayidx10 = getelementptr inbounds ptr, ptr %1, i64 %k.028276  %3 = load ptr, ptr %arrayidx10, align 8277  %bcmp = tail call i32 @bcmp(ptr %3, ptr %2, i64 4)278  %tobool = icmp eq i32 %bcmp, 0279  %add = zext i1 %tobool to i64280  %spec.select = add i64 %sum.227, %add281  %inc = add nuw i64 %k.028, 1282  %exitcond = icmp eq i64 %inc, %K283  br i1 %exitcond, label %for.cond5.for.cond, label %for.body8284 285for.cond5.for.cond:   ; preds = %for.body8286  %inc13 = add nuw i64 %j.031, 1287  %exitcond46 = icmp eq i64 %inc13, %M288  br i1 %exitcond46, label %for.cond1.for.cond, label %for.cond5.preheader289 290for.cond1.for.cond: ; preds = %for.cond5.for.cond291  %inc16 = add nuw i64 %i.035, 1292  %exitcond47 = icmp eq i64 %inc16, %N293  br i1 %exitcond47, label %for.exit, label %for.cond1.preheader294 295for.exit:                                 ; preds = %for.cond1.for.cond296  ret i64 %spec.select297}298 299; Make sure that store inside loop prevents hoisting invariant loads300;   for (int i = 0; i < N; ++i)301;     c[i] = memcmp(a[i], b, 4);302;303define void @one_dimensional_with_store(ptr %a, ptr %b, ptr %c, i32 %N) {304; CHECK-LABEL: one_dimensional_with_store:305; CHECK:       // %bb.0: // %entry306; CHECK-NEXT:    mov w8, w3307; CHECK-NEXT:  .LBB4_1: // %for.body308; CHECK-NEXT:    // =>This Inner Loop Header: Depth=1309; CHECK-NEXT:    ldr x9, [x0], #8310; CHECK-NEXT:    ldr w10, [x1]311; CHECK-NEXT:    ldr w9, [x9]312; CHECK-NEXT:    rev w10, w10313; CHECK-NEXT:    rev w9, w9314; CHECK-NEXT:    cmp w9, w10315; CHECK-NEXT:    cset w9, hi316; CHECK-NEXT:    csinv w9, w9, wzr, hs317; CHECK-NEXT:    subs x8, x8, #1318; CHECK-NEXT:    strb w9, [x2], #1319; CHECK-NEXT:    b.ne .LBB4_1320; CHECK-NEXT:  // %bb.2: // %for.exit321; CHECK-NEXT:    ret322entry:323  br label %for.body.preheader324 325for.body.preheader:                               ; preds = %entry326  %wide.trip.count = zext i32 %N to i64327  br label %for.body328 329for.body:                                         ; preds = %for.body.preheader, %for.body330  %indvars.iv = phi i64 [ 0, %for.body.preheader ], [ %indvars.iv.next, %for.body ]331  %arrayidx = getelementptr inbounds ptr, ptr %a, i64 %indvars.iv332  %0 = load ptr, ptr %arrayidx, align 8333  %call = tail call i32 @memcmp(ptr %0, ptr %b, i64 4)334  %conv = trunc i32 %call to i8335  %arrayidx2 = getelementptr inbounds i8, ptr %c, i64 %indvars.iv336  store i8 %conv, ptr %arrayidx2, align 1337  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1338  %exitcond.not = icmp eq i64 %indvars.iv.next, %wide.trip.count339  br i1 %exitcond.not, label %for.exit, label %for.body340 341for.exit:                                 ; preds = %for.body342  ret void343}344 345; Make sure that call inside loop prevents hoisting invariant loads346;347define i32 @one_dimensional_with_call(ptr %a, ptr %b, i32 %N) {348; CHECK-LABEL: one_dimensional_with_call:349; CHECK:       // %bb.0: // %entry350; CHECK-NEXT:    str x30, [sp, #-48]! // 8-byte Folded Spill351; CHECK-NEXT:    stp x22, x21, [sp, #16] // 16-byte Folded Spill352; CHECK-NEXT:    stp x20, x19, [sp, #32] // 16-byte Folded Spill353; CHECK-NEXT:    .cfi_def_cfa_offset 48354; CHECK-NEXT:    .cfi_offset w19, -8355; CHECK-NEXT:    .cfi_offset w20, -16356; CHECK-NEXT:    .cfi_offset w21, -24357; CHECK-NEXT:    .cfi_offset w22, -32358; CHECK-NEXT:    .cfi_offset w30, -48359; CHECK-NEXT:    mov x19, x1360; CHECK-NEXT:    mov x21, x0361; CHECK-NEXT:    mov w20, wzr362; CHECK-NEXT:    mov w22, w2363; CHECK-NEXT:  .LBB5_1: // %for.body364; CHECK-NEXT:    // =>This Inner Loop Header: Depth=1365; CHECK-NEXT:    ldr x8, [x21], #8366; CHECK-NEXT:    ldr w9, [x19]367; CHECK-NEXT:    ldr w8, [x8]368; CHECK-NEXT:    cmp w8, w9369; CHECK-NEXT:    cinc w20, w20, eq370; CHECK-NEXT:    bl func371; CHECK-NEXT:    subs x22, x22, #1372; CHECK-NEXT:    b.ne .LBB5_1373; CHECK-NEXT:  // %bb.2: // %for.exit374; CHECK-NEXT:    mov w0, w20375; CHECK-NEXT:    ldp x20, x19, [sp, #32] // 16-byte Folded Reload376; CHECK-NEXT:    ldp x22, x21, [sp, #16] // 16-byte Folded Reload377; CHECK-NEXT:    ldr x30, [sp], #48 // 8-byte Folded Reload378; CHECK-NEXT:    ret379entry:380  br label %for.body.preheader381 382for.body.preheader:                               ; preds = %entry383  %wide.trip.count = zext i32 %N to i64384  br label %for.body385 386for.body:                                         ; preds = %for.body.preheader, %for.body387  %indvars.iv = phi i64 [ 0, %for.body.preheader ], [ %indvars.iv.next, %for.body ]388  %sum.05 = phi i32 [ 0, %for.body.preheader ], [ %spec.select, %for.body ]389  %arrayidx = getelementptr inbounds ptr, ptr %a, i64 %indvars.iv390  %0 = load ptr, ptr %arrayidx, align 8391  %bcmp = tail call i32 @bcmp(ptr %0, ptr %b, i64 4)392  %tobool.not = icmp eq i32 %bcmp, 0393  %add = zext i1 %tobool.not to i32394  %spec.select = add nuw nsw i32 %sum.05, %add395  tail call void @func()396  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1397  %exitcond.not = icmp eq i64 %indvars.iv.next, %wide.trip.count398  br i1 %exitcond.not, label %for.exit, label %for.body399 400for.exit:                                 ; preds = %for.body401  ret i32 %spec.select402}403 404; One dimensional loop with memcmp size equal six.405; The test shows that shows that several loads can be hoisted at the same time.406;   for (int i = 0; i < N; ++i)407;     if (!memcmp(a[i], b, 6))408;       sum += 1;409;410define i64 @one_dimensional_two_loads(ptr %a, ptr %b, i64 %N) {411; CHECK-LABEL: one_dimensional_two_loads:412; CHECK:       // %bb.0: // %entry413; CHECK-NEXT:    ldr w9, [x1]414; CHECK-NEXT:    ldrh w10, [x1, #4]415; CHECK-NEXT:    mov x8, xzr416; CHECK-NEXT:  .LBB6_1: // %for.body417; CHECK-NEXT:    // =>This Inner Loop Header: Depth=1418; CHECK-NEXT:    ldr x11, [x0], #8419; CHECK-NEXT:    ldr w12, [x11]420; CHECK-NEXT:    ldrh w11, [x11, #4]421; CHECK-NEXT:    cmp w12, w9422; CHECK-NEXT:    ccmp w11, w10, #0, eq423; CHECK-NEXT:    cinc x8, x8, eq424; CHECK-NEXT:    subs x2, x2, #1425; CHECK-NEXT:    b.ne .LBB6_1426; CHECK-NEXT:  // %bb.2: // %for.exit427; CHECK-NEXT:    mov x0, x8428; CHECK-NEXT:    ret429entry:430  br label %for.body431 432for.body:                                         ; preds = %entry, %for.body433  %i.06 = phi i64 [ %inc, %for.body ], [ 0, %entry ]434  %sum.05 = phi i64 [ %spec.select, %for.body ], [ 0, %entry ]435  %arrayidx = getelementptr inbounds ptr, ptr %a, i64 %i.06436  %0 = load ptr, ptr %arrayidx, align 8437  %bcmp = tail call i32 @bcmp(ptr %0, ptr %b, i64 6)438  %tobool = icmp eq i32 %bcmp, 0439  %add = zext i1 %tobool to i64440  %spec.select = add i64 %sum.05, %add441  %inc = add nuw i64 %i.06, 1442  %exitcond = icmp eq i64 %inc, %N443  br i1 %exitcond, label %for.exit, label %for.body444 445for.exit:                                 ; preds = %for.body446  ret i64 %spec.select447}448 449; See issue https://github.com/llvm/llvm-project/issues/72855450;451; When hoisting instruction out of the loop, ensure that loads are not common452; subexpressions eliminated. In this example pointer %c may alias pointer %b,453; so when hoisting `%y = load i64, ptr %b` instruction we can't replace it with454; `%b.val = load i64, ptr %b`455;456define i64 @hoisting_no_cse(ptr %a, ptr %b, ptr %c, i64 %N) {457; CHECK-LABEL: hoisting_no_cse:458; CHECK:       // %bb.0: // %entry459; CHECK-NEXT:    ldr x8, [x1]460; CHECK-NEXT:    add x8, x8, #1461; CHECK-NEXT:    str x8, [x2]462; CHECK-NEXT:    mov x8, xzr463; CHECK-NEXT:    ldr x9, [x1]464; CHECK-NEXT:  .LBB7_1: // %for.body465; CHECK-NEXT:    // =>This Inner Loop Header: Depth=1466; CHECK-NEXT:    ldr x10, [x0], #8467; CHECK-NEXT:    ldr x10, [x10]468; CHECK-NEXT:    cmp x10, x9469; CHECK-NEXT:    cinc x8, x8, eq470; CHECK-NEXT:    subs x3, x3, #1471; CHECK-NEXT:    b.ne .LBB7_1472; CHECK-NEXT:  // %bb.2: // %for.exit473; CHECK-NEXT:    mov x0, x8474; CHECK-NEXT:    ret475entry:476  %b.val = load i64, ptr %b477  %b.val.changed = add i64 %b.val, 1478  store i64 %b.val.changed, ptr %c479  br label %for.body480 481for.body:                                         ; preds = %entry, %for.body482  %idx = phi i64 [ %inc, %for.body ], [ 0, %entry ]483  %sum = phi i64 [ %spec.select, %for.body ], [ 0, %entry ]484  %arrayidx = getelementptr inbounds ptr, ptr %a, i64 %idx485  %0 = load ptr, ptr %arrayidx, align 8486  %x = load i64, ptr %0487  %y = load i64, ptr %b488  %cmp = icmp eq i64 %x, %y489  %add = zext i1 %cmp to i64490  %spec.select = add i64 %sum, %add491  %inc = add nuw i64 %idx, 1492  %exitcond = icmp eq i64 %inc, %N493  br i1 %exitcond, label %for.exit, label %for.body494 495for.exit:                                 ; preds = %for.body496  ret i64 %spec.select497}498 499@a = external local_unnamed_addr global i32, align 4500 501; Make sure the load is not hoisted out of the loop across memory barriers.502define i32 @load_between_memory_barriers() {503; CHECK-LABEL: load_between_memory_barriers:504; CHECK:       // %bb.0:505; CHECK-NEXT:    adrp x8, :got:a506; CHECK-NEXT:    ldr x8, [x8, :got_lo12:a]507; CHECK-NEXT:  .LBB8_1: // %loop508; CHECK-NEXT:    // =>This Inner Loop Header: Depth=1509; CHECK-NEXT:    //MEMBARRIER510; CHECK-NEXT:    ldr w0, [x8]511; CHECK-NEXT:    //MEMBARRIER512; CHECK-NEXT:    cbz w0, .LBB8_1513; CHECK-NEXT:  // %bb.2: // %exit514; CHECK-NEXT:    ret515  br label %loop516 517loop:518  fence syncscope("singlethread") acq_rel519  %l = load i32, ptr @a, align 4520  fence syncscope("singlethread") acq_rel521  %c = icmp eq i32 %l, 0522  br i1 %c, label %loop, label %exit523 524exit:525  ret i32 %l526}527 528declare i32 @bcmp(ptr, ptr, i64)529declare i32 @memcmp(ptr, ptr, i64)530declare void @func()531