| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py | 
 | ; RUN: llc -mtriple=aarch64-none-linux-gnu -verify-machineinstrs < %s | FileCheck %s | 
 |  | 
 | define i8 @test1(i32 %a) { | 
 | ; CHECK-LABEL: test1: | 
 | ; CHECK:       // %bb.0: // %entry | 
 | ; CHECK-NEXT:    and w8, w0, #0x3ffc00 | 
 | ; CHECK-NEXT:    and w8, w8, #0xffe007ff | 
 | ; CHECK-NEXT:    cmp w8, #1024 | 
 | ; CHECK-NEXT:    cset w0, eq | 
 | ; CHECK-NEXT:    ret | 
 | entry: | 
 |   %and = and i32 %a, 2098176 | 
 |   %cmp = icmp eq i32 %and, 1024 | 
 |   %conv = zext i1 %cmp to i8 | 
 |   ret i8 %conv | 
 | } | 
 |  | 
 | ; This constant should not be split because it can be handled by one mov. | 
 | define i8 @test2(i32 %a) { | 
 | ; CHECK-LABEL: test2: | 
 | ; CHECK:       // %bb.0: // %entry | 
 | ; CHECK-NEXT:    mov w8, #135 | 
 | ; CHECK-NEXT:    and w8, w0, w8 | 
 | ; CHECK-NEXT:    cmp w8, #1024 | 
 | ; CHECK-NEXT:    cset w0, eq | 
 | ; CHECK-NEXT:    ret | 
 | entry: | 
 |   %and = and i32 %a, 135 | 
 |   %cmp = icmp eq i32 %and, 1024 | 
 |   %conv = zext i1 %cmp to i8 | 
 |   ret i8 %conv | 
 | } | 
 |  | 
 | ; This constant should not be split because the split immediate is not valid | 
 | ; bitmask immediate. | 
 | define i8 @test3(i32 %a) { | 
 | ; CHECK-LABEL: test3: | 
 | ; CHECK:       // %bb.0: // %entry | 
 | ; CHECK-NEXT:    mov w8, #1024 | 
 | ; CHECK-NEXT:    movk w8, #33, lsl #16 | 
 | ; CHECK-NEXT:    and w8, w0, w8 | 
 | ; CHECK-NEXT:    cmp w8, #1024 | 
 | ; CHECK-NEXT:    cset w0, eq | 
 | ; CHECK-NEXT:    ret | 
 | entry: | 
 |   %and = and i32 %a, 2163712 | 
 |   %cmp = icmp eq i32 %and, 1024 | 
 |   %conv = zext i1 %cmp to i8 | 
 |   ret i8 %conv | 
 | } | 
 |  | 
 | define i8 @test4(i64 %a) { | 
 | ; CHECK-LABEL: test4: | 
 | ; CHECK:       // %bb.0: // %entry | 
 | ; CHECK-NEXT:    and x8, x0, #0x3ffc00 | 
 | ; CHECK-NEXT:    and x8, x8, #0xffffffffffe007ff | 
 | ; CHECK-NEXT:    cmp x8, #1024 | 
 | ; CHECK-NEXT:    cset w0, eq | 
 | ; CHECK-NEXT:    ret | 
 | entry: | 
 |   %and = and i64 %a, 2098176 | 
 |   %cmp = icmp eq i64 %and, 1024 | 
 |   %conv = zext i1 %cmp to i8 | 
 |   ret i8 %conv | 
 | } | 
 |  | 
 | define i8 @test5(i64 %a) { | 
 | ; CHECK-LABEL: test5: | 
 | ; CHECK:       // %bb.0: // %entry | 
 | ; CHECK-NEXT:    and x8, x0, #0x3ffffc000 | 
 | ; CHECK-NEXT:    and x8, x8, #0xfffffffe00007fff | 
 | ; CHECK-NEXT:    cmp x8, #1024 | 
 | ; CHECK-NEXT:    cset w0, eq | 
 | ; CHECK-NEXT:    ret | 
 | entry: | 
 |   %and = and i64 %a, 8589950976 | 
 |   %cmp = icmp eq i64 %and, 1024 | 
 |   %conv = zext i1 %cmp to i8 | 
 |   ret i8 %conv | 
 | } | 
 |  | 
 | ; This constant should not be split because it can be handled by one mov. | 
 | define i8 @test6(i64 %a) { | 
 | ; CHECK-LABEL: test6: | 
 | ; CHECK:       // %bb.0: // %entry | 
 | ; CHECK-NEXT:    mov w8, #135 | 
 | ; CHECK-NEXT:    and x8, x0, x8 | 
 | ; CHECK-NEXT:    cmp x8, #1024 | 
 | ; CHECK-NEXT:    cset w0, eq | 
 | ; CHECK-NEXT:    ret | 
 | entry: | 
 |   %and = and i64 %a, 135 | 
 |   %cmp = icmp eq i64 %and, 1024 | 
 |   %conv = zext i1 %cmp to i8 | 
 |   ret i8 %conv | 
 | } | 
 |  | 
 | ; This constant should not be split because the split immediate is not valid | 
 | ; bitmask immediate. | 
 | define i8 @test7(i64 %a) { | 
 | ; CHECK-LABEL: test7: | 
 | ; CHECK:       // %bb.0: // %entry | 
 | ; CHECK-NEXT:    mov w8, #1024 | 
 | ; CHECK-NEXT:    movk w8, #33, lsl #16 | 
 | ; CHECK-NEXT:    and x8, x0, x8 | 
 | ; CHECK-NEXT:    cmp x8, #1024 | 
 | ; CHECK-NEXT:    cset w0, eq | 
 | ; CHECK-NEXT:    ret | 
 | entry: | 
 |   %and = and i64 %a, 2163712 | 
 |   %cmp = icmp eq i64 %and, 1024 | 
 |   %conv = zext i1 %cmp to i8 | 
 |   ret i8 %conv | 
 | } | 
 |  | 
 | ; The split bitmask immediates should be hoisted outside loop because they are | 
 | ; loop invariant. | 
 | define void @test8(i64 %a, ptr noalias %src, ptr noalias %dst, i64 %n) { | 
 | ; CHECK-LABEL: test8: | 
 | ; CHECK:       // %bb.0: // %loop.ph | 
 | ; CHECK-NEXT:    and x9, x0, #0x3ffc00 | 
 | ; CHECK-NEXT:    mov x8, xzr | 
 | ; CHECK-NEXT:    and x9, x9, #0xffffffffffe007ff | 
 | ; CHECK-NEXT:    b .LBB7_2 | 
 | ; CHECK-NEXT:  .LBB7_1: // %for.inc | 
 | ; CHECK-NEXT:    // in Loop: Header=BB7_2 Depth=1 | 
 | ; CHECK-NEXT:    add x8, x8, #1 | 
 | ; CHECK-NEXT:    cmp x8, x3 | 
 | ; CHECK-NEXT:    b.gt .LBB7_4 | 
 | ; CHECK-NEXT:  .LBB7_2: // %loop | 
 | ; CHECK-NEXT:    // =>This Inner Loop Header: Depth=1 | 
 | ; CHECK-NEXT:    cmp x8, x9 | 
 | ; CHECK-NEXT:    b.hs .LBB7_1 | 
 | ; CHECK-NEXT:  // %bb.3: // %if.then | 
 | ; CHECK-NEXT:    // in Loop: Header=BB7_2 Depth=1 | 
 | ; CHECK-NEXT:    lsl x10, x8, #3 | 
 | ; CHECK-NEXT:    ldr x11, [x1, x10] | 
 | ; CHECK-NEXT:    str x11, [x2, x10] | 
 | ; CHECK-NEXT:    b .LBB7_1 | 
 | ; CHECK-NEXT:  .LBB7_4: // %exit | 
 | ; CHECK-NEXT:    ret | 
 | loop.ph: | 
 |   br label %loop | 
 |  | 
 | loop: | 
 |   %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ] | 
 |   %and = and i64 %a, 2098176 | 
 |   %cmp = icmp ult i64 %iv, %and | 
 |   br i1 %cmp, label %if.then, label %if.else | 
 |  | 
 | if.then: | 
 |   %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv | 
 |   %val = load i64, ptr %src.arrayidx | 
 |   %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv | 
 |   store i64 %val, ptr %dst.arrayidx | 
 |   br label %for.inc | 
 |  | 
 | if.else: | 
 |   br label %for.inc | 
 |  | 
 | for.inc: | 
 |   %inc = add nuw nsw i64 %iv, 1 | 
 |   %cond = icmp sgt i64 %inc, %n | 
 |   br i1 %cond, label %exit, label %loop | 
 |  | 
 | exit: | 
 |   ret void | 
 | } | 
 |  | 
 | ; This constant should not be split because the `and` is not loop invariant. | 
 | define i32 @test9(ptr nocapture %x, ptr nocapture readonly %y, i32 %n) { | 
 | ; CHECK-LABEL: test9: | 
 | ; CHECK:       // %bb.0: // %entry | 
 | ; CHECK-NEXT:    cmp w2, #1 | 
 | ; CHECK-NEXT:    b.lt .LBB8_3 | 
 | ; CHECK-NEXT:  // %bb.1: // %for.body.preheader | 
 | ; CHECK-NEXT:    mov w9, #1024 | 
 | ; CHECK-NEXT:    mov w8, w2 | 
 | ; CHECK-NEXT:    movk w9, #32, lsl #16 | 
 | ; CHECK-NEXT:  .LBB8_2: // %for.body | 
 | ; CHECK-NEXT:    // =>This Inner Loop Header: Depth=1 | 
 | ; CHECK-NEXT:    ldr w10, [x1], #4 | 
 | ; CHECK-NEXT:    subs x8, x8, #1 | 
 | ; CHECK-NEXT:    and w10, w10, w9 | 
 | ; CHECK-NEXT:    str w10, [x0], #4 | 
 | ; CHECK-NEXT:    b.ne .LBB8_2 | 
 | ; CHECK-NEXT:  .LBB8_3: // %for.cond.cleanup | 
 | ; CHECK-NEXT:    mov w0, wzr | 
 | ; CHECK-NEXT:    ret | 
 | entry: | 
 |   %cmp8 = icmp sgt i32 %n, 0 | 
 |   br i1 %cmp8, label %for.body.preheader, label %for.cond.cleanup | 
 |  | 
 | for.body.preheader:                               ; preds = %entry | 
 |   %wide.trip.count = zext i32 %n to i64 | 
 |   br label %for.body | 
 |  | 
 | for.cond.cleanup:                                 ; preds = %for.body, %entry | 
 |   ret i32 0 | 
 |  | 
 | for.body:                                         ; preds = %for.body.preheader, %for.body | 
 |   %indvars.iv = phi i64 [ 0, %for.body.preheader ], [ %indvars.iv.next, %for.body ] | 
 |   %arrayidx = getelementptr inbounds i32, ptr %y, i64 %indvars.iv | 
 |   %0 = load i32, ptr %arrayidx, align 4 | 
 |   %and = and i32 %0, 2098176 | 
 |   %arrayidx2 = getelementptr inbounds i32, ptr %x, i64 %indvars.iv | 
 |   store i32 %and, ptr %arrayidx2, align 4 | 
 |   %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 | 
 |   %exitcond.not = icmp eq i64 %indvars.iv.next, %wide.trip.count | 
 |   br i1 %exitcond.not, label %for.cond.cleanup, label %for.body | 
 | } | 
 |  | 
 | ; After instruction selection end, we can see the `and` and `or` share the | 
 | ; constant as below. | 
 | ; | 
 | ; %4:gpr32 = MOVi32imm 2098176 | 
 | ; %5:gpr32 = ANDWrr killed %3:gpr32, %4:gpr32 | 
 | ; STRWui killed %5:gpr32, %0:gpr64common, 0 :: (store (s32) into %ir.x, !tbaa !8) | 
 | ; %6:gpr32 = LDRWui %1:gpr64common, 0 :: (load (s32) from %ir.y, !tbaa !8) | 
 | ; %7:gpr32 = ORRWrr killed %6:gpr32, %4:gpr32 | 
 | ; | 
 | ; In this case, the constant should not be split because it causes more | 
 | ; instructions. | 
 | define void @test10(ptr nocapture %x, ptr nocapture readonly %y, ptr nocapture %z) { | 
 | ; CHECK-LABEL: test10: | 
 | ; CHECK:       // %bb.0: // %entry | 
 | ; CHECK-NEXT:    ldr w8, [x1] | 
 | ; CHECK-NEXT:    mov w9, #1024 | 
 | ; CHECK-NEXT:    movk w9, #32, lsl #16 | 
 | ; CHECK-NEXT:    and w8, w8, w9 | 
 | ; CHECK-NEXT:    str w8, [x0] | 
 | ; CHECK-NEXT:    ldr w8, [x1] | 
 | ; CHECK-NEXT:    orr w8, w8, w9 | 
 | ; CHECK-NEXT:    str w8, [x2] | 
 | ; CHECK-NEXT:    ret | 
 | entry: | 
 |   %0 = load i32, ptr %y, align 4 | 
 |   %and = and i32 %0, 2098176 | 
 |   store i32 %and, ptr %x, align 4 | 
 |   %1 = load i32, ptr %y, align 4 | 
 |   %or = or i32 %1, 2098176 | 
 |   store i32 %or, ptr %z, align 4 | 
 |   ret void | 
 | } | 
 |  | 
 | ; This test genereates below MIs. | 
 | ; | 
 | ; MOVi32imm -1610612736 | 
 | ; SUBREG_TO_REG | 
 | ; | 
 | ; The constant should be zero-extended to 64 bit and it should not be split. | 
 | define i8 @test11(i64 %a) { | 
 | ; CHECK-LABEL: test11: | 
 | ; CHECK:       // %bb.0: // %entry | 
 | ; CHECK-NEXT:    mov w8, #-1610612736 | 
 | ; CHECK-NEXT:    and x8, x0, x8 | 
 | ; CHECK-NEXT:    cmp x8, #1024 | 
 | ; CHECK-NEXT:    cset w0, eq | 
 | ; CHECK-NEXT:    ret | 
 | entry: | 
 |   %and = and i64 %a, 2684354560 | 
 |   %cmp = icmp eq i64 %and, 1024 | 
 |   %conv = zext i1 %cmp to i8 | 
 |   ret i8 %conv | 
 | } |