diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index a817ed5f0e917..132d9ade2d135 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -3330,6 +3330,14 @@ static bool isLegalArithImmed(uint64_t C) { return IsLegal; } +bool isLegalCmpImmed(APInt C) { + if (C.isMinSignedValue()) + return false; + // Works for negative immediates too, as it can be written as an ADDS + // instruction with a negated immediate. + return isLegalArithImmed(C.abs().getZExtValue()); +} + static bool cannotBeIntMin(SDValue CheckedVal, SelectionDAG &DAG) { KnownBits KnownSrc = DAG.computeKnownBits(CheckedVal); return !KnownSrc.getSignedMinValue().isMinSignedValue(); @@ -3760,53 +3768,50 @@ static SDValue getAArch64Cmp(SDValue LHS, SDValue RHS, ISD::CondCode CC, const SDLoc &dl) { if (ConstantSDNode *RHSC = dyn_cast(RHS.getNode())) { EVT VT = RHS.getValueType(); - uint64_t C = RHSC->getZExtValue(); - if (!isLegalArithImmed(C)) { + APInt C = RHSC->getAPIntValue(); + if (!isLegalCmpImmed(C)) { // Constant does not fit, try adjusting it by one? switch (CC) { default: break; case ISD::SETLT: case ISD::SETGE: - if ((VT == MVT::i32 && C != 0x80000000 && - isLegalArithImmed((uint32_t)(C - 1))) || - (VT == MVT::i64 && C != 0x80000000ULL && - isLegalArithImmed(C - 1ULL))) { - CC = (CC == ISD::SETLT) ? ISD::SETLE : ISD::SETGT; - C = (VT == MVT::i32) ? (uint32_t)(C - 1) : C - 1; - RHS = DAG.getConstant(C, dl, VT); + if (!C.isMinSignedValue()) { + APInt CMinusOne = C - 1; + if (isLegalCmpImmed(CMinusOne)) { + CC = (CC == ISD::SETLT) ? ISD::SETLE : ISD::SETGT; + RHS = DAG.getConstant(CMinusOne, dl, VT); + } } break; case ISD::SETULT: case ISD::SETUGE: - if ((VT == MVT::i32 && C != 0 && - isLegalArithImmed((uint32_t)(C - 1))) || - (VT == MVT::i64 && C != 0ULL && isLegalArithImmed(C - 1ULL))) { - CC = (CC == ISD::SETULT) ? ISD::SETULE : ISD::SETUGT; - C = (VT == MVT::i32) ? (uint32_t)(C - 1) : C - 1; - RHS = DAG.getConstant(C, dl, VT); + if (!C.isZero()) { + APInt CMinusOne = C - 1; + if (isLegalCmpImmed(CMinusOne)) { + CC = (CC == ISD::SETULT) ? ISD::SETULE : ISD::SETUGT; + RHS = DAG.getConstant(CMinusOne, dl, VT); + } } break; case ISD::SETLE: case ISD::SETGT: - if ((VT == MVT::i32 && C != INT32_MAX && - isLegalArithImmed((uint32_t)(C + 1))) || - (VT == MVT::i64 && C != INT64_MAX && - isLegalArithImmed(C + 1ULL))) { - CC = (CC == ISD::SETLE) ? ISD::SETLT : ISD::SETGE; - C = (VT == MVT::i32) ? (uint32_t)(C + 1) : C + 1; - RHS = DAG.getConstant(C, dl, VT); + if (!C.isMaxSignedValue()) { + APInt CPlusOne = C + 1; + if (isLegalCmpImmed(CPlusOne)) { + CC = (CC == ISD::SETLE) ? ISD::SETLT : ISD::SETGE; + RHS = DAG.getConstant(CPlusOne, dl, VT); + } } break; case ISD::SETULE: case ISD::SETUGT: - if ((VT == MVT::i32 && C != UINT32_MAX && - isLegalArithImmed((uint32_t)(C + 1))) || - (VT == MVT::i64 && C != UINT64_MAX && - isLegalArithImmed(C + 1ULL))) { - CC = (CC == ISD::SETULE) ? ISD::SETULT : ISD::SETUGE; - C = (VT == MVT::i32) ? (uint32_t)(C + 1) : C + 1; - RHS = DAG.getConstant(C, dl, VT); + if (!C.isAllOnes()) { + APInt CPlusOne = C + 1; + if (isLegalCmpImmed(CPlusOne)) { + CC = (CC == ISD::SETULE) ? ISD::SETULT : ISD::SETUGE; + RHS = DAG.getConstant(CPlusOne, dl, VT); + } } break; } @@ -3823,8 +3828,7 @@ static SDValue getAArch64Cmp(SDValue LHS, SDValue RHS, ISD::CondCode CC, // cmp w13, w12 // can be turned into: // cmp w12, w11, lsl #1 - if (!isa(RHS) || - !isLegalArithImmed(RHS->getAsAPIntVal().abs().getZExtValue())) { + if (!isa(RHS) || !isLegalCmpImmed(RHS->getAsAPIntVal())) { bool LHSIsCMN = isCMN(LHS, CC, DAG); bool RHSIsCMN = isCMN(RHS, CC, DAG); SDValue TheLHS = LHSIsCMN ? LHS.getOperand(1) : LHS; @@ -17353,17 +17357,10 @@ LLT AArch64TargetLowering::getOptimalMemOpLLT( // 12-bit optionally shifted immediates are legal for adds. bool AArch64TargetLowering::isLegalAddImmediate(int64_t Immed) const { if (Immed == std::numeric_limits::min()) { - LLVM_DEBUG(dbgs() << "Illegal add imm " << Immed - << ": avoid UB for INT64_MIN\n"); return false; } // Same encoding for add/sub, just flip the sign. - Immed = std::abs(Immed); - bool IsLegal = ((Immed >> 12) == 0 || - ((Immed & 0xfff) == 0 && Immed >> 24 == 0)); - LLVM_DEBUG(dbgs() << "Is " << Immed - << " legal add imm: " << (IsLegal ? "yes" : "no") << "\n"); - return IsLegal; + return isLegalArithImmed((uint64_t)std::abs(Immed)); } bool AArch64TargetLowering::isLegalAddScalableImmediate(int64_t Imm) const { diff --git a/llvm/test/CodeGen/AArch64/arm64-csel.ll b/llvm/test/CodeGen/AArch64/arm64-csel.ll index 1cf99d1b31a8b..69fad57a683ac 100644 --- a/llvm/test/CodeGen/AArch64/arm64-csel.ll +++ b/llvm/test/CodeGen/AArch64/arm64-csel.ll @@ -100,9 +100,8 @@ define i32 @foo7(i32 %a, i32 %b) nounwind { ; CHECK-NEXT: subs w8, w0, w1 ; CHECK-NEXT: cneg w9, w8, mi ; CHECK-NEXT: cmn w8, #1 -; CHECK-NEXT: csel w10, w9, w0, lt -; CHECK-NEXT: cmp w8, #0 -; CHECK-NEXT: csel w0, w10, w9, ge +; CHECK-NEXT: csel w8, w9, w0, lt +; CHECK-NEXT: csel w0, w8, w9, gt ; CHECK-NEXT: ret entry: %sub = sub nsw i32 %a, %b diff --git a/llvm/test/CodeGen/AArch64/check-sign-bit-before-extension.ll b/llvm/test/CodeGen/AArch64/check-sign-bit-before-extension.ll index 8fbed8bfdb3fd..1d60929f2b94c 100644 --- a/llvm/test/CodeGen/AArch64/check-sign-bit-before-extension.ll +++ b/llvm/test/CodeGen/AArch64/check-sign-bit-before-extension.ll @@ -14,8 +14,8 @@ define i32 @f_i8_sign_extend_inreg(i8 %in, i32 %a, i32 %b) nounwind { ; CHECK-LABEL: f_i8_sign_extend_inreg: ; CHECK: // %bb.0: // %entry ; CHECK-NEXT: sxtb w8, w0 -; CHECK-NEXT: cmp w8, #0 -; CHECK-NEXT: csel w8, w1, w2, ge +; CHECK-NEXT: cmn w8, #1 +; CHECK-NEXT: csel w8, w1, w2, gt ; CHECK-NEXT: add w0, w8, w0, uxtb ; CHECK-NEXT: ret entry: @@ -36,8 +36,8 @@ define i32 @f_i16_sign_extend_inreg(i16 %in, i32 %a, i32 %b) nounwind { ; CHECK-LABEL: f_i16_sign_extend_inreg: ; CHECK: // %bb.0: // %entry ; CHECK-NEXT: sxth w8, w0 -; CHECK-NEXT: cmp w8, #0 -; CHECK-NEXT: csel w8, w1, w2, ge +; CHECK-NEXT: cmn w8, #1 +; CHECK-NEXT: csel w8, w1, w2, gt ; CHECK-NEXT: add w0, w8, w0, uxth ; CHECK-NEXT: ret entry: @@ -57,8 +57,8 @@ B: define i64 @f_i32_sign_extend_inreg(i32 %in, i64 %a, i64 %b) nounwind { ; CHECK-LABEL: f_i32_sign_extend_inreg: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: cmp w0, #0 -; CHECK-NEXT: csel x8, x1, x2, ge +; CHECK-NEXT: cmn w0, #1 +; CHECK-NEXT: csel x8, x1, x2, gt ; CHECK-NEXT: add x0, x8, w0, uxtw ; CHECK-NEXT: ret entry: @@ -145,8 +145,8 @@ define i64 @f_i32_sign_extend_i64(i32 %in, i64 %a, i64 %b) nounwind { ; CHECK: // %bb.0: // %entry ; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0 ; CHECK-NEXT: sxtw x8, w0 -; CHECK-NEXT: cmp x8, #0 -; CHECK-NEXT: csel x8, x1, x2, ge +; CHECK-NEXT: cmn x8, #1 +; CHECK-NEXT: csel x8, x1, x2, gt ; CHECK-NEXT: add x0, x8, w0, uxtw ; CHECK-NEXT: ret entry: diff --git a/llvm/test/CodeGen/AArch64/cmp-to-cmn.ll b/llvm/test/CodeGen/AArch64/cmp-to-cmn.ll index e87d43161a895..c5fd9b63cce97 100644 --- a/llvm/test/CodeGen/AArch64/cmp-to-cmn.ll +++ b/llvm/test/CodeGen/AArch64/cmp-to-cmn.ll @@ -430,3 +430,175 @@ entry: %cmp = icmp ne i32 %conv, %add ret i1 %cmp } + +define i1 @cmn_large_imm(i32 %a) { +; CHECK-LABEL: cmn_large_imm: +; CHECK: // %bb.0: +; CHECK-NEXT: mov w8, #64765 // =0xfcfd +; CHECK-NEXT: movk w8, #64764, lsl #16 +; CHECK-NEXT: cmp w0, w8 +; CHECK-NEXT: cset w0, gt +; CHECK-NEXT: ret + %cmp = icmp sgt i32 %a, -50529027 + ret i1 %cmp +} + +define i1 @almost_immediate_neg_slt(i32 %x) { +; CHECK-LABEL: almost_immediate_neg_slt: +; CHECK: // %bb.0: +; CHECK-NEXT: cmn w0, #4079, lsl #12 // =16707584 +; CHECK-NEXT: cset w0, le +; CHECK-NEXT: ret + %cmp = icmp slt i32 %x, -16707583 + ret i1 %cmp +} + +define i1 @almost_immediate_neg_slt_64(i64 %x) { +; CHECK-LABEL: almost_immediate_neg_slt_64: +; CHECK: // %bb.0: +; CHECK-NEXT: cmn x0, #4079, lsl #12 // =16707584 +; CHECK-NEXT: cset w0, le +; CHECK-NEXT: ret + %cmp = icmp slt i64 %x, -16707583 + ret i1 %cmp +} + +define i1 @almost_immediate_neg_sge(i32 %x) { +; CHECK-LABEL: almost_immediate_neg_sge: +; CHECK: // %bb.0: +; CHECK-NEXT: cmn w0, #4079, lsl #12 // =16707584 +; CHECK-NEXT: cset w0, gt +; CHECK-NEXT: ret + %cmp = icmp sge i32 %x, -16707583 + ret i1 %cmp +} + +define i1 @almost_immediate_neg_sge_64(i64 %x) { +; CHECK-LABEL: almost_immediate_neg_sge_64: +; CHECK: // %bb.0: +; CHECK-NEXT: cmn x0, #4079, lsl #12 // =16707584 +; CHECK-NEXT: cset w0, gt +; CHECK-NEXT: ret + %cmp = icmp sge i64 %x, -16707583 + ret i1 %cmp +} + +define i1 @almost_immediate_neg_uge(i32 %x) { +; CHECK-LABEL: almost_immediate_neg_uge: +; CHECK: // %bb.0: +; CHECK-NEXT: cmn w0, #4079, lsl #12 // =16707584 +; CHECK-NEXT: cset w0, hi +; CHECK-NEXT: ret + %cmp = icmp uge i32 %x, -16707583 + ret i1 %cmp +} + +define i1 @almost_immediate_neg_uge_64(i64 %x) { +; CHECK-LABEL: almost_immediate_neg_uge_64: +; CHECK: // %bb.0: +; CHECK-NEXT: cmn x0, #4079, lsl #12 // =16707584 +; CHECK-NEXT: cset w0, hi +; CHECK-NEXT: ret + %cmp = icmp uge i64 %x, -16707583 + ret i1 %cmp +} + +define i1 @almost_immediate_neg_ult(i32 %x) { +; CHECK-LABEL: almost_immediate_neg_ult: +; CHECK: // %bb.0: +; CHECK-NEXT: cmn w0, #4079, lsl #12 // =16707584 +; CHECK-NEXT: cset w0, ls +; CHECK-NEXT: ret + %cmp = icmp ult i32 %x, -16707583 + ret i1 %cmp +} + +define i1 @almost_immediate_neg_ult_64(i64 %x) { +; CHECK-LABEL: almost_immediate_neg_ult_64: +; CHECK: // %bb.0: +; CHECK-NEXT: cmn x0, #4079, lsl #12 // =16707584 +; CHECK-NEXT: cset w0, ls +; CHECK-NEXT: ret + %cmp = icmp ult i64 %x, -16707583 + ret i1 %cmp +} + +define i1 @almost_immediate_neg_sle(i32 %x) { +; CHECK-LABEL: almost_immediate_neg_sle: +; CHECK: // %bb.0: +; CHECK-NEXT: cmn w0, #4095, lsl #12 // =16773120 +; CHECK-NEXT: cset w0, lt +; CHECK-NEXT: ret + %cmp = icmp sle i32 %x, -16773121 + ret i1 %cmp +} + +define i1 @almost_immediate_neg_sle_64(i64 %x) { +; CHECK-LABEL: almost_immediate_neg_sle_64: +; CHECK: // %bb.0: +; CHECK-NEXT: cmn x0, #4095, lsl #12 // =16773120 +; CHECK-NEXT: cset w0, lt +; CHECK-NEXT: ret + %cmp = icmp sle i64 %x, -16773121 + ret i1 %cmp +} + +define i1 @almost_immediate_neg_sgt(i32 %x) { +; CHECK-LABEL: almost_immediate_neg_sgt: +; CHECK: // %bb.0: +; CHECK-NEXT: cmn w0, #4095, lsl #12 // =16773120 +; CHECK-NEXT: cset w0, ge +; CHECK-NEXT: ret + %cmp = icmp sgt i32 %x, -16773121 + ret i1 %cmp +} + +define i1 @almost_immediate_neg_sgt_64(i64 %x) { +; CHECK-LABEL: almost_immediate_neg_sgt_64: +; CHECK: // %bb.0: +; CHECK-NEXT: cmn x0, #4095, lsl #12 // =16773120 +; CHECK-NEXT: cset w0, ge +; CHECK-NEXT: ret + %cmp = icmp sgt i64 %x, -16773121 + ret i1 %cmp +} + +define i1 @almost_immediate_neg_ule(i32 %x) { +; CHECK-LABEL: almost_immediate_neg_ule: +; CHECK: // %bb.0: +; CHECK-NEXT: cmn w0, #4095, lsl #12 // =16773120 +; CHECK-NEXT: cset w0, lo +; CHECK-NEXT: ret + %cmp = icmp ule i32 %x, -16773121 + ret i1 %cmp +} + +define i1 @almost_immediate_neg_ule_64(i64 %x) { +; CHECK-LABEL: almost_immediate_neg_ule_64: +; CHECK: // %bb.0: +; CHECK-NEXT: cmn x0, #4095, lsl #12 // =16773120 +; CHECK-NEXT: cset w0, lo +; CHECK-NEXT: ret + %cmp = icmp ule i64 %x, -16773121 + ret i1 %cmp +} + +define i1 @almost_immediate_neg_ugt(i32 %x) { +; CHECK-LABEL: almost_immediate_neg_ugt: +; CHECK: // %bb.0: +; CHECK-NEXT: cmn w0, #4095, lsl #12 // =16773120 +; CHECK-NEXT: cset w0, hs +; CHECK-NEXT: ret + %cmp = icmp ugt i32 %x, -16773121 + ret i1 %cmp +} + +define i1 @almost_immediate_neg_ugt_64(i64 %x) { +; CHECK-LABEL: almost_immediate_neg_ugt_64: +; CHECK: // %bb.0: +; CHECK-NEXT: cmn x0, #4095, lsl #12 // =16773120 +; CHECK-NEXT: cset w0, hs +; CHECK-NEXT: ret + %cmp = icmp ugt i64 %x, -16773121 + ret i1 %cmp +} diff --git a/llvm/test/CodeGen/AArch64/csel-subs-swapped.ll b/llvm/test/CodeGen/AArch64/csel-subs-swapped.ll index 3971da27cdddc..7d2c7854baf3d 100644 --- a/llvm/test/CodeGen/AArch64/csel-subs-swapped.ll +++ b/llvm/test/CodeGen/AArch64/csel-subs-swapped.ll @@ -44,10 +44,8 @@ define i32 @sge_i32(i32 %x) { ; CHECK-LABEL: sge_i32: ; CHECK: // %bb.0: ; CHECK-NEXT: mov w8, #-2097152 // =0xffe00000 -; CHECK-NEXT: mov w9, #-2097153 // =0xffdfffff -; CHECK-NEXT: sub w8, w8, w0 -; CHECK-NEXT: cmp w0, w9 -; CHECK-NEXT: csel w0, w0, w8, gt +; CHECK-NEXT: subs w8, w8, w0 +; CHECK-NEXT: csel w0, w0, w8, le ; CHECK-NEXT: ret %cmp = icmp sge i32 %x, -2097152 %sub = sub i32 -2097152, %x @@ -72,10 +70,8 @@ define i32 @sle_i32(i32 %x) { ; CHECK-LABEL: sle_i32: ; CHECK: // %bb.0: ; CHECK-NEXT: mov w8, #-2097152 // =0xffe00000 -; CHECK-NEXT: mov w9, #-2097151 // =0xffe00001 -; CHECK-NEXT: sub w8, w8, w0 -; CHECK-NEXT: cmp w0, w9 -; CHECK-NEXT: csel w0, w0, w8, lt +; CHECK-NEXT: subs w8, w8, w0 +; CHECK-NEXT: csel w0, w0, w8, ge ; CHECK-NEXT: ret %cmp = icmp sle i32 %x, -2097152 %sub = sub i32 -2097152, %x @@ -128,10 +124,8 @@ define i32 @ule_i32(i32 %x) { ; CHECK-LABEL: ule_i32: ; CHECK: // %bb.0: ; CHECK-NEXT: mov w8, #-2097152 // =0xffe00000 -; CHECK-NEXT: mov w9, #-2097151 // =0xffe00001 -; CHECK-NEXT: sub w8, w8, w0 -; CHECK-NEXT: cmp w0, w9 -; CHECK-NEXT: csel w0, w0, w8, lo +; CHECK-NEXT: subs w8, w8, w0 +; CHECK-NEXT: csel w0, w0, w8, hs ; CHECK-NEXT: ret %cmp = icmp ule i32 %x, -2097152 %sub = sub i32 -2097152, %x diff --git a/llvm/test/CodeGen/AArch64/fptosi-sat-scalar.ll b/llvm/test/CodeGen/AArch64/fptosi-sat-scalar.ll index 39e2db3a52d2c..b766da2a3a829 100644 --- a/llvm/test/CodeGen/AArch64/fptosi-sat-scalar.ll +++ b/llvm/test/CodeGen/AArch64/fptosi-sat-scalar.ll @@ -23,8 +23,9 @@ define i1 @test_signed_i1_f32(float %f) nounwind { ; CHECK-SD-LABEL: test_signed_i1_f32: ; CHECK-SD: // %bb.0: ; CHECK-SD-NEXT: fcvtzs w8, s0 -; CHECK-SD-NEXT: ands w8, w8, w8, asr #31 -; CHECK-SD-NEXT: csinv w8, w8, wzr, ge +; CHECK-SD-NEXT: and w8, w8, w8, asr #31 +; CHECK-SD-NEXT: cmn w8, #1 +; CHECK-SD-NEXT: csinv w8, w8, wzr, gt ; CHECK-SD-NEXT: and w0, w8, #0x1 ; CHECK-SD-NEXT: ret ; @@ -268,8 +269,9 @@ define i1 @test_signed_i1_f64(double %f) nounwind { ; CHECK-SD-LABEL: test_signed_i1_f64: ; CHECK-SD: // %bb.0: ; CHECK-SD-NEXT: fcvtzs w8, d0 -; CHECK-SD-NEXT: ands w8, w8, w8, asr #31 -; CHECK-SD-NEXT: csinv w8, w8, wzr, ge +; CHECK-SD-NEXT: and w8, w8, w8, asr #31 +; CHECK-SD-NEXT: cmn w8, #1 +; CHECK-SD-NEXT: csinv w8, w8, wzr, gt ; CHECK-SD-NEXT: and w0, w8, #0x1 ; CHECK-SD-NEXT: ret ; @@ -518,16 +520,18 @@ define i1 @test_signed_i1_f16(half %f) nounwind { ; CHECK-SD-CVT: // %bb.0: ; CHECK-SD-CVT-NEXT: fcvt s0, h0 ; CHECK-SD-CVT-NEXT: fcvtzs w8, s0 -; CHECK-SD-CVT-NEXT: ands w8, w8, w8, asr #31 -; CHECK-SD-CVT-NEXT: csinv w8, w8, wzr, ge +; CHECK-SD-CVT-NEXT: and w8, w8, w8, asr #31 +; CHECK-SD-CVT-NEXT: cmn w8, #1 +; CHECK-SD-CVT-NEXT: csinv w8, w8, wzr, gt ; CHECK-SD-CVT-NEXT: and w0, w8, #0x1 ; CHECK-SD-CVT-NEXT: ret ; ; CHECK-SD-FP16-LABEL: test_signed_i1_f16: ; CHECK-SD-FP16: // %bb.0: ; CHECK-SD-FP16-NEXT: fcvtzs w8, h0 -; CHECK-SD-FP16-NEXT: ands w8, w8, w8, asr #31 -; CHECK-SD-FP16-NEXT: csinv w8, w8, wzr, ge +; CHECK-SD-FP16-NEXT: and w8, w8, w8, asr #31 +; CHECK-SD-FP16-NEXT: cmn w8, #1 +; CHECK-SD-FP16-NEXT: csinv w8, w8, wzr, gt ; CHECK-SD-FP16-NEXT: and w0, w8, #0x1 ; CHECK-SD-FP16-NEXT: ret ; diff --git a/llvm/test/CodeGen/AArch64/fptosi-sat-vector.ll b/llvm/test/CodeGen/AArch64/fptosi-sat-vector.ll index a33b1ef569fc3..3d7bcf6409438 100644 --- a/llvm/test/CodeGen/AArch64/fptosi-sat-vector.ll +++ b/llvm/test/CodeGen/AArch64/fptosi-sat-vector.ll @@ -2371,10 +2371,12 @@ define <2 x i1> @test_signed_v2f64_v2i1(<2 x double> %f) { ; CHECK-SD-NEXT: mov d1, v0.d[1] ; CHECK-SD-NEXT: fcvtzs w9, d0 ; CHECK-SD-NEXT: fcvtzs w8, d1 -; CHECK-SD-NEXT: ands w8, w8, w8, asr #31 -; CHECK-SD-NEXT: csinv w8, w8, wzr, ge -; CHECK-SD-NEXT: ands w9, w9, w9, asr #31 -; CHECK-SD-NEXT: csinv w9, w9, wzr, ge +; CHECK-SD-NEXT: and w9, w9, w9, asr #31 +; CHECK-SD-NEXT: and w8, w8, w8, asr #31 +; CHECK-SD-NEXT: cmn w8, #1 +; CHECK-SD-NEXT: csinv w8, w8, wzr, gt +; CHECK-SD-NEXT: cmn w9, #1 +; CHECK-SD-NEXT: csinv w9, w9, wzr, gt ; CHECK-SD-NEXT: fmov s0, w9 ; CHECK-SD-NEXT: mov v0.s[1], w8 ; CHECK-SD-NEXT: // kill: def $d0 killed $d0 killed $q0 diff --git a/llvm/test/CodeGen/AArch64/select-constant-xor.ll b/llvm/test/CodeGen/AArch64/select-constant-xor.ll index 6803411f66896..fe9a2c0fad830 100644 --- a/llvm/test/CodeGen/AArch64/select-constant-xor.ll +++ b/llvm/test/CodeGen/AArch64/select-constant-xor.ll @@ -168,8 +168,8 @@ define i32 @icmpasreq(i32 %input, i32 %a, i32 %b) { define i32 @icmpasrne(i32 %input, i32 %a, i32 %b) { ; CHECK-SD-LABEL: icmpasrne: ; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: cmp w0, #0 -; CHECK-SD-NEXT: csel w0, w1, w2, ge +; CHECK-SD-NEXT: cmn w0, #1 +; CHECK-SD-NEXT: csel w0, w1, w2, gt ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: icmpasrne: diff --git a/llvm/test/CodeGen/AArch64/signbit-shift.ll b/llvm/test/CodeGen/AArch64/signbit-shift.ll index 253ea1cab91fb..0e6da326a31f4 100644 --- a/llvm/test/CodeGen/AArch64/signbit-shift.ll +++ b/llvm/test/CodeGen/AArch64/signbit-shift.ll @@ -43,8 +43,8 @@ define i32 @sel_ifpos_tval_bigger(i32 %x) { ; CHECK-LABEL: sel_ifpos_tval_bigger: ; CHECK: // %bb.0: ; CHECK-NEXT: mov w8, #41 // =0x29 -; CHECK-NEXT: cmp w0, #0 -; CHECK-NEXT: cinc w0, w8, ge +; CHECK-NEXT: cmn w0, #1 +; CHECK-NEXT: cinc w0, w8, gt ; CHECK-NEXT: ret %c = icmp sgt i32 %x, -1 %r = select i1 %c, i32 42, i32 41 @@ -91,8 +91,8 @@ define i32 @sel_ifpos_fval_bigger(i32 %x) { ; CHECK-LABEL: sel_ifpos_fval_bigger: ; CHECK: // %bb.0: ; CHECK-NEXT: mov w8, #41 // =0x29 -; CHECK-NEXT: cmp w0, #0 -; CHECK-NEXT: cinc w0, w8, lt +; CHECK-NEXT: cmn w0, #1 +; CHECK-NEXT: cinc w0, w8, le ; CHECK-NEXT: ret %c = icmp sgt i32 %x, -1 %r = select i1 %c, i32 41, i32 42 diff --git a/llvm/test/CodeGen/AArch64/signbit-test.ll b/llvm/test/CodeGen/AArch64/signbit-test.ll index f5eaf80cf7f8d..c74a934ee09d8 100644 --- a/llvm/test/CodeGen/AArch64/signbit-test.ll +++ b/llvm/test/CodeGen/AArch64/signbit-test.ll @@ -4,9 +4,9 @@ define i64 @test_clear_mask_i64_i32(i64 %x) nounwind { ; CHECK-LABEL: test_clear_mask_i64_i32: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: mov w8, #42 -; CHECK-NEXT: cmp w0, #0 -; CHECK-NEXT: csel x0, x8, x0, ge +; CHECK-NEXT: mov w8, #42 // =0x2a +; CHECK-NEXT: cmn w0, #1 +; CHECK-NEXT: csel x0, x8, x0, gt ; CHECK-NEXT: ret entry: %a = and i64 %x, 2147483648 @@ -22,7 +22,7 @@ f: define i64 @test_set_mask_i64_i32(i64 %x) nounwind { ; CHECK-LABEL: test_set_mask_i64_i32: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: mov w8, #42 +; CHECK-NEXT: mov w8, #42 // =0x2a ; CHECK-NEXT: tst x0, #0x80000000 ; CHECK-NEXT: csel x0, x8, x0, ne ; CHECK-NEXT: ret @@ -40,7 +40,7 @@ f: define i64 @test_clear_mask_i64_i16(i64 %x) nounwind { ; CHECK-LABEL: test_clear_mask_i64_i16: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: mov w8, #42 +; CHECK-NEXT: mov w8, #42 // =0x2a ; CHECK-NEXT: tst x0, #0x8000 ; CHECK-NEXT: csel x0, x8, x0, eq ; CHECK-NEXT: ret @@ -58,7 +58,7 @@ f: define i64 @test_set_mask_i64_i16(i64 %x) nounwind { ; CHECK-LABEL: test_set_mask_i64_i16: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: mov w8, #42 +; CHECK-NEXT: mov w8, #42 // =0x2a ; CHECK-NEXT: tst x0, #0x8000 ; CHECK-NEXT: csel x0, x8, x0, ne ; CHECK-NEXT: ret @@ -76,7 +76,7 @@ f: define i64 @test_clear_mask_i64_i8(i64 %x) nounwind { ; CHECK-LABEL: test_clear_mask_i64_i8: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: mov w8, #42 +; CHECK-NEXT: mov w8, #42 // =0x2a ; CHECK-NEXT: tst x0, #0x80 ; CHECK-NEXT: csel x0, x8, x0, eq ; CHECK-NEXT: ret @@ -94,7 +94,7 @@ f: define i64 @test_set_mask_i64_i8(i64 %x) nounwind { ; CHECK-LABEL: test_set_mask_i64_i8: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: mov w8, #42 +; CHECK-NEXT: mov w8, #42 // =0x2a ; CHECK-NEXT: tst x0, #0x80 ; CHECK-NEXT: csel x0, x8, x0, ne ; CHECK-NEXT: ret @@ -112,7 +112,7 @@ f: define i32 @test_clear_mask_i32_i16(i32 %x) nounwind { ; CHECK-LABEL: test_clear_mask_i32_i16: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: mov w8, #42 +; CHECK-NEXT: mov w8, #42 // =0x2a ; CHECK-NEXT: tst w0, #0x8000 ; CHECK-NEXT: csel w0, w8, w0, eq ; CHECK-NEXT: ret @@ -130,7 +130,7 @@ f: define i32 @test_set_mask_i32_i16(i32 %x) nounwind { ; CHECK-LABEL: test_set_mask_i32_i16: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: mov w8, #42 +; CHECK-NEXT: mov w8, #42 // =0x2a ; CHECK-NEXT: tst w0, #0x8000 ; CHECK-NEXT: csel w0, w8, w0, ne ; CHECK-NEXT: ret @@ -148,7 +148,7 @@ f: define i32 @test_clear_mask_i32_i8(i32 %x) nounwind { ; CHECK-LABEL: test_clear_mask_i32_i8: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: mov w8, #42 +; CHECK-NEXT: mov w8, #42 // =0x2a ; CHECK-NEXT: tst w0, #0x80 ; CHECK-NEXT: csel w0, w8, w0, eq ; CHECK-NEXT: ret @@ -166,7 +166,7 @@ f: define i32 @test_set_mask_i32_i8(i32 %x) nounwind { ; CHECK-LABEL: test_set_mask_i32_i8: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: mov w8, #42 +; CHECK-NEXT: mov w8, #42 // =0x2a ; CHECK-NEXT: tst w0, #0x80 ; CHECK-NEXT: csel w0, w8, w0, ne ; CHECK-NEXT: ret @@ -184,7 +184,7 @@ f: define i16 @test_clear_mask_i16_i8(i16 %x) nounwind { ; CHECK-LABEL: test_clear_mask_i16_i8: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: mov w8, #42 +; CHECK-NEXT: mov w8, #42 // =0x2a ; CHECK-NEXT: tst w0, #0x80 ; CHECK-NEXT: csel w0, w8, w0, eq ; CHECK-NEXT: ret @@ -202,7 +202,7 @@ f: define i16 @test_set_mask_i16_i8(i16 %x) nounwind { ; CHECK-LABEL: test_set_mask_i16_i8: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: mov w8, #42 +; CHECK-NEXT: mov w8, #42 // =0x2a ; CHECK-NEXT: tst w0, #0x80 ; CHECK-NEXT: csel w0, w8, w0, ne ; CHECK-NEXT: ret @@ -220,7 +220,7 @@ f: define i16 @test_set_mask_i16_i7(i16 %x) nounwind { ; CHECK-LABEL: test_set_mask_i16_i7: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: mov w8, #42 +; CHECK-NEXT: mov w8, #42 // =0x2a ; CHECK-NEXT: tst w0, #0x40 ; CHECK-NEXT: csel w0, w8, w0, ne ; CHECK-NEXT: ret diff --git a/llvm/test/CodeGen/AArch64/tbz-tbnz.ll b/llvm/test/CodeGen/AArch64/tbz-tbnz.ll index 3fe7346b3db28..0fa3bc9824be6 100644 --- a/llvm/test/CodeGen/AArch64/tbz-tbnz.ll +++ b/llvm/test/CodeGen/AArch64/tbz-tbnz.ll @@ -199,14 +199,16 @@ if.end: define void @test8(i64 %val1, i64 %val2, i64 %val3) { ; CHECK-SD-LABEL: test8: ; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: tst x0, x1 -; CHECK-SD-NEXT: b.ge .LBB7_3 +; CHECK-SD-NEXT: and x8, x0, x1 +; CHECK-SD-NEXT: cmn x8, #1 +; CHECK-SD-NEXT: b.gt .LBB7_3 ; CHECK-SD-NEXT: // %bb.1: ; CHECK-SD-NEXT: and x8, x1, x2 ; CHECK-SD-NEXT: tbnz x8, #63, .LBB7_3 ; CHECK-SD-NEXT: // %bb.2: // %if.then2 -; CHECK-SD-NEXT: tst x0, x1, lsl #63 -; CHECK-SD-NEXT: b.lt .LBB7_4 +; CHECK-SD-NEXT: and x8, x0, x1, lsl #63 +; CHECK-SD-NEXT: cmn x8, #1 +; CHECK-SD-NEXT: b.le .LBB7_4 ; CHECK-SD-NEXT: .LBB7_3: // %if.end ; CHECK-SD-NEXT: ret ; CHECK-SD-NEXT: .LBB7_4: // %if.then3 diff --git a/llvm/test/CodeGen/AArch64/typepromotion-signed.ll b/llvm/test/CodeGen/AArch64/typepromotion-signed.ll index 212f02d86850b..0feac24062647 100644 --- a/llvm/test/CodeGen/AArch64/typepromotion-signed.ll +++ b/llvm/test/CodeGen/AArch64/typepromotion-signed.ll @@ -60,9 +60,9 @@ define i32 @test_signext_b(ptr nocapture readonly %ptr, i8 signext %arg) { ; CHECK-NEXT: mov w8, #20894 // =0x519e ; CHECK-NEXT: add w9, w9, w1 ; CHECK-NEXT: sxtb w9, w9 -; CHECK-NEXT: cmp w9, #0 +; CHECK-NEXT: cmn w9, #1 ; CHECK-NEXT: mov w9, #42 // =0x2a -; CHECK-NEXT: csel w0, w9, w8, ge +; CHECK-NEXT: csel w0, w9, w8, gt ; CHECK-NEXT: ret entry: %0 = load i8, ptr %ptr, align 1 @@ -100,9 +100,9 @@ define i32 @test_signext_h(ptr nocapture readonly %ptr, i16 signext %arg) { ; CHECK-NEXT: mov w8, #20894 // =0x519e ; CHECK-NEXT: add w9, w9, w1 ; CHECK-NEXT: sxth w9, w9 -; CHECK-NEXT: cmp w9, #0 +; CHECK-NEXT: cmn w9, #1 ; CHECK-NEXT: mov w9, #42 // =0x2a -; CHECK-NEXT: csel w0, w9, w8, ge +; CHECK-NEXT: csel w0, w9, w8, gt ; CHECK-NEXT: ret entry: %0 = load i16, ptr %ptr, align 1 diff --git a/llvm/test/CodeGen/AArch64/use-cr-result-of-dom-icmp-st.ll b/llvm/test/CodeGen/AArch64/use-cr-result-of-dom-icmp-st.ll index d23e23c752350..f475b384b67e0 100644 --- a/llvm/test/CodeGen/AArch64/use-cr-result-of-dom-icmp-st.ll +++ b/llvm/test/CodeGen/AArch64/use-cr-result-of-dom-icmp-st.ll @@ -43,10 +43,9 @@ define i64 @ll_a_op_b__1(i64 %a, i64 %b) { ; CHECK: // %bb.0: // %entry ; CHECK-NEXT: lsl x8, x0, x1 ; CHECK-NEXT: cmn x8, #1 -; CHECK-NEXT: csinc x9, x1, xzr, eq -; CHECK-NEXT: cmp x8, #0 -; CHECK-NEXT: mul x9, x9, x0 -; CHECK-NEXT: csel x0, x1, x9, ge +; CHECK-NEXT: csinc x8, x1, xzr, eq +; CHECK-NEXT: mul x8, x8, x0 +; CHECK-NEXT: csel x0, x1, x8, gt ; CHECK-NEXT: ret entry: %shl = shl i64 %a, %b @@ -162,9 +161,8 @@ define i64 @ll_a__1(i64 %a, i64 %b) { ; CHECK: // %bb.0: // %entry ; CHECK-NEXT: cmn x0, #1 ; CHECK-NEXT: csinc x8, x1, xzr, eq -; CHECK-NEXT: cmp x0, #0 ; CHECK-NEXT: mul x8, x8, x0 -; CHECK-NEXT: csel x0, x1, x8, ge +; CHECK-NEXT: csel x0, x1, x8, gt ; CHECK-NEXT: ret entry: %cmp = icmp sgt i64 %a, -1 @@ -278,10 +276,9 @@ define i64 @i_a_op_b__1(i32 signext %a, i32 signext %b) { ; CHECK: // %bb.0: // %entry ; CHECK-NEXT: lsl w8, w0, w1 ; CHECK-NEXT: cmn w8, #1 -; CHECK-NEXT: csinc w9, w1, wzr, eq -; CHECK-NEXT: cmp w8, #0 -; CHECK-NEXT: mul w9, w9, w0 -; CHECK-NEXT: csel w8, w1, w9, ge +; CHECK-NEXT: csinc w8, w1, wzr, eq +; CHECK-NEXT: mul w8, w8, w0 +; CHECK-NEXT: csel w8, w1, w8, gt ; CHECK-NEXT: sxtw x0, w8 ; CHECK-NEXT: ret entry: @@ -412,9 +409,8 @@ define i64 @i_a__1(i32 signext %a, i32 signext %b) { ; CHECK: // %bb.0: // %entry ; CHECK-NEXT: cmn w0, #1 ; CHECK-NEXT: csinc w8, w1, wzr, eq -; CHECK-NEXT: cmp w0, #0 ; CHECK-NEXT: mul w8, w8, w0 -; CHECK-NEXT: csel w8, w1, w8, ge +; CHECK-NEXT: csel w8, w1, w8, gt ; CHECK-NEXT: sxtw x0, w8 ; CHECK-NEXT: ret entry: diff --git a/llvm/test/CodeGen/AArch64/win64_vararg.ll b/llvm/test/CodeGen/AArch64/win64_vararg.ll index aaf4cad608740..d72dee9021251 100644 --- a/llvm/test/CodeGen/AArch64/win64_vararg.ll +++ b/llvm/test/CodeGen/AArch64/win64_vararg.ll @@ -133,8 +133,8 @@ define i32 @fp(ptr, i64, ptr, ...) local_unnamed_addr #6 { ; CHECK-NEXT: mov x4, xzr ; CHECK-NEXT: orr x0, x8, #0x2 ; CHECK-NEXT: bl __stdio_common_vsprintf -; CHECK-NEXT: cmp w0, #0 -; CHECK-NEXT: csinv w0, w0, wzr, ge +; CHECK-NEXT: cmn w0, #1 +; CHECK-NEXT: csinv w0, w0, wzr, gt ; CHECK-NEXT: .seh_startepilogue ; CHECK-NEXT: ldp x29, x30, [sp, #24] // 16-byte Folded Reload ; CHECK-NEXT: .seh_save_fplr 24 @@ -268,8 +268,8 @@ define i32 @snprintf(ptr, i64, ptr, ...) local_unnamed_addr #5 { ; CHECK-NEXT: mov x4, xzr ; CHECK-NEXT: orr x0, x8, #0x2 ; CHECK-NEXT: bl __stdio_common_vsprintf -; CHECK-NEXT: cmp w0, #0 -; CHECK-NEXT: csinv w0, w0, wzr, ge +; CHECK-NEXT: cmn w0, #1 +; CHECK-NEXT: csinv w0, w0, wzr, gt ; CHECK-NEXT: .seh_startepilogue ; CHECK-NEXT: ldp x21, x30, [sp, #32] // 16-byte Folded Reload ; CHECK-NEXT: .seh_save_lrpair x21, 32