Compiler projects using llvm
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
# RUN: llc -mtriple=aarch64 -run-pass=aarch64-postlegalizer-lowering -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=LOWER
# RUN: llc -mtriple=aarch64 -global-isel -start-before=aarch64-postlegalizer-lowering -stop-after=instruction-select -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=SELECT

# Verify that we will adjust the constant + predicate of a compare when it will
# allow us to fold an immediate into a compare.
...
---
name:            slt_to_sle_s32
legalized:       true
tracksRegLiveness: true
body:             |
  bb.0:
    liveins: $w0

    ; x slt c => x sle c - 1
    ;
    ; log_2(4096) == 12, so we can represent this as a 12 bit value with a
    ; left shift.

    ; LOWER-LABEL: name: slt_to_sle_s32
    ; LOWER: liveins: $w0
    ; LOWER-NEXT: {{  $}}
    ; LOWER-NEXT: %reg:_(s32) = COPY $w0
    ; LOWER-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 4096
    ; LOWER-NEXT: %cmp:_(s32) = G_ICMP intpred(sle), %reg(s32), [[C]]
    ; LOWER-NEXT: $w0 = COPY %cmp(s32)
    ; LOWER-NEXT: RET_ReallyLR implicit $w0
    ; SELECT-LABEL: name: slt_to_sle_s32
    ; SELECT: liveins: $w0
    ; SELECT-NEXT: {{  $}}
    ; SELECT-NEXT: %reg:gpr32sp = COPY $w0
    ; SELECT-NEXT: [[SUBSWri:%[0-9]+]]:gpr32 = SUBSWri %reg, 1, 12, implicit-def $nzcv
    ; SELECT-NEXT: %cmp:gpr32 = CSINCWr $wzr, $wzr, 12, implicit $nzcv
    ; SELECT-NEXT: $w0 = COPY %cmp
    ; SELECT-NEXT: RET_ReallyLR implicit $w0
    %reg:_(s32) = COPY $w0
    %cst:_(s32) = G_CONSTANT i32 4097
    %cmp:_(s32) = G_ICMP intpred(slt), %reg(s32), %cst
    $w0 = COPY %cmp(s32)
    RET_ReallyLR implicit $w0

...
---
name:            slt_to_sle_s64
legalized:       true
tracksRegLiveness: true
body:             |
  bb.0:
    liveins: $x0

    ; x slt c => x sle c - 1
    ;
    ; log_2(4096) == 12, so we can represent this as a 12 bit value with a
    ; left shift.

    ; LOWER-LABEL: name: slt_to_sle_s64
    ; LOWER: liveins: $x0
    ; LOWER-NEXT: {{  $}}
    ; LOWER-NEXT: %reg:_(s64) = COPY $x0
    ; LOWER-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 4096
    ; LOWER-NEXT: %cmp:_(s32) = G_ICMP intpred(sle), %reg(s64), [[C]]
    ; LOWER-NEXT: $w0 = COPY %cmp(s32)
    ; LOWER-NEXT: RET_ReallyLR implicit $w0
    ; SELECT-LABEL: name: slt_to_sle_s64
    ; SELECT: liveins: $x0
    ; SELECT-NEXT: {{  $}}
    ; SELECT-NEXT: %reg:gpr64sp = COPY $x0
    ; SELECT-NEXT: [[SUBSXri:%[0-9]+]]:gpr64 = SUBSXri %reg, 1, 12, implicit-def $nzcv
    ; SELECT-NEXT: %cmp:gpr32 = CSINCWr $wzr, $wzr, 12, implicit $nzcv
    ; SELECT-NEXT: $w0 = COPY %cmp
    ; SELECT-NEXT: RET_ReallyLR implicit $w0
    %reg:_(s64) = COPY $x0
    %cst:_(s64) = G_CONSTANT i64 4097
    %cmp:_(s32) = G_ICMP intpred(slt), %reg(s64), %cst
    $w0 = COPY %cmp(s32)
    RET_ReallyLR implicit $w0

...
---
name:            sge_to_sgt_s32
legalized:       true
tracksRegLiveness: true
body:             |
  bb.0:
    liveins: $w0

    ; x sge c => x sgt c - 1
    ;
    ; log_2(4096) == 12, so we can represent this as a 12 bit value with a
    ; left shift.

    ; LOWER-LABEL: name: sge_to_sgt_s32
    ; LOWER: liveins: $w0
    ; LOWER-NEXT: {{  $}}
    ; LOWER-NEXT: %reg:_(s32) = COPY $w0
    ; LOWER-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 4096
    ; LOWER-NEXT: %cmp:_(s32) = G_ICMP intpred(sgt), %reg(s32), [[C]]
    ; LOWER-NEXT: $w0 = COPY %cmp(s32)
    ; LOWER-NEXT: RET_ReallyLR implicit $w0
    ; SELECT-LABEL: name: sge_to_sgt_s32
    ; SELECT: liveins: $w0
    ; SELECT-NEXT: {{  $}}
    ; SELECT-NEXT: %reg:gpr32sp = COPY $w0
    ; SELECT-NEXT: [[SUBSWri:%[0-9]+]]:gpr32 = SUBSWri %reg, 1, 12, implicit-def $nzcv
    ; SELECT-NEXT: %cmp:gpr32 = CSINCWr $wzr, $wzr, 13, implicit $nzcv
    ; SELECT-NEXT: $w0 = COPY %cmp
    ; SELECT-NEXT: RET_ReallyLR implicit $w0
    %reg:_(s32) = COPY $w0
    %cst:_(s32) = G_CONSTANT i32 4097
    %cmp:_(s32) = G_ICMP intpred(sge), %reg(s32), %cst
    $w0 = COPY %cmp(s32)
    RET_ReallyLR implicit $w0

...
---
name:            sge_to_sgt_s64
legalized:       true
tracksRegLiveness: true
body:             |
  bb.0:
    liveins: $x0

    ; x sge c => x sgt c - 1
    ;
    ; log_2(4096) == 12, so we can represent this as a 12 bit value with a
    ; left shift.

    ; LOWER-LABEL: name: sge_to_sgt_s64
    ; LOWER: liveins: $x0
    ; LOWER-NEXT: {{  $}}
    ; LOWER-NEXT: %reg:_(s64) = COPY $x0
    ; LOWER-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 4096
    ; LOWER-NEXT: %cmp:_(s32) = G_ICMP intpred(sgt), %reg(s64), [[C]]
    ; LOWER-NEXT: $w0 = COPY %cmp(s32)
    ; LOWER-NEXT: RET_ReallyLR implicit $w0
    ; SELECT-LABEL: name: sge_to_sgt_s64
    ; SELECT: liveins: $x0
    ; SELECT-NEXT: {{  $}}
    ; SELECT-NEXT: %reg:gpr64sp = COPY $x0
    ; SELECT-NEXT: [[SUBSXri:%[0-9]+]]:gpr64 = SUBSXri %reg, 1, 12, implicit-def $nzcv
    ; SELECT-NEXT: %cmp:gpr32 = CSINCWr $wzr, $wzr, 13, implicit $nzcv
    ; SELECT-NEXT: $w0 = COPY %cmp
    ; SELECT-NEXT: RET_ReallyLR implicit $w0
    %reg:_(s64) = COPY $x0
    %cst:_(s64) = G_CONSTANT i64 4097
    %cmp:_(s32) = G_ICMP intpred(sge), %reg(s64), %cst
    $w0 = COPY %cmp(s32)
    RET_ReallyLR implicit $w0

...
---
name:            ult_to_ule_s32
legalized:       true
tracksRegLiveness: true
body:             |
  bb.0:
    liveins: $w0

    ; x ult c => x ule c - 1
    ;
    ; log_2(4096) == 12, so we can represent this as a 12 bit value with a
    ; left shift.

    ; LOWER-LABEL: name: ult_to_ule_s32
    ; LOWER: liveins: $w0
    ; LOWER-NEXT: {{  $}}
    ; LOWER-NEXT: %reg:_(s32) = COPY $w0
    ; LOWER-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 4096
    ; LOWER-NEXT: %cmp:_(s32) = G_ICMP intpred(ule), %reg(s32), [[C]]
    ; LOWER-NEXT: $w0 = COPY %cmp(s32)
    ; LOWER-NEXT: RET_ReallyLR implicit $w0
    ; SELECT-LABEL: name: ult_to_ule_s32
    ; SELECT: liveins: $w0
    ; SELECT-NEXT: {{  $}}
    ; SELECT-NEXT: %reg:gpr32sp = COPY $w0
    ; SELECT-NEXT: [[SUBSWri:%[0-9]+]]:gpr32 = SUBSWri %reg, 1, 12, implicit-def $nzcv
    ; SELECT-NEXT: %cmp:gpr32 = CSINCWr $wzr, $wzr, 8, implicit $nzcv
    ; SELECT-NEXT: $w0 = COPY %cmp
    ; SELECT-NEXT: RET_ReallyLR implicit $w0
    %reg:_(s32) = COPY $w0
    %cst:_(s32) = G_CONSTANT i32 4097
    %cmp:_(s32) = G_ICMP intpred(ult), %reg(s32), %cst
    $w0 = COPY %cmp(s32)
    RET_ReallyLR implicit $w0

...
---
name:            ult_to_ule_s64
legalized:       true
tracksRegLiveness: true
body:             |
  bb.0:
    liveins: $x0

    ; x ult c => x ule c - 1
    ;
    ; log_2(4096) == 12, so we can represent this as a 12 bit value with a
    ; left shift.

    ; LOWER-LABEL: name: ult_to_ule_s64
    ; LOWER: liveins: $x0
    ; LOWER-NEXT: {{  $}}
    ; LOWER-NEXT: %reg:_(s64) = COPY $x0
    ; LOWER-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 4096
    ; LOWER-NEXT: %cmp:_(s32) = G_ICMP intpred(ule), %reg(s64), [[C]]
    ; LOWER-NEXT: $w0 = COPY %cmp(s32)
    ; LOWER-NEXT: RET_ReallyLR implicit $w0
    ; SELECT-LABEL: name: ult_to_ule_s64
    ; SELECT: liveins: $x0
    ; SELECT-NEXT: {{  $}}
    ; SELECT-NEXT: %reg:gpr64sp = COPY $x0
    ; SELECT-NEXT: [[SUBSXri:%[0-9]+]]:gpr64 = SUBSXri %reg, 1, 12, implicit-def $nzcv
    ; SELECT-NEXT: %cmp:gpr32 = CSINCWr $wzr, $wzr, 8, implicit $nzcv
    ; SELECT-NEXT: $w0 = COPY %cmp
    ; SELECT-NEXT: RET_ReallyLR implicit $w0
    %reg:_(s64) = COPY $x0
    %cst:_(s64) = G_CONSTANT i64 4097
    %cmp:_(s32) = G_ICMP intpred(ult), %reg(s64), %cst
    $w0 = COPY %cmp(s32)
    RET_ReallyLR implicit $w0

...
---
name:            uge_to_ugt_s32
legalized:       true
tracksRegLiveness: true
body:             |
  bb.0:
    liveins: $w0

    ; x uge c => x ugt c - 1
    ;
    ; log_2(4096) == 12, so we can represent this as a 12 bit value with a
    ; left shift.

    ; LOWER-LABEL: name: uge_to_ugt_s32
    ; LOWER: liveins: $w0
    ; LOWER-NEXT: {{  $}}
    ; LOWER-NEXT: %reg:_(s32) = COPY $w0
    ; LOWER-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 4096
    ; LOWER-NEXT: %cmp:_(s32) = G_ICMP intpred(ugt), %reg(s32), [[C]]
    ; LOWER-NEXT: $w0 = COPY %cmp(s32)
    ; LOWER-NEXT: RET_ReallyLR implicit $w0
    ; SELECT-LABEL: name: uge_to_ugt_s32
    ; SELECT: liveins: $w0
    ; SELECT-NEXT: {{  $}}
    ; SELECT-NEXT: %reg:gpr32sp = COPY $w0
    ; SELECT-NEXT: [[SUBSWri:%[0-9]+]]:gpr32 = SUBSWri %reg, 1, 12, implicit-def $nzcv
    ; SELECT-NEXT: %cmp:gpr32 = CSINCWr $wzr, $wzr, 9, implicit $nzcv
    ; SELECT-NEXT: $w0 = COPY %cmp
    ; SELECT-NEXT: RET_ReallyLR implicit $w0
    %reg:_(s32) = COPY $w0
    %cst:_(s32) = G_CONSTANT i32 4097
    %cmp:_(s32) = G_ICMP intpred(uge), %reg(s32), %cst
    $w0 = COPY %cmp(s32)
    RET_ReallyLR implicit $w0

...
---
name:            uge_to_ugt_s64
legalized:       true
tracksRegLiveness: true
body:             |
  bb.0:
    liveins: $x0

    ; x uge c => x ugt c - 1
    ;
    ; log_2(4096) == 12, so we can represent this as a 12 bit value with a
    ; left shift.

    ; LOWER-LABEL: name: uge_to_ugt_s64
    ; LOWER: liveins: $x0
    ; LOWER-NEXT: {{  $}}
    ; LOWER-NEXT: %reg:_(s64) = COPY $x0
    ; LOWER-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 4096
    ; LOWER-NEXT: %cmp:_(s32) = G_ICMP intpred(ugt), %reg(s64), [[C]]
    ; LOWER-NEXT: $w0 = COPY %cmp(s32)
    ; LOWER-NEXT: RET_ReallyLR implicit $w0
    ; SELECT-LABEL: name: uge_to_ugt_s64
    ; SELECT: liveins: $x0
    ; SELECT-NEXT: {{  $}}
    ; SELECT-NEXT: %reg:gpr64sp = COPY $x0
    ; SELECT-NEXT: [[SUBSXri:%[0-9]+]]:gpr64 = SUBSXri %reg, 1, 12, implicit-def $nzcv
    ; SELECT-NEXT: %cmp:gpr32 = CSINCWr $wzr, $wzr, 9, implicit $nzcv
    ; SELECT-NEXT: $w0 = COPY %cmp
    ; SELECT-NEXT: RET_ReallyLR implicit $w0
    %reg:_(s64) = COPY $x0
    %cst:_(s64) = G_CONSTANT i64 4097
    %cmp:_(s32) = G_ICMP intpred(uge), %reg(s64), %cst
    $w0 = COPY %cmp(s32)
    RET_ReallyLR implicit $w0

...
---
name:            sle_to_slt_s32
legalized:       true
tracksRegLiveness: true
body:             |
  bb.0:
    liveins: $w0

    ; x sle c => x slt c + 1
    ;
    ; log_2(8192) == 13, so we can represent this as a 12 bit value with a
    ; left shift.
    ;
    ; (We can't use 4095 here, because that's a legal arithmetic immediate.)

    ; LOWER-LABEL: name: sle_to_slt_s32
    ; LOWER: liveins: $w0
    ; LOWER-NEXT: {{  $}}
    ; LOWER-NEXT: %reg:_(s32) = COPY $w0
    ; LOWER-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 8192
    ; LOWER-NEXT: %cmp:_(s32) = G_ICMP intpred(slt), %reg(s32), [[C]]
    ; LOWER-NEXT: $w0 = COPY %cmp(s32)
    ; LOWER-NEXT: RET_ReallyLR implicit $w0
    ; SELECT-LABEL: name: sle_to_slt_s32
    ; SELECT: liveins: $w0
    ; SELECT-NEXT: {{  $}}
    ; SELECT-NEXT: %reg:gpr32sp = COPY $w0
    ; SELECT-NEXT: [[SUBSWri:%[0-9]+]]:gpr32 = SUBSWri %reg, 2, 12, implicit-def $nzcv
    ; SELECT-NEXT: %cmp:gpr32 = CSINCWr $wzr, $wzr, 10, implicit $nzcv
    ; SELECT-NEXT: $w0 = COPY %cmp
    ; SELECT-NEXT: RET_ReallyLR implicit $w0
    %reg:_(s32) = COPY $w0
    %cst:_(s32) = G_CONSTANT i32 8191
    %cmp:_(s32) = G_ICMP intpred(sle), %reg(s32), %cst
    $w0 = COPY %cmp(s32)
    RET_ReallyLR implicit $w0

...
---
name:            sle_to_slt_s64
legalized:       true
tracksRegLiveness: true
body:             |
  bb.0:
    liveins: $x0

    ; x sle c => x slt c + 1
    ;
    ; log_2(8192) == 13, so we can represent this as a 12 bit value with a
    ; left shift.

    ; LOWER-LABEL: name: sle_to_slt_s64
    ; LOWER: liveins: $x0
    ; LOWER-NEXT: {{  $}}
    ; LOWER-NEXT: %reg:_(s64) = COPY $x0
    ; LOWER-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 8192
    ; LOWER-NEXT: %cmp:_(s32) = G_ICMP intpred(slt), %reg(s64), [[C]]
    ; LOWER-NEXT: $w0 = COPY %cmp(s32)
    ; LOWER-NEXT: RET_ReallyLR implicit $w0
    ; SELECT-LABEL: name: sle_to_slt_s64
    ; SELECT: liveins: $x0
    ; SELECT-NEXT: {{  $}}
    ; SELECT-NEXT: %reg:gpr64sp = COPY $x0
    ; SELECT-NEXT: [[SUBSXri:%[0-9]+]]:gpr64 = SUBSXri %reg, 2, 12, implicit-def $nzcv
    ; SELECT-NEXT: %cmp:gpr32 = CSINCWr $wzr, $wzr, 10, implicit $nzcv
    ; SELECT-NEXT: $w0 = COPY %cmp
    ; SELECT-NEXT: RET_ReallyLR implicit $w0
    %reg:_(s64) = COPY $x0
    %cst:_(s64) = G_CONSTANT i64 8191
    %cmp:_(s32) = G_ICMP intpred(sle), %reg(s64), %cst
    $w0 = COPY %cmp(s32)
    RET_ReallyLR implicit $w0

...
---
name:            sgt_to_sge_s32
legalized:       true
tracksRegLiveness: true
body:             |
  bb.0:
    liveins: $w0

    ; x sgt c => s sge c + 1
    ;
    ; log_2(8192) == 13, so we can represent this as a 12 bit value with a
    ; left shift.

    ; LOWER-LABEL: name: sgt_to_sge_s32
    ; LOWER: liveins: $w0
    ; LOWER-NEXT: {{  $}}
    ; LOWER-NEXT: %reg:_(s32) = COPY $w0
    ; LOWER-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 8192
    ; LOWER-NEXT: %cmp:_(s32) = G_ICMP intpred(sge), %reg(s32), [[C]]
    ; LOWER-NEXT: $w0 = COPY %cmp(s32)
    ; LOWER-NEXT: RET_ReallyLR implicit $w0
    ; SELECT-LABEL: name: sgt_to_sge_s32
    ; SELECT: liveins: $w0
    ; SELECT-NEXT: {{  $}}
    ; SELECT-NEXT: %reg:gpr32sp = COPY $w0
    ; SELECT-NEXT: [[SUBSWri:%[0-9]+]]:gpr32 = SUBSWri %reg, 2, 12, implicit-def $nzcv
    ; SELECT-NEXT: %cmp:gpr32 = CSINCWr $wzr, $wzr, 11, implicit $nzcv
    ; SELECT-NEXT: $w0 = COPY %cmp
    ; SELECT-NEXT: RET_ReallyLR implicit $w0
    %reg:_(s32) = COPY $w0
    %cst:_(s32) = G_CONSTANT i32 8191
    %cmp:_(s32) = G_ICMP intpred(sgt), %reg(s32), %cst
    $w0 = COPY %cmp(s32)
    RET_ReallyLR implicit $w0

...
---
name:            sgt_to_sge_s64
legalized:       true
tracksRegLiveness: true
body:             |
  bb.0:
    liveins: $x0

    ; x sgt c => s sge c + 1
    ;
    ; log_2(8192) == 13, so we can represent this as a 12 bit value with a
    ; left shift.

    ; LOWER-LABEL: name: sgt_to_sge_s64
    ; LOWER: liveins: $x0
    ; LOWER-NEXT: {{  $}}
    ; LOWER-NEXT: %reg:_(s64) = COPY $x0
    ; LOWER-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 8192
    ; LOWER-NEXT: %cmp:_(s32) = G_ICMP intpred(sge), %reg(s64), [[C]]
    ; LOWER-NEXT: $w0 = COPY %cmp(s32)
    ; LOWER-NEXT: RET_ReallyLR implicit $w0
    ; SELECT-LABEL: name: sgt_to_sge_s64
    ; SELECT: liveins: $x0
    ; SELECT-NEXT: {{  $}}
    ; SELECT-NEXT: %reg:gpr64sp = COPY $x0
    ; SELECT-NEXT: [[SUBSXri:%[0-9]+]]:gpr64 = SUBSXri %reg, 2, 12, implicit-def $nzcv
    ; SELECT-NEXT: %cmp:gpr32 = CSINCWr $wzr, $wzr, 11, implicit $nzcv
    ; SELECT-NEXT: $w0 = COPY %cmp
    ; SELECT-NEXT: RET_ReallyLR implicit $w0
    %reg:_(s64) = COPY $x0
    %cst:_(s64) = G_CONSTANT i64 8191
    %cmp:_(s32) = G_ICMP intpred(sgt), %reg(s64), %cst
    $w0 = COPY %cmp(s32)
    RET_ReallyLR implicit $w0

...
---
name:            no_opt_int32_min
legalized:       true
tracksRegLiveness: true
body:             |
  bb.0:
    liveins: $w0

    ; The cmp should not change.
    ;
    ; If we subtract 1 from the constant, it will wrap around, and so it's not
    ; true that
    ;
    ; x slt c => x sle c - 1
    ; x sge c => x sgt c - 1

    ; LOWER-LABEL: name: no_opt_int32_min
    ; LOWER: liveins: $w0
    ; LOWER-NEXT: {{  $}}
    ; LOWER-NEXT: %reg:_(s32) = COPY $w0
    ; LOWER-NEXT: %cst:_(s32) = G_CONSTANT i32 -2147483648
    ; LOWER-NEXT: %cmp:_(s32) = G_ICMP intpred(slt), %reg(s32), %cst
    ; LOWER-NEXT: $w0 = COPY %cmp(s32)
    ; LOWER-NEXT: RET_ReallyLR implicit $w0
    ; SELECT-LABEL: name: no_opt_int32_min
    ; SELECT: liveins: $w0
    ; SELECT-NEXT: {{  $}}
    ; SELECT-NEXT: %reg:gpr32 = COPY $w0
    ; SELECT-NEXT: %cst:gpr32 = MOVi32imm -2147483648
    ; SELECT-NEXT: [[SUBSWrr:%[0-9]+]]:gpr32 = SUBSWrr %reg, %cst, implicit-def $nzcv
    ; SELECT-NEXT: %cmp:gpr32 = CSINCWr $wzr, $wzr, 10, implicit $nzcv
    ; SELECT-NEXT: $w0 = COPY %cmp
    ; SELECT-NEXT: RET_ReallyLR implicit $w0
    %reg:_(s32) = COPY $w0
    %cst:_(s32) = G_CONSTANT i32 -2147483648
    %cmp:_(s32) = G_ICMP intpred(slt), %reg(s32), %cst
    $w0 = COPY %cmp(s32)
    RET_ReallyLR implicit $w0

...
---
name:            no_opt_int64_min
legalized:       true
tracksRegLiveness: true
body:             |
  bb.0:
    liveins: $x0

    ; The cmp should not change.
    ;
    ; If we subtract 1 from the constant, it will wrap around, and so it's not
    ; true that
    ;
    ; x slt c => x sle c - 1
    ; x sge c => x sgt c - 1

    ; LOWER-LABEL: name: no_opt_int64_min
    ; LOWER: liveins: $x0
    ; LOWER-NEXT: {{  $}}
    ; LOWER-NEXT: %reg:_(s64) = COPY $x0
    ; LOWER-NEXT: %cst:_(s64) = G_CONSTANT i64 -9223372036854775808
    ; LOWER-NEXT: %cmp:_(s32) = G_ICMP intpred(slt), %reg(s64), %cst
    ; LOWER-NEXT: $w0 = COPY %cmp(s32)
    ; LOWER-NEXT: RET_ReallyLR implicit $w0
    ; SELECT-LABEL: name: no_opt_int64_min
    ; SELECT: liveins: $x0
    ; SELECT-NEXT: {{  $}}
    ; SELECT-NEXT: %reg:gpr64 = COPY $x0
    ; SELECT-NEXT: %cst:gpr64 = MOVi64imm -9223372036854775808
    ; SELECT-NEXT: [[SUBSXrr:%[0-9]+]]:gpr64 = SUBSXrr %reg, %cst, implicit-def $nzcv
    ; SELECT-NEXT: %cmp:gpr32 = CSINCWr $wzr, $wzr, 10, implicit $nzcv
    ; SELECT-NEXT: $w0 = COPY %cmp
    ; SELECT-NEXT: RET_ReallyLR implicit $w0
    %reg:_(s64) = COPY $x0
    %cst:_(s64) = G_CONSTANT i64 -9223372036854775808
    %cmp:_(s32) = G_ICMP intpred(slt), %reg(s64), %cst
    $w0 = COPY %cmp(s32)
    RET_ReallyLR implicit $w0

...
---
name:            no_opt_int32_max
legalized:       true
tracksRegLiveness: true
body:             |
  bb.0:
    liveins: $w0

    ; The cmp should not change.
    ;
    ; If we add 1 to the constant, it will wrap around, and so it's not true
    ; that
    ;
    ; x slt c => x sle c - 1
    ; x sge c => x sgt c - 1

    ; LOWER-LABEL: name: no_opt_int32_max
    ; LOWER: liveins: $w0
    ; LOWER-NEXT: {{  $}}
    ; LOWER-NEXT: %reg:_(s32) = COPY $w0
    ; LOWER-NEXT: %cst:_(s32) = G_CONSTANT i32 2147483647
    ; LOWER-NEXT: %cmp:_(s32) = G_ICMP intpred(sle), %reg(s32), %cst
    ; LOWER-NEXT: $w0 = COPY %cmp(s32)
    ; LOWER-NEXT: RET_ReallyLR implicit $w0
    ; SELECT-LABEL: name: no_opt_int32_max
    ; SELECT: liveins: $w0
    ; SELECT-NEXT: {{  $}}
    ; SELECT-NEXT: %reg:gpr32 = COPY $w0
    ; SELECT-NEXT: %cst:gpr32 = MOVi32imm 2147483647
    ; SELECT-NEXT: [[SUBSWrr:%[0-9]+]]:gpr32 = SUBSWrr %reg, %cst, implicit-def $nzcv
    ; SELECT-NEXT: %cmp:gpr32 = CSINCWr $wzr, $wzr, 12, implicit $nzcv
    ; SELECT-NEXT: $w0 = COPY %cmp
    ; SELECT-NEXT: RET_ReallyLR implicit $w0
    %reg:_(s32) = COPY $w0
    %cst:_(s32) = G_CONSTANT i32 2147483647
    %cmp:_(s32) = G_ICMP intpred(sle), %reg(s32), %cst
    $w0 = COPY %cmp(s32)
    RET_ReallyLR implicit $w0

...
---
name:            no_opt_int64_max
legalized:       true
tracksRegLiveness: true
body:             |
  bb.0:
    liveins: $x0

    ; The cmp should not change.
    ;
    ; If we add 1 to the constant, it will wrap around, and so it's not true
    ; that
    ;
    ; x slt c => x sle c - 1
    ; x sge c => x sgt c - 1


    ; LOWER-LABEL: name: no_opt_int64_max
    ; LOWER: liveins: $x0
    ; LOWER-NEXT: {{  $}}
    ; LOWER-NEXT: %reg:_(s64) = COPY $x0
    ; LOWER-NEXT: %cst:_(s64) = G_CONSTANT i64 9223372036854775807
    ; LOWER-NEXT: %cmp:_(s32) = G_ICMP intpred(sle), %reg(s64), %cst
    ; LOWER-NEXT: $w0 = COPY %cmp(s32)
    ; LOWER-NEXT: RET_ReallyLR implicit $w0
    ; SELECT-LABEL: name: no_opt_int64_max
    ; SELECT: liveins: $x0
    ; SELECT-NEXT: {{  $}}
    ; SELECT-NEXT: %reg:gpr64 = COPY $x0
    ; SELECT-NEXT: %cst:gpr64 = MOVi64imm 9223372036854775807
    ; SELECT-NEXT: [[SUBSXrr:%[0-9]+]]:gpr64 = SUBSXrr %reg, %cst, implicit-def $nzcv
    ; SELECT-NEXT: %cmp:gpr32 = CSINCWr $wzr, $wzr, 12, implicit $nzcv
    ; SELECT-NEXT: $w0 = COPY %cmp
    ; SELECT-NEXT: RET_ReallyLR implicit $w0
    %reg:_(s64) = COPY $x0
    %cst:_(s64) = G_CONSTANT i64 9223372036854775807
    %cmp:_(s32) = G_ICMP intpred(sle), %reg(s64), %cst
    $w0 = COPY %cmp(s32)
    RET_ReallyLR implicit $w0

...
---
name:            no_opt_zero
legalized:       true
tracksRegLiveness: true
body:             |
  bb.0:
    liveins: $x0

    ; The cmp should not change during the lowering pass.
    ;
    ; This is an unsigned comparison, so when the constant is 0, the following
    ; does not hold:
    ;
    ; x slt c => x sle c - 1
    ; x sge c => x sgt c - 1

    ; LOWER-LABEL: name: no_opt_zero
    ; LOWER: liveins: $x0
    ; LOWER-NEXT: {{  $}}
    ; LOWER-NEXT: %reg:_(s64) = COPY $x0
    ; LOWER-NEXT: %cst:_(s64) = G_CONSTANT i64 0
    ; LOWER-NEXT: %cmp:_(s32) = G_ICMP intpred(ult), %reg(s64), %cst
    ; LOWER-NEXT: $w0 = COPY %cmp(s32)
    ; LOWER-NEXT: RET_ReallyLR implicit $w0
    ; SELECT-LABEL: name: no_opt_zero
    ; SELECT: liveins: $x0
    ; SELECT-NEXT: {{  $}}
    ; SELECT-NEXT: %reg:gpr64sp = COPY $x0
    ; SELECT-NEXT: [[SUBSXri:%[0-9]+]]:gpr64 = SUBSXri %reg, 0, 0, implicit-def $nzcv
    ; SELECT-NEXT: %cmp:gpr32 = CSINCWr $wzr, $wzr, 2, implicit $nzcv
    ; SELECT-NEXT: $w0 = COPY %cmp
    ; SELECT-NEXT: RET_ReallyLR implicit $w0
    %reg:_(s64) = COPY $x0
    %cst:_(s64) = G_CONSTANT i64 0
    %cmp:_(s32) = G_ICMP intpred(ult), %reg(s64), %cst
    $w0 = COPY %cmp(s32)
    RET_ReallyLR implicit $w0

...
---
name:            cmp_and_select
legalized:       true
tracksRegLiveness: true
body:             |
  bb.0:
    liveins: $w0, $w1
    ; The G_ICMP is optimized here to be a slt comparison by adding 1 to the
    ; constant. So, the CSELWr should use the predicate code 11, rather than
    ; 13.

    ; LOWER-LABEL: name: cmp_and_select
    ; LOWER: liveins: $w0, $w1
    ; LOWER-NEXT: {{  $}}
    ; LOWER-NEXT: %reg0:_(s32) = COPY $w0
    ; LOWER-NEXT: %reg1:_(s32) = COPY $w1
    ; LOWER-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
    ; LOWER-NEXT: %cmp:_(s32) = G_ICMP intpred(slt), %reg0(s32), [[C]]
    ; LOWER-NEXT: %select:_(s32) = G_SELECT %cmp(s32), %reg0, %reg1
    ; LOWER-NEXT: $w0 = COPY %select(s32)
    ; LOWER-NEXT: RET_ReallyLR implicit $w0
    ; SELECT-LABEL: name: cmp_and_select
    ; SELECT: liveins: $w0, $w1
    ; SELECT-NEXT: {{  $}}
    ; SELECT-NEXT: %reg0:gpr32common = COPY $w0
    ; SELECT-NEXT: %reg1:gpr32 = COPY $w1
    ; SELECT-NEXT: [[SUBSWri:%[0-9]+]]:gpr32 = SUBSWri %reg0, 0, 0, implicit-def $nzcv
    ; SELECT-NEXT: %select:gpr32 = CSELWr %reg0, %reg1, 11, implicit $nzcv
    ; SELECT-NEXT: $w0 = COPY %select
    ; SELECT-NEXT: RET_ReallyLR implicit $w0
    %reg0:_(s32) = COPY $w0
    %reg1:_(s32) = COPY $w1
    %cst:_(s32) = G_CONSTANT i32 -1
    %cmp:_(s32) = G_ICMP intpred(sle), %reg0(s32), %cst
    %select:_(s32) = G_SELECT %cmp, %reg0, %reg1
    $w0 = COPY %select(s32)
    RET_ReallyLR implicit $w0

...
---
name:             andsxri
legalized: true
tracksRegLiveness: true
body:             |
  bb.0:
    liveins: $x0
    ; Show that we can select a tst/ands by optimizing the G_ICMP in the
    ; lowering phase.

    ; LOWER-LABEL: name: andsxri
    ; LOWER: liveins: $x0
    ; LOWER-NEXT: {{  $}}
    ; LOWER-NEXT: %reg0:gpr(s64) = COPY $x0
    ; LOWER-NEXT: %bit:gpr(s64) = G_CONSTANT i64 8
    ; LOWER-NEXT: %and:gpr(s64) = G_AND %reg0, %bit
    ; LOWER-NEXT: [[C:%[0-9]+]]:gpr(s64) = G_CONSTANT i64 0
    ; LOWER-NEXT: %cmp:gpr(s32) = G_ICMP intpred(sge), %and(s64), [[C]]
    ; LOWER-NEXT: $w0 = COPY %cmp(s32)
    ; LOWER-NEXT: RET_ReallyLR implicit $w0
    ; SELECT-LABEL: name: andsxri
    ; SELECT: liveins: $x0
    ; SELECT-NEXT: {{  $}}
    ; SELECT-NEXT: %reg0:gpr64 = COPY $x0
    ; SELECT-NEXT: [[ANDSXri:%[0-9]+]]:gpr64 = ANDSXri %reg0, 8000, implicit-def $nzcv
    ; SELECT-NEXT: %cmp:gpr32 = CSINCWr $wzr, $wzr, 11, implicit $nzcv
    ; SELECT-NEXT: $w0 = COPY %cmp
    ; SELECT-NEXT: RET_ReallyLR implicit $w0
    %reg0:gpr(s64) = COPY $x0
    %bit:gpr(s64) = G_CONSTANT i64 8
    %and:gpr(s64) = G_AND %reg0, %bit
    %cst:gpr(s64) = G_CONSTANT i64 -1
    %cmp:gpr(s32) = G_ICMP intpred(sgt), %and(s64), %cst
    $w0 = COPY %cmp(s32)
    RET_ReallyLR implicit $w0