# 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