diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h --- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h @@ -414,6 +414,7 @@ LegalizeResult lowerVectorReduction(MachineInstr &MI); LegalizeResult lowerMemcpyInline(MachineInstr &MI); LegalizeResult lowerMemCpyFamily(MachineInstr &MI, unsigned MaxLen = 0); + LegalizeResult lowerIsFPClass(MachineInstr &MI); }; /// Helper function that creates a libcall to the given \p Name using the given diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp --- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -2268,6 +2268,20 @@ return true; } + case Intrinsic::is_fpclass: { + unsigned Flags = + MachineInstr::copyFlagsFromInstruction(CI) | MachineInstr::NoFPExcept; + Register Src = getOrCreateVReg(*CI.getArgOperand(0)); + unsigned Test = cast(CI.getOperand(1))->getZExtValue(); + const fltSemantics &S = + CI.getArgOperand(0)->getType()->getScalarType()->getFltSemantics(); + MIRBuilder + .buildInstr(TargetOpcode::G_IS_FPCLASS, {getOrCreateVReg(CI)}, {Src}, + Flags) + .addImm(Test) + .addImm(APFloat::SemanticsToEnum(S)); + return true; + } #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \ case Intrinsic::INTRINSIC: #include "llvm/IR/ConstrainedOps.def" diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp --- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h" +#include "llvm/CodeGen/CodeGenCommonISel.h" #include "llvm/CodeGen/GlobalISel/CallLowering.h" #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h" #include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h" @@ -3569,6 +3570,8 @@ return lowerMemcpyInline(MI); GISEL_VECREDUCE_CASES_NONSEQ return lowerVectorReduction(MI); + case G_IS_FPCLASS: + return lowerIsFPClass(MI); } } @@ -4282,6 +4285,8 @@ return fewerElementsVectorReductions(MI, TypeIdx, NarrowTy); case G_SHUFFLE_VECTOR: return fewerElementsVectorShuffle(MI, TypeIdx, NarrowTy); + case G_IS_FPCLASS: + return fewerElementsVectorMultiEltType(GMI, NumElts, {2, 3}); default: return UnableToLegalize; } @@ -7885,3 +7890,183 @@ return lowerMemset(MI, Dst, Src, KnownLen, DstAlign, IsVolatile); return UnableToLegalize; } + +LegalizerHelper::LegalizeResult +LegalizerHelper::lowerIsFPClass(MachineInstr &MI) { + Register Dst = MI.getOperand(0).getReg(); + Register Src = MI.getOperand(1).getReg(); + unsigned Test = MI.getOperand(2).getImm(); + auto FloatSem = static_cast(MI.getOperand(3).getImm()); + LLT DstTy = MRI.getType(Dst); + LLT SrcTy = MRI.getType(Src); + + // Some checks may be represented as inversion of simpler check, for example + // "inf|normal|subnormal|zero" => !"nan". + bool IsInverted = false; + if (unsigned InvertedCheck = getInvertedFPClassTest(Test)) { + IsInverted = true; + Test = InvertedCheck; + } + + // Some checks can be implemented using float comparisons, if floating point + // exceptions are ignored. + Function &F = MI.getParent()->getParent()->getFunction(); + if (!F.getAttributes().hasFnAttr(llvm::Attribute::StrictFP)) { + if (Test == fcZero) { + CmpInst::Predicate Predicate = IsInverted ? CmpInst::Predicate::FCMP_UNE + : CmpInst::Predicate::FCMP_OEQ; + auto Zero = MIRBuilder.buildFConstant(SrcTy, 0.0); + MIRBuilder.buildFCmp(Predicate, Dst, Src, Zero); + MI.eraseFromParent(); + return Legalized; + } + if (Test == fcNan) { + CmpInst::Predicate Predicate = IsInverted ? CmpInst::Predicate::FCMP_ORD + : CmpInst::Predicate::FCMP_UNO; + MIRBuilder.buildFCmp(Predicate, Dst, Src, Src); + MI.eraseFromParent(); + return Legalized; + } + } + + // In the general case use integer operations. + unsigned BitSize = SrcTy.getSizeInBits(); + LLT IntTy = LLT::scalar(BitSize); + const fltSemantics &S = APFloat::EnumToSemantics(FloatSem); + + APInt SignBit = APInt::getSignMask(BitSize); + APInt ValueMask = APInt::getSignedMaxValue(BitSize); // All bits but sign. + APInt Inf = APFloat::getInf(S).bitcastToAPInt(); // Exp and int bit. + APInt ExpMask = Inf; + APInt AllOneMantissa = APFloat::getLargest(S).bitcastToAPInt() & ~Inf; + APInt QNaNBitMask = AllOneMantissa & ~(AllOneMantissa.lshr(1)); + + auto ValueMaskV = MIRBuilder.buildConstant(IntTy, ValueMask); + auto SignBitV = MIRBuilder.buildConstant(IntTy, SignBit); + auto ExpMaskV = MIRBuilder.buildConstant(IntTy, ExpMask); + auto ZeroV = MIRBuilder.buildConstant(IntTy, 0); + auto InfV = MIRBuilder.buildConstant(IntTy, Inf); + + APInt InvertionMask = APInt::getAllOnesValue(DstTy.getScalarSizeInBits()); + auto ResultInvertionMask = MIRBuilder.buildConstant(DstTy, InvertionMask); + + MachineInstrBuilder Res; + const auto appendResult = [&](MachineInstrBuilder PartialRes) { + if (PartialRes) { + if (Res) + Res = MIRBuilder.buildOr(DstTy, Res, PartialRes); + else + Res = PartialRes; + } + }; + + // Split the value into sign bit and absolute value. + auto AbsV = MIRBuilder.buildAnd(IntTy, Src, ValueMaskV); + auto SignV = MIRBuilder.buildICmp(CmpInst::ICMP_SLT, DstTy, Src, ZeroV); + + // Tests that involve more than one class should be processed first. + MachineInstrBuilder PartialRes; + + if ((Test & fcFinite) == fcFinite) { + // finite(V) ==> exp mask > abs(V) + PartialRes = MIRBuilder.buildICmp(CmpInst::ICMP_SGT, DstTy, ExpMaskV, AbsV); + Test &= ~fcFinite; + } else if ((Test & fcFinite) == fcPosFinite) { + // finite(V) && V > 0 ==> exp mask > V + PartialRes = MIRBuilder.buildICmp(CmpInst::ICMP_UGT, DstTy, ExpMaskV, Src); + Test &= ~fcPosFinite; + } else if ((Test & fcFinite) == fcNegFinite) { + // finite(V) && V < 0 ==> exp mask > abs(V) && signbit == 1 + PartialRes = MIRBuilder.buildICmp(CmpInst::ICMP_UGT, DstTy, ExpMaskV, AbsV); + PartialRes = MIRBuilder.buildAnd(DstTy, PartialRes, SignV); + Test &= ~fcNegFinite; + } + appendResult(PartialRes); + + // Check for individual classes. + + if (unsigned PartialCheck = Test & fcZero) { + if (PartialCheck == fcPosZero) + PartialRes = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, DstTy, Src, ZeroV); + else if (PartialCheck == fcZero) + PartialRes = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, DstTy, AbsV, ZeroV); + else // fcNegZero + PartialRes = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, DstTy, Src, SignBitV); + appendResult(PartialRes); + } + + if (unsigned PartialCheck = Test & fcInf) { + if (PartialCheck == fcPosInf) + PartialRes = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, DstTy, Src, InfV); + else if (PartialCheck == fcInf) + PartialRes = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, DstTy, AbsV, InfV); + else { // fcNegInf + APInt NegInf = APFloat::getInf(S, true).bitcastToAPInt(); + auto NegInfV = MIRBuilder.buildConstant(IntTy, NegInf); + PartialRes = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, DstTy, Src, NegInfV); + } + appendResult(PartialRes); + } + + if (unsigned PartialCheck = Test & fcNan) { + APInt InfWithQnanBit = Inf | QNaNBitMask; + auto InfWithQnanBitV = MIRBuilder.buildConstant(IntTy, InfWithQnanBit); + if (PartialCheck == fcNan) { + // isnan(V) ==> abs(V) > int(inf) + PartialRes = MIRBuilder.buildICmp(CmpInst::ICMP_SGT, DstTy, AbsV, InfV); + } else if (PartialCheck == fcQNan) { + // isquiet(V) ==> unsigned(V) >= (unsigned(Inf) | quiet_bit) + PartialRes = + MIRBuilder.buildICmp(CmpInst::ICMP_SGE, DstTy, AbsV, InfWithQnanBitV); + } else { // fcSNan + // issignaling(V) ==> abs(V) > unsigned(Inf) && + // abs(V) < (unsigned(Inf) | quiet_bit) + auto IsNan = MIRBuilder.buildICmp(CmpInst::ICMP_SGT, DstTy, AbsV, InfV); + auto IsNotQnan = + MIRBuilder.buildICmp(CmpInst::ICMP_SLT, DstTy, AbsV, InfWithQnanBitV); + PartialRes = MIRBuilder.buildAnd(DstTy, IsNan, IsNotQnan); + } + appendResult(PartialRes); + } + + if (unsigned PartialCheck = Test & fcSubnormal) { + // issubnormal(V) ==> unsigned(abs(V) - 1) < (all mantissa bits set) + // issubnormal(V) && V>0 ==> unsigned(V - 1) < (all mantissa bits set) + auto V = (PartialCheck == fcPosSubnormal) ? SrcOp(Src) : AbsV; + auto MantissaV = MIRBuilder.buildConstant(IntTy, AllOneMantissa); + auto VMinusOneV = + MIRBuilder.buildSub(IntTy, V, MIRBuilder.buildConstant(IntTy, 1)); + PartialRes = + MIRBuilder.buildICmp(CmpInst::ICMP_ULT, DstTy, VMinusOneV, MantissaV); + if (PartialCheck == fcNegSubnormal) + PartialRes = MIRBuilder.buildAnd(DstTy, PartialRes, SignV); + appendResult(PartialRes); + } + + if (unsigned PartialCheck = Test & fcNormal) { + // isnormal(V) ==> (0 < exp < max_exp) == (unsigned(exp-1) < (max_exp-1)) + APInt ExpLSB = ExpMask & ~(ExpMask.shl(1)); + auto ExpLSBV = MIRBuilder.buildConstant(IntTy, ExpLSB); + auto ExpMinus1 = MIRBuilder.buildSub(IntTy, AbsV, ExpLSBV); + APInt ExpLimit = ExpMask - ExpLSB; + auto ExpLimitV = MIRBuilder.buildConstant(IntTy, ExpLimit); + PartialRes = + MIRBuilder.buildICmp(CmpInst::ICMP_ULT, DstTy, ExpMinus1, ExpLimitV); + if (PartialCheck == fcNegNormal) + PartialRes = MIRBuilder.buildAnd(DstTy, PartialRes, SignV); + else if (PartialCheck == fcPosNormal) { + auto PosSignV = MIRBuilder.buildXor(DstTy, SignV, ResultInvertionMask); + PartialRes = MIRBuilder.buildAnd(DstTy, PartialRes, PosSignV); + } + appendResult(PartialRes); + } + + if (!Res) + MIRBuilder.buildConstant(Dst, IsInverted); + else if (IsInverted) + MIRBuilder.buildXor(Dst, Res, ResultInvertionMask); + else + MIRBuilder.buildCopy(Dst, Res); + MI.eraseFromParent(); + return Legalized; +} diff --git a/llvm/lib/Target/X86/X86LegalizerInfo.cpp b/llvm/lib/Target/X86/X86LegalizerInfo.cpp --- a/llvm/lib/Target/X86/X86LegalizerInfo.cpp +++ b/llvm/lib/Target/X86/X86LegalizerInfo.cpp @@ -75,6 +75,7 @@ .scalarize(0) .minScalar(0, LLT::scalar(32)) .libcall(); + getActionDefinitionsBuilder(G_IS_FPCLASS).lower(); auto &LegacyInfo = getLegacyLegalizerInfo(); LegacyInfo.setLegalizeScalarToDifferentSizeStrategy(G_PHI, 0, widen_1); diff --git a/llvm/test/CodeGen/X86/GlobalISel/is_fpclass.ll b/llvm/test/CodeGen/X86/GlobalISel/is_fpclass.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/X86/GlobalISel/is_fpclass.ll @@ -0,0 +1,468 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=x86_64 -global-isel | FileCheck %s -check-prefix=CHECK-64 + +define i1 @isnan_f(float %x) { +; CHECK-64-LABEL: isnan_f: +; CHECK-64: # %bb.0: # %entry +; CHECK-64-NEXT: ucomiss %xmm0, %xmm0 +; CHECK-64-NEXT: setp %al +; CHECK-64-NEXT: retq +entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 3) ; "nan" + ret i1 %0 +} + +define i1 @isnot_nan_f(float %x) { +; CHECK-64-LABEL: isnot_nan_f: +; CHECK-64: # %bb.0: # %entry +; CHECK-64-NEXT: ucomiss %xmm0, %xmm0 +; CHECK-64-NEXT: setnp %al +; CHECK-64-NEXT: retq +entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 1020) ; 0x3fc = "zero|subnormal|normal|inf" + ret i1 %0 +} + +define i1 @issignaling_f(float %x) { +; CHECK-64-LABEL: issignaling_f: +; CHECK-64: # %bb.0: # %entry +; CHECK-64-NEXT: movl $2139095040, %eax # imm = 0x7F800000 +; CHECK-64-NEXT: movd %xmm0, %ecx +; CHECK-64-NEXT: andl $2147483647, %ecx # imm = 0x7FFFFFFF +; CHECK-64-NEXT: movl $2143289344, %esi # imm = 0x7FC00000 +; CHECK-64-NEXT: cmpl %eax, %ecx +; CHECK-64-NEXT: setg %dl +; CHECK-64-NEXT: cmpl %esi, %ecx +; CHECK-64-NEXT: setl %al +; CHECK-64-NEXT: andb %dl, %al +; CHECK-64-NEXT: retq +entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 1) ; "snan" + ret i1 %0 +} + +define i1 @isquiet_f(float %x) { +; CHECK-64-LABEL: isquiet_f: +; CHECK-64: # %bb.0: # %entry +; CHECK-64-NEXT: movd %xmm0, %eax +; CHECK-64-NEXT: andl $2147483647, %eax # imm = 0x7FFFFFFF +; CHECK-64-NEXT: movl $2143289344, %ecx # imm = 0x7FC00000 +; CHECK-64-NEXT: cmpl %ecx, %eax +; CHECK-64-NEXT: setge %al +; CHECK-64-NEXT: retq +entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 2) ; "qnan" + ret i1 %0 +} + +define i1 @isinf_f(float %x) { +; CHECK-64-LABEL: isinf_f: +; CHECK-64: # %bb.0: # %entry +; CHECK-64-NEXT: movl $2139095040, %eax # imm = 0x7F800000 +; CHECK-64-NEXT: movd %xmm0, %ecx +; CHECK-64-NEXT: andl $2147483647, %ecx # imm = 0x7FFFFFFF +; CHECK-64-NEXT: cmpl %eax, %ecx +; CHECK-64-NEXT: sete %al +; CHECK-64-NEXT: retq +entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 516) ; 0x204 = "inf" + ret i1 %0 +} + +define i1 @is_plus_inf_f(float %x) { +; CHECK-64-LABEL: is_plus_inf_f: +; CHECK-64: # %bb.0: # %entry +; CHECK-64-NEXT: movl $2139095040, %eax # imm = 0x7F800000 +; CHECK-64-NEXT: movd %xmm0, %ecx +; CHECK-64-NEXT: cmpl %eax, %ecx +; CHECK-64-NEXT: sete %al +; CHECK-64-NEXT: retq +entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 512) ; 0x200 = "+inf" + ret i1 %0 +} + +define i1 @is_minus_inf_f(float %x) { +; CHECK-64-LABEL: is_minus_inf_f: +; CHECK-64: # %bb.0: # %entry +; CHECK-64-NEXT: movl $-8388608, %eax # imm = 0xFF800000 +; CHECK-64-NEXT: movd %xmm0, %ecx +; CHECK-64-NEXT: cmpl %eax, %ecx +; CHECK-64-NEXT: sete %al +; CHECK-64-NEXT: retq +entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 4) ; "-inf" + ret i1 %0 +} + +define i1 @isfinite_f(float %x) { +; CHECK-64-LABEL: isfinite_f: +; CHECK-64: # %bb.0: # %entry +; CHECK-64-NEXT: movl $2139095040, %eax # imm = 0x7F800000 +; CHECK-64-NEXT: movd %xmm0, %ecx +; CHECK-64-NEXT: andl $2147483647, %ecx # imm = 0x7FFFFFFF +; CHECK-64-NEXT: cmpl %ecx, %eax +; CHECK-64-NEXT: setg %al +; CHECK-64-NEXT: retq +entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 504) ; 0x1f8 = "finite" + ret i1 %0 +} + +define i1 @is_plus_finite_f(float %x) { +; CHECK-64-LABEL: is_plus_finite_f: +; CHECK-64: # %bb.0: # %entry +; CHECK-64-NEXT: movl $2139095040, %eax # imm = 0x7F800000 +; CHECK-64-NEXT: movd %xmm0, %ecx +; CHECK-64-NEXT: cmpl %ecx, %eax +; CHECK-64-NEXT: seta %al +; CHECK-64-NEXT: retq +entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 448) ; 0x1c0 = "+finite" + ret i1 %0 +} + +define i1 @is_minus_finite_f(float %x) { +; CHECK-64-LABEL: is_minus_finite_f: +; CHECK-64: # %bb.0: # %entry +; CHECK-64-NEXT: movl $2139095040, %eax # imm = 0x7F800000 +; CHECK-64-NEXT: xorl %ecx, %ecx +; CHECK-64-NEXT: movd %xmm0, %edx +; CHECK-64-NEXT: movl %edx, %esi +; CHECK-64-NEXT: andl $2147483647, %esi # imm = 0x7FFFFFFF +; CHECK-64-NEXT: cmpl %ecx, %edx +; CHECK-64-NEXT: setl %cl +; CHECK-64-NEXT: cmpl %esi, %eax +; CHECK-64-NEXT: seta %al +; CHECK-64-NEXT: andb %cl, %al +; CHECK-64-NEXT: retq +entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 56) ; 0x38 = "-finite" + ret i1 %0 +} + +define i1 @isnormal_f(float %x) { +; CHECK-64-LABEL: isnormal_f: +; CHECK-64: # %bb.0: # %entry +; CHECK-64-NEXT: movd %xmm0, %eax +; CHECK-64-NEXT: andl $2147483647, %eax # imm = 0x7FFFFFFF +; CHECK-64-NEXT: subl $8388608, %eax # imm = 0x800000 +; CHECK-64-NEXT: movl $2130706432, %ecx # imm = 0x7F000000 +; CHECK-64-NEXT: cmpl %ecx, %eax +; CHECK-64-NEXT: setb %al +; CHECK-64-NEXT: retq +entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 264) ; 0x108 = "normal" + ret i1 %0 +} + +define i1 @is_plus_normal_f(float %x) { +; CHECK-64-LABEL: is_plus_normal_f: +; CHECK-64: # %bb.0: # %entry +; CHECK-64-NEXT: xorl %eax, %eax +; CHECK-64-NEXT: movd %xmm0, %ecx +; CHECK-64-NEXT: movl %ecx, %edx +; CHECK-64-NEXT: andl $2147483647, %edx # imm = 0x7FFFFFFF +; CHECK-64-NEXT: cmpl %eax, %ecx +; CHECK-64-NEXT: setl %al +; CHECK-64-NEXT: subl $8388608, %edx # imm = 0x800000 +; CHECK-64-NEXT: movl $2130706432, %ecx # imm = 0x7F000000 +; CHECK-64-NEXT: cmpl %ecx, %edx +; CHECK-64-NEXT: setb %cl +; CHECK-64-NEXT: xorb $1, %al +; CHECK-64-NEXT: andb %cl, %al +; CHECK-64-NEXT: retq +entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 256) ; 0x100 = "+normal" + ret i1 %0 +} + +define i1 @issubnormal_f(float %x) { +; CHECK-64-LABEL: issubnormal_f: +; CHECK-64: # %bb.0: # %entry +; CHECK-64-NEXT: movd %xmm0, %eax +; CHECK-64-NEXT: andl $2147483647, %eax # imm = 0x7FFFFFFF +; CHECK-64-NEXT: movl $8388607, %ecx # imm = 0x7FFFFF +; CHECK-64-NEXT: subl $1, %eax +; CHECK-64-NEXT: cmpl %ecx, %eax +; CHECK-64-NEXT: setb %al +; CHECK-64-NEXT: retq +entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 144) ; 0x90 = "subnormal" + ret i1 %0 +} + +define i1 @is_plus_subnormal_f(float %x) { +; CHECK-64-LABEL: is_plus_subnormal_f: +; CHECK-64: # %bb.0: # %entry +; CHECK-64-NEXT: movl $8388607, %eax # imm = 0x7FFFFF +; CHECK-64-NEXT: movd %xmm0, %ecx +; CHECK-64-NEXT: subl $1, %ecx +; CHECK-64-NEXT: cmpl %eax, %ecx +; CHECK-64-NEXT: setb %al +; CHECK-64-NEXT: retq +entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 128) ; 0x80 = "+subnormal" + ret i1 %0 +} + +define i1 @is_minus_subnormal_f(float %x) { +; CHECK-64-LABEL: is_minus_subnormal_f: +; CHECK-64: # %bb.0: # %entry +; CHECK-64-NEXT: xorl %eax, %eax +; CHECK-64-NEXT: movd %xmm0, %ecx +; CHECK-64-NEXT: movl %ecx, %edx +; CHECK-64-NEXT: andl $2147483647, %edx # imm = 0x7FFFFFFF +; CHECK-64-NEXT: cmpl %eax, %ecx +; CHECK-64-NEXT: setl %cl +; CHECK-64-NEXT: movl $8388607, %eax # imm = 0x7FFFFF +; CHECK-64-NEXT: subl $1, %edx +; CHECK-64-NEXT: cmpl %eax, %edx +; CHECK-64-NEXT: setb %al +; CHECK-64-NEXT: andb %cl, %al +; CHECK-64-NEXT: retq +entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 16) ; 0x10 = "-subnormal" + ret i1 %0 +} + +define i1 @iszero_f(float %x) { +; CHECK-64-LABEL: iszero_f: +; CHECK-64: # %bb.0: # %entry +; CHECK-64-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero +; CHECK-64-NEXT: ucomiss %xmm1, %xmm0 +; CHECK-64-NEXT: sete %cl +; CHECK-64-NEXT: setnp %al +; CHECK-64-NEXT: andb %cl, %al +; CHECK-64-NEXT: retq +entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 96) ; 0x60 = "zero" + ret i1 %0 +} + +define i1 @is_plus_zero_f(float %x) { +; CHECK-64-LABEL: is_plus_zero_f: +; CHECK-64: # %bb.0: # %entry +; CHECK-64-NEXT: xorl %eax, %eax +; CHECK-64-NEXT: movd %xmm0, %ecx +; CHECK-64-NEXT: cmpl %eax, %ecx +; CHECK-64-NEXT: sete %al +; CHECK-64-NEXT: retq +entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 64) ; 0x40 = "+zero" + ret i1 %0 +} + +define i1 @is_minus_zero_f(float %x) { +; CHECK-64-LABEL: is_minus_zero_f: +; CHECK-64: # %bb.0: # %entry +; CHECK-64-NEXT: movl $-2147483648, %eax # imm = 0x80000000 +; CHECK-64-NEXT: movd %xmm0, %ecx +; CHECK-64-NEXT: cmpl %eax, %ecx +; CHECK-64-NEXT: sete %al +; CHECK-64-NEXT: retq +entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 32) ; 0x20 = "-zero" + ret i1 %0 +} + + + +define i1 @isnan_f_strictfp(float %x) strictfp { +; CHECK-64-LABEL: isnan_f_strictfp: +; CHECK-64: # %bb.0: # %entry +; CHECK-64-NEXT: movl $2139095040, %eax # imm = 0x7F800000 +; CHECK-64-NEXT: movd %xmm0, %ecx +; CHECK-64-NEXT: andl $2147483647, %ecx # imm = 0x7FFFFFFF +; CHECK-64-NEXT: cmpl %eax, %ecx +; CHECK-64-NEXT: setg %al +; CHECK-64-NEXT: retq +entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 3) ; "nan" + ret i1 %0 +} + +define i1 @isfinite_f_strictfp(float %x) strictfp { +; CHECK-64-LABEL: isfinite_f_strictfp: +; CHECK-64: # %bb.0: # %entry +; CHECK-64-NEXT: movl $2139095040, %eax # imm = 0x7F800000 +; CHECK-64-NEXT: movd %xmm0, %ecx +; CHECK-64-NEXT: andl $2147483647, %ecx # imm = 0x7FFFFFFF +; CHECK-64-NEXT: cmpl %ecx, %eax +; CHECK-64-NEXT: setg %al +; CHECK-64-NEXT: retq +entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 504) ; 0x1f8 = "finite" + ret i1 %0 +} + +define i1 @iszero_f_strictfp(float %x) strictfp { +; CHECK-64-LABEL: iszero_f_strictfp: +; CHECK-64: # %bb.0: # %entry +; CHECK-64-NEXT: xorl %eax, %eax +; CHECK-64-NEXT: movd %xmm0, %ecx +; CHECK-64-NEXT: andl $2147483647, %ecx # imm = 0x7FFFFFFF +; CHECK-64-NEXT: cmpl %eax, %ecx +; CHECK-64-NEXT: sete %al +; CHECK-64-NEXT: retq +entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 96) ; 0x60 = "zero" + ret i1 %0 +} + + +define i1 @isnan_d(double %x) { +; CHECK-64-LABEL: isnan_d: +; CHECK-64: # %bb.0: # %entry +; CHECK-64-NEXT: ucomisd %xmm0, %xmm0 +; CHECK-64-NEXT: setp %al +; CHECK-64-NEXT: retq +entry: + %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 3) ; "nan" + ret i1 %0 +} + +define i1 @isinf_d(double %x) { +; CHECK-64-LABEL: isinf_d: +; CHECK-64: # %bb.0: # %entry +; CHECK-64-NEXT: movabsq $9223372036854775807, %rax # imm = 0x7FFFFFFFFFFFFFFF +; CHECK-64-NEXT: movabsq $9218868437227405312, %rcx # imm = 0x7FF0000000000000 +; CHECK-64-NEXT: movq %xmm0, %rdx +; CHECK-64-NEXT: andq %rax, %rdx +; CHECK-64-NEXT: cmpq %rcx, %rdx +; CHECK-64-NEXT: sete %al +; CHECK-64-NEXT: retq +entry: + %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 516) ; 0x204 = "inf" + ret i1 %0 +} + +define i1 @isfinite_d(double %x) { +; CHECK-64-LABEL: isfinite_d: +; CHECK-64: # %bb.0: # %entry +; CHECK-64-NEXT: movabsq $9223372036854775807, %rax # imm = 0x7FFFFFFFFFFFFFFF +; CHECK-64-NEXT: movabsq $9218868437227405312, %rcx # imm = 0x7FF0000000000000 +; CHECK-64-NEXT: movq %xmm0, %rdx +; CHECK-64-NEXT: andq %rax, %rdx +; CHECK-64-NEXT: cmpq %rdx, %rcx +; CHECK-64-NEXT: setg %al +; CHECK-64-NEXT: retq +entry: + %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 504) ; 0x1f8 = "finite" + ret i1 %0 +} + +define i1 @isnormal_d(double %x) { +; CHECK-64-LABEL: isnormal_d: +; CHECK-64: # %bb.0: # %entry +; CHECK-64-NEXT: movabsq $9223372036854775807, %rax # imm = 0x7FFFFFFFFFFFFFFF +; CHECK-64-NEXT: movq %xmm0, %rcx +; CHECK-64-NEXT: andq %rax, %rcx +; CHECK-64-NEXT: movabsq $4503599627370496, %rax # imm = 0x10000000000000 +; CHECK-64-NEXT: subq %rax, %rcx +; CHECK-64-NEXT: movabsq $9214364837600034816, %rax # imm = 0x7FE0000000000000 +; CHECK-64-NEXT: cmpq %rax, %rcx +; CHECK-64-NEXT: setb %al +; CHECK-64-NEXT: retq +entry: + %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 264) ; 0x108 = "normal" + ret i1 %0 +} + +define i1 @issubnormal_d(double %x) { +; CHECK-64-LABEL: issubnormal_d: +; CHECK-64: # %bb.0: # %entry +; CHECK-64-NEXT: movabsq $9223372036854775807, %rax # imm = 0x7FFFFFFFFFFFFFFF +; CHECK-64-NEXT: movq %xmm0, %rcx +; CHECK-64-NEXT: andq %rax, %rcx +; CHECK-64-NEXT: movabsq $4503599627370495, %rax # imm = 0xFFFFFFFFFFFFF +; CHECK-64-NEXT: subq $1, %rcx +; CHECK-64-NEXT: cmpq %rax, %rcx +; CHECK-64-NEXT: setb %al +; CHECK-64-NEXT: retq +entry: + %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 144) ; 0x90 = "subnormal" + ret i1 %0 +} + +define i1 @iszero_d(double %x) { +; CHECK-64-LABEL: iszero_d: +; CHECK-64: # %bb.0: # %entry +; CHECK-64-NEXT: movsd {{.*#+}} xmm1 = mem[0],zero +; CHECK-64-NEXT: ucomisd %xmm1, %xmm0 +; CHECK-64-NEXT: sete %cl +; CHECK-64-NEXT: setnp %al +; CHECK-64-NEXT: andb %cl, %al +; CHECK-64-NEXT: retq +entry: + %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 96) ; 0x60 = "zero" + ret i1 %0 +} + +define i1 @issignaling_d(double %x) { +; CHECK-64-LABEL: issignaling_d: +; CHECK-64: # %bb.0: # %entry +; CHECK-64-NEXT: movabsq $9223372036854775807, %rax # imm = 0x7FFFFFFFFFFFFFFF +; CHECK-64-NEXT: movabsq $9218868437227405312, %rcx # imm = 0x7FF0000000000000 +; CHECK-64-NEXT: movq %xmm0, %rdx +; CHECK-64-NEXT: andq %rax, %rdx +; CHECK-64-NEXT: movabsq $9221120237041090560, %rax # imm = 0x7FF8000000000000 +; CHECK-64-NEXT: cmpq %rcx, %rdx +; CHECK-64-NEXT: setg %cl +; CHECK-64-NEXT: cmpq %rax, %rdx +; CHECK-64-NEXT: setl %al +; CHECK-64-NEXT: andb %cl, %al +; CHECK-64-NEXT: retq +entry: + %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 1) ; "snan" + ret i1 %0 +} + +define i1 @isquiet_d(double %x) { +; CHECK-64-LABEL: isquiet_d: +; CHECK-64: # %bb.0: # %entry +; CHECK-64-NEXT: movabsq $9223372036854775807, %rax # imm = 0x7FFFFFFFFFFFFFFF +; CHECK-64-NEXT: movq %xmm0, %rcx +; CHECK-64-NEXT: andq %rax, %rcx +; CHECK-64-NEXT: movabsq $9221120237041090560, %rax # imm = 0x7FF8000000000000 +; CHECK-64-NEXT: cmpq %rax, %rcx +; CHECK-64-NEXT: setge %al +; CHECK-64-NEXT: retq +entry: + %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 2) ; "qnan" + ret i1 %0 +} + +define i1 @isnan_d_strictfp(double %x) strictfp { +; CHECK-64-LABEL: isnan_d_strictfp: +; CHECK-64: # %bb.0: # %entry +; CHECK-64-NEXT: movabsq $9223372036854775807, %rax # imm = 0x7FFFFFFFFFFFFFFF +; CHECK-64-NEXT: movabsq $9218868437227405312, %rcx # imm = 0x7FF0000000000000 +; CHECK-64-NEXT: movq %xmm0, %rdx +; CHECK-64-NEXT: andq %rax, %rdx +; CHECK-64-NEXT: cmpq %rcx, %rdx +; CHECK-64-NEXT: setg %al +; CHECK-64-NEXT: retq +entry: + %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 3) ; "nan" + ret i1 %0 +} + +define i1 @iszero_d_strictfp(double %x) strictfp { +; CHECK-64-LABEL: iszero_d_strictfp: +; CHECK-64: # %bb.0: # %entry +; CHECK-64-NEXT: movabsq $9223372036854775807, %rax # imm = 0x7FFFFFFFFFFFFFFF +; CHECK-64-NEXT: movl $0, %ecx +; CHECK-64-NEXT: movq %xmm0, %rdx +; CHECK-64-NEXT: andq %rax, %rdx +; CHECK-64-NEXT: cmpq %rcx, %rdx +; CHECK-64-NEXT: sete %al +; CHECK-64-NEXT: retq +entry: + %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 96) ; 0x60 = "zero" + ret i1 %0 +} + + +declare i1 @llvm.is.fpclass.f32(float, i32) +declare i1 @llvm.is.fpclass.f64(double, i32) diff --git a/llvm/test/CodeGen/X86/GlobalISel/legalize-is_fpclass.mir b/llvm/test/CodeGen/X86/GlobalISel/legalize-is_fpclass.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/X86/GlobalISel/legalize-is_fpclass.mir @@ -0,0 +1,1079 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -mtriple=x86_64-linux-gnu -run-pass=legalizer %s -o - | FileCheck %s + +--- | + + define i1 @isnan_f(float %x) { + entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 3) + ret i1 %0 + } + + define i1 @isnot_nan_f(float %x) { + entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 1020) + ret i1 %0 + } + + define i1 @issignaling_f(float %x) { + entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 1) + ret i1 %0 + } + + define i1 @isquiet_f(float %x) { + entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 2) + ret i1 %0 + } + + define i1 @isinf_f(float %x) { + entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 516) + ret i1 %0 + } + + define i1 @is_plus_inf_f(float %x) { + entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 512) + ret i1 %0 + } + + define i1 @is_minus_inf_f(float %x) { + entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 4) + ret i1 %0 + } + + define i1 @isfinite_f(float %x) { + entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 504) + ret i1 %0 + } + + define i1 @is_plus_finite_f(float %x) { + entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 448) + ret i1 %0 + } + + define i1 @is_minus_finite_f(float %x) { + entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 56) + ret i1 %0 + } + + define i1 @isnormal_f(float %x) { + entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 264) + ret i1 %0 + } + + define i1 @is_plus_normal_f(float %x) { + entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 256) + ret i1 %0 + } + + define i1 @issubnormal_f(float %x) { + entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 144) + ret i1 %0 + } + + define i1 @is_plus_subnormal_f(float %x) { + entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 128) + ret i1 %0 + } + + define i1 @is_minus_subnormal_f(float %x) { + entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 16) + ret i1 %0 + } + + define i1 @iszero_f(float %x) { + entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 96) + ret i1 %0 + } + + define i1 @is_plus_zero_f(float %x) { + entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 64) + ret i1 %0 + } + + define i1 @is_minus_zero_f(float %x) { + entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 32) + ret i1 %0 + } + + ; Function Attrs: strictfp + define i1 @isnan_f_strictfp(float %x) #0 { + entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 3) + ret i1 %0 + } + + ; Function Attrs: strictfp + define i1 @isfinite_f_strictfp(float %x) #0 { + entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 504) + ret i1 %0 + } + + ; Function Attrs: strictfp + define i1 @iszero_f_strictfp(float %x) #0 { + entry: + %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 96) + ret i1 %0 + } + + define i1 @isnan_d(double %x) { + entry: + %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 3) + ret i1 %0 + } + + define i1 @isinf_d(double %x) { + entry: + %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 516) + ret i1 %0 + } + + define i1 @isfinite_d(double %x) { + entry: + %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 504) + ret i1 %0 + } + + define i1 @isnormal_d(double %x) { + entry: + %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 264) + ret i1 %0 + } + + define i1 @issubnormal_d(double %x) { + entry: + %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 144) + ret i1 %0 + } + + define i1 @iszero_d(double %x) { + entry: + %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 96) + ret i1 %0 + } + + define i1 @issignaling_d(double %x) { + entry: + %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 1) + ret i1 %0 + } + + define i1 @isquiet_d(double %x) { + entry: + %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 2) + ret i1 %0 + } + + ; Function Attrs: strictfp + define i1 @isnan_d_strictfp(double %x) #0 { + entry: + %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 3) + ret i1 %0 + } + + ; Function Attrs: strictfp + define i1 @iszero_d_strictfp(double %x) #0 { + entry: + %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 96) + ret i1 %0 + } + + ; Function Attrs: nofree nosync nounwind readnone willreturn + declare i1 @llvm.is.fpclass.f32(float, i32) #1 + + ; Function Attrs: nofree nosync nounwind readnone willreturn + declare i1 @llvm.is.fpclass.f64(double, i32) #1 + + attributes #0 = { strictfp } + attributes #1 = { nofree nosync nounwind readnone willreturn } + +... +--- +name: isnan_f +alignment: 16 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } + - { id: 2, class: _, preferred-register: '' } +body: | + bb.1.entry: + liveins: $xmm0 + + ; CHECK-LABEL: name: isnan_f + ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $xmm0 + ; CHECK-NEXT: [[FCMP:%[0-9]+]]:_(s8) = G_FCMP floatpred(uno), [[COPY]](s32), [[COPY]] + ; CHECK-NEXT: $al = COPY [[FCMP]](s8) + ; CHECK-NEXT: RET 0, implicit $al + %0:_(s32) = COPY $xmm0 + %1:_(s1) = nofpexcept G_IS_FPCLASS %0(s32), 3, 2 + %2:_(s8) = G_ANYEXT %1(s1) + $al = COPY %2(s8) + RET 0, implicit $al + +... +--- +name: isnot_nan_f +alignment: 16 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } + - { id: 2, class: _, preferred-register: '' } +body: | + bb.1.entry: + liveins: $xmm0 + + ; CHECK-LABEL: name: isnot_nan_f + ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $xmm0 + ; CHECK-NEXT: [[FCMP:%[0-9]+]]:_(s8) = G_FCMP floatpred(ord), [[COPY]](s32), [[COPY]] + ; CHECK-NEXT: $al = COPY [[FCMP]](s8) + ; CHECK-NEXT: RET 0, implicit $al + %0:_(s32) = COPY $xmm0 + %1:_(s1) = nofpexcept G_IS_FPCLASS %0(s32), 1020, 2 + %2:_(s8) = G_ANYEXT %1(s1) + $al = COPY %2(s8) + RET 0, implicit $al + +... +--- +name: issignaling_f +alignment: 16 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } + - { id: 2, class: _, preferred-register: '' } +body: | + bb.1.entry: + liveins: $xmm0 + + ; CHECK-LABEL: name: issignaling_f + ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $xmm0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 2147483647 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 2139095040 + ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY]], [[C]] + ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 2143289344 + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s8) = G_ICMP intpred(sgt), [[AND]](s32), [[C1]] + ; CHECK-NEXT: [[ICMP1:%[0-9]+]]:_(s8) = G_ICMP intpred(slt), [[AND]](s32), [[C2]] + ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s8) = G_AND [[ICMP]], [[ICMP1]] + ; CHECK-NEXT: $al = COPY [[AND1]](s8) + ; CHECK-NEXT: RET 0, implicit $al + %0:_(s32) = COPY $xmm0 + %1:_(s1) = nofpexcept G_IS_FPCLASS %0(s32), 1, 2 + %2:_(s8) = G_ANYEXT %1(s1) + $al = COPY %2(s8) + RET 0, implicit $al + +... +--- +name: isquiet_f +alignment: 16 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } + - { id: 2, class: _, preferred-register: '' } +body: | + bb.1.entry: + liveins: $xmm0 + + ; CHECK-LABEL: name: isquiet_f + ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $xmm0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 2147483647 + ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY]], [[C]] + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 2143289344 + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s8) = G_ICMP intpred(sge), [[AND]](s32), [[C1]] + ; CHECK-NEXT: $al = COPY [[ICMP]](s8) + ; CHECK-NEXT: RET 0, implicit $al + %0:_(s32) = COPY $xmm0 + %1:_(s1) = nofpexcept G_IS_FPCLASS %0(s32), 2, 2 + %2:_(s8) = G_ANYEXT %1(s1) + $al = COPY %2(s8) + RET 0, implicit $al + +... +--- +name: isinf_f +alignment: 16 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } + - { id: 2, class: _, preferred-register: '' } +body: | + bb.1.entry: + liveins: $xmm0 + + ; CHECK-LABEL: name: isinf_f + ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $xmm0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 2147483647 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 2139095040 + ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY]], [[C]] + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s8) = G_ICMP intpred(eq), [[AND]](s32), [[C1]] + ; CHECK-NEXT: $al = COPY [[ICMP]](s8) + ; CHECK-NEXT: RET 0, implicit $al + %0:_(s32) = COPY $xmm0 + %1:_(s1) = nofpexcept G_IS_FPCLASS %0(s32), 516, 2 + %2:_(s8) = G_ANYEXT %1(s1) + $al = COPY %2(s8) + RET 0, implicit $al + +... +--- +name: is_plus_inf_f +alignment: 16 +legalized: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } + - { id: 2, class: _, preferred-register: '' } +body: | + bb.1.entry: + liveins: $xmm0 + + ; CHECK-LABEL: name: is_plus_inf_f + ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $xmm0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 2139095040 + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s8) = G_ICMP intpred(eq), [[COPY]](s32), [[C]] + ; CHECK-NEXT: $al = COPY [[ICMP]](s8) + ; CHECK-NEXT: RET 0, implicit $al + %0:_(s32) = COPY $xmm0 + %1:_(s1) = nofpexcept G_IS_FPCLASS %0(s32), 512, 2 + %2:_(s8) = G_ANYEXT %1(s1) + $al = COPY %2(s8) + RET 0, implicit $al + +... +--- +name: is_minus_inf_f +alignment: 16 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } + - { id: 2, class: _, preferred-register: '' } +body: | + bb.1.entry: + liveins: $xmm0 + + ; CHECK-LABEL: name: is_minus_inf_f + ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $xmm0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 -8388608 + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s8) = G_ICMP intpred(eq), [[COPY]](s32), [[C]] + ; CHECK-NEXT: $al = COPY [[ICMP]](s8) + ; CHECK-NEXT: RET 0, implicit $al + %0:_(s32) = COPY $xmm0 + %1:_(s1) = nofpexcept G_IS_FPCLASS %0(s32), 4, 2 + %2:_(s8) = G_ANYEXT %1(s1) + $al = COPY %2(s8) + RET 0, implicit $al + +... +--- +name: isfinite_f +alignment: 16 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } + - { id: 2, class: _, preferred-register: '' } +body: | + bb.1.entry: + liveins: $xmm0 + + ; CHECK-LABEL: name: isfinite_f + ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $xmm0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 2147483647 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 2139095040 + ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY]], [[C]] + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s8) = G_ICMP intpred(sgt), [[C1]](s32), [[AND]] + ; CHECK-NEXT: $al = COPY [[ICMP]](s8) + ; CHECK-NEXT: RET 0, implicit $al + %0:_(s32) = COPY $xmm0 + %1:_(s1) = nofpexcept G_IS_FPCLASS %0(s32), 504, 2 + %2:_(s8) = G_ANYEXT %1(s1) + $al = COPY %2(s8) + RET 0, implicit $al + +... +--- +name: is_plus_finite_f +alignment: 16 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } + - { id: 2, class: _, preferred-register: '' } +body: | + bb.1.entry: + liveins: $xmm0 + + ; CHECK-LABEL: name: is_plus_finite_f + ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $xmm0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 2139095040 + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s8) = G_ICMP intpred(ugt), [[C]](s32), [[COPY]] + ; CHECK-NEXT: $al = COPY [[ICMP]](s8) + ; CHECK-NEXT: RET 0, implicit $al + %0:_(s32) = COPY $xmm0 + %1:_(s1) = nofpexcept G_IS_FPCLASS %0(s32), 448, 2 + %2:_(s8) = G_ANYEXT %1(s1) + $al = COPY %2(s8) + RET 0, implicit $al + +... +--- +name: is_minus_finite_f +alignment: 16 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } + - { id: 2, class: _, preferred-register: '' } +body: | + bb.1.entry: + liveins: $xmm0 + + ; CHECK-LABEL: name: is_minus_finite_f + ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $xmm0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 2147483647 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 2139095040 + ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY]], [[C]] + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s8) = G_ICMP intpred(slt), [[COPY]](s32), [[C2]] + ; CHECK-NEXT: [[ICMP1:%[0-9]+]]:_(s8) = G_ICMP intpred(ugt), [[C1]](s32), [[AND]] + ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s8) = G_AND [[ICMP1]], [[ICMP]] + ; CHECK-NEXT: $al = COPY [[AND1]](s8) + ; CHECK-NEXT: RET 0, implicit $al + %0:_(s32) = COPY $xmm0 + %1:_(s1) = nofpexcept G_IS_FPCLASS %0(s32), 56, 2 + %2:_(s8) = G_ANYEXT %1(s1) + $al = COPY %2(s8) + RET 0, implicit $al + +... +--- +name: isnormal_f +alignment: 16 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } + - { id: 2, class: _, preferred-register: '' } +body: | + bb.1.entry: + liveins: $xmm0 + + ; CHECK-LABEL: name: isnormal_f + ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $xmm0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 2147483647 + ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY]], [[C]] + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 8388608 + ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[AND]], [[C1]] + ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 2130706432 + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s8) = G_ICMP intpred(ult), [[SUB]](s32), [[C2]] + ; CHECK-NEXT: $al = COPY [[ICMP]](s8) + ; CHECK-NEXT: RET 0, implicit $al + %0:_(s32) = COPY $xmm0 + %1:_(s1) = nofpexcept G_IS_FPCLASS %0(s32), 264, 2 + %2:_(s8) = G_ANYEXT %1(s1) + $al = COPY %2(s8) + RET 0, implicit $al + +... +--- +name: is_plus_normal_f +alignment: 16 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } + - { id: 2, class: _, preferred-register: '' } +body: | + bb.1.entry: + liveins: $xmm0 + + ; CHECK-LABEL: name: is_plus_normal_f + ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $xmm0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 2147483647 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s8) = G_CONSTANT i8 1 + ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY]], [[C]] + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s8) = G_ICMP intpred(slt), [[COPY]](s32), [[C1]] + ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 8388608 + ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[AND]], [[C3]] + ; CHECK-NEXT: [[C4:%[0-9]+]]:_(s32) = G_CONSTANT i32 2130706432 + ; CHECK-NEXT: [[ICMP1:%[0-9]+]]:_(s8) = G_ICMP intpred(ult), [[SUB]](s32), [[C4]] + ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s8) = G_XOR [[ICMP]], [[C2]] + ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s8) = G_AND [[ICMP1]], [[XOR]] + ; CHECK-NEXT: $al = COPY [[AND1]](s8) + ; CHECK-NEXT: RET 0, implicit $al + %0:_(s32) = COPY $xmm0 + %1:_(s1) = nofpexcept G_IS_FPCLASS %0(s32), 256, 2 + %2:_(s8) = G_ANYEXT %1(s1) + $al = COPY %2(s8) + RET 0, implicit $al + +... +--- +name: issubnormal_f +alignment: 16 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } + - { id: 2, class: _, preferred-register: '' } +body: | + bb.1.entry: + liveins: $xmm0 + + ; CHECK-LABEL: name: issubnormal_f + ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $xmm0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 2147483647 + ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY]], [[C]] + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 8388607 + ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 + ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[AND]], [[C2]] + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s8) = G_ICMP intpred(ult), [[SUB]](s32), [[C1]] + ; CHECK-NEXT: $al = COPY [[ICMP]](s8) + ; CHECK-NEXT: RET 0, implicit $al + %0:_(s32) = COPY $xmm0 + %1:_(s1) = nofpexcept G_IS_FPCLASS %0(s32), 144, 2 + %2:_(s8) = G_ANYEXT %1(s1) + $al = COPY %2(s8) + RET 0, implicit $al + +... +--- +name: is_plus_subnormal_f +alignment: 16 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } + - { id: 2, class: _, preferred-register: '' } +body: | + bb.1.entry: + liveins: $xmm0 + + ; CHECK-LABEL: name: is_plus_subnormal_f + ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $xmm0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 8388607 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 + ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[COPY]], [[C1]] + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s8) = G_ICMP intpred(ult), [[SUB]](s32), [[C]] + ; CHECK-NEXT: $al = COPY [[ICMP]](s8) + ; CHECK-NEXT: RET 0, implicit $al + %0:_(s32) = COPY $xmm0 + %1:_(s1) = nofpexcept G_IS_FPCLASS %0(s32), 128, 2 + %2:_(s8) = G_ANYEXT %1(s1) + $al = COPY %2(s8) + RET 0, implicit $al + +... +--- +name: is_minus_subnormal_f +alignment: 16 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } + - { id: 2, class: _, preferred-register: '' } +body: | + bb.1.entry: + liveins: $xmm0 + + ; CHECK-LABEL: name: is_minus_subnormal_f + ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $xmm0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 2147483647 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY]], [[C]] + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s8) = G_ICMP intpred(slt), [[COPY]](s32), [[C1]] + ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 8388607 + ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 + ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[AND]], [[C3]] + ; CHECK-NEXT: [[ICMP1:%[0-9]+]]:_(s8) = G_ICMP intpred(ult), [[SUB]](s32), [[C2]] + ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s8) = G_AND [[ICMP1]], [[ICMP]] + ; CHECK-NEXT: $al = COPY [[AND1]](s8) + ; CHECK-NEXT: RET 0, implicit $al + %0:_(s32) = COPY $xmm0 + %1:_(s1) = nofpexcept G_IS_FPCLASS %0(s32), 16, 2 + %2:_(s8) = G_ANYEXT %1(s1) + $al = COPY %2(s8) + RET 0, implicit $al + +... +--- +name: iszero_f +alignment: 16 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } + - { id: 2, class: _, preferred-register: '' } +body: | + bb.1.entry: + liveins: $xmm0 + + ; CHECK-LABEL: name: iszero_f + ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $xmm0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_FCONSTANT float 0.000000e+00 + ; CHECK-NEXT: [[FCMP:%[0-9]+]]:_(s8) = G_FCMP floatpred(oeq), [[COPY]](s32), [[C]] + ; CHECK-NEXT: $al = COPY [[FCMP]](s8) + ; CHECK-NEXT: RET 0, implicit $al + %0:_(s32) = COPY $xmm0 + %1:_(s1) = nofpexcept G_IS_FPCLASS %0(s32), 96, 2 + %2:_(s8) = G_ANYEXT %1(s1) + $al = COPY %2(s8) + RET 0, implicit $al + +... +--- +name: is_plus_zero_f +alignment: 16 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } + - { id: 2, class: _, preferred-register: '' } +body: | + bb.1.entry: + liveins: $xmm0 + + ; CHECK-LABEL: name: is_plus_zero_f + ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $xmm0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s8) = G_ICMP intpred(eq), [[COPY]](s32), [[C]] + ; CHECK-NEXT: $al = COPY [[ICMP]](s8) + ; CHECK-NEXT: RET 0, implicit $al + %0:_(s32) = COPY $xmm0 + %1:_(s1) = nofpexcept G_IS_FPCLASS %0(s32), 64, 2 + %2:_(s8) = G_ANYEXT %1(s1) + $al = COPY %2(s8) + RET 0, implicit $al + +... +--- +name: is_minus_zero_f +alignment: 16 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } + - { id: 2, class: _, preferred-register: '' } +body: | + bb.1.entry: + liveins: $xmm0 + + ; CHECK-LABEL: name: is_minus_zero_f + ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $xmm0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 -2147483648 + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s8) = G_ICMP intpred(eq), [[COPY]](s32), [[C]] + ; CHECK-NEXT: $al = COPY [[ICMP]](s8) + ; CHECK-NEXT: RET 0, implicit $al + %0:_(s32) = COPY $xmm0 + %1:_(s1) = nofpexcept G_IS_FPCLASS %0(s32), 32, 2 + %2:_(s8) = G_ANYEXT %1(s1) + $al = COPY %2(s8) + RET 0, implicit $al + +... +--- +name: isnan_f_strictfp +alignment: 16 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } + - { id: 2, class: _, preferred-register: '' } +body: | + bb.1.entry: + liveins: $xmm0 + + ; CHECK-LABEL: name: isnan_f_strictfp + ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $xmm0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 2147483647 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 2139095040 + ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY]], [[C]] + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s8) = G_ICMP intpred(sgt), [[AND]](s32), [[C1]] + ; CHECK-NEXT: $al = COPY [[ICMP]](s8) + ; CHECK-NEXT: RET 0, implicit $al + %0:_(s32) = COPY $xmm0 + %1:_(s1) = nofpexcept G_IS_FPCLASS %0(s32), 3, 2 + %2:_(s8) = G_ANYEXT %1(s1) + $al = COPY %2(s8) + RET 0, implicit $al + +... +--- +name: isfinite_f_strictfp +alignment: 16 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } + - { id: 2, class: _, preferred-register: '' } +body: | + bb.1.entry: + liveins: $xmm0 + + ; CHECK-LABEL: name: isfinite_f_strictfp + ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $xmm0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 2147483647 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 2139095040 + ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY]], [[C]] + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s8) = G_ICMP intpred(sgt), [[C1]](s32), [[AND]] + ; CHECK-NEXT: $al = COPY [[ICMP]](s8) + ; CHECK-NEXT: RET 0, implicit $al + %0:_(s32) = COPY $xmm0 + %1:_(s1) = nofpexcept G_IS_FPCLASS %0(s32), 504, 2 + %2:_(s8) = G_ANYEXT %1(s1) + $al = COPY %2(s8) + RET 0, implicit $al + +... +--- +name: iszero_f_strictfp +alignment: 16 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } + - { id: 2, class: _, preferred-register: '' } +body: | + bb.1.entry: + liveins: $xmm0 + + ; CHECK-LABEL: name: iszero_f_strictfp + ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $xmm0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 2147483647 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY]], [[C]] + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s8) = G_ICMP intpred(eq), [[AND]](s32), [[C1]] + ; CHECK-NEXT: $al = COPY [[ICMP]](s8) + ; CHECK-NEXT: RET 0, implicit $al + %0:_(s32) = COPY $xmm0 + %1:_(s1) = nofpexcept G_IS_FPCLASS %0(s32), 96, 2 + %2:_(s8) = G_ANYEXT %1(s1) + $al = COPY %2(s8) + RET 0, implicit $al + +... +--- +name: isnan_d +alignment: 16 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } + - { id: 2, class: _, preferred-register: '' } +body: | + bb.1.entry: + liveins: $xmm0 + + ; CHECK-LABEL: name: isnan_d + ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $xmm0 + ; CHECK-NEXT: [[FCMP:%[0-9]+]]:_(s8) = G_FCMP floatpred(uno), [[COPY]](s64), [[COPY]] + ; CHECK-NEXT: $al = COPY [[FCMP]](s8) + ; CHECK-NEXT: RET 0, implicit $al + %0:_(s64) = COPY $xmm0 + %1:_(s1) = nofpexcept G_IS_FPCLASS %0(s64), 3, 3 + %2:_(s8) = G_ANYEXT %1(s1) + $al = COPY %2(s8) + RET 0, implicit $al + +... +--- +name: isinf_d +alignment: 16 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } + - { id: 2, class: _, preferred-register: '' } +body: | + bb.1.entry: + liveins: $xmm0 + + ; CHECK-LABEL: name: isinf_d + ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $xmm0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 9223372036854775807 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 9218868437227405312 + ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s64) = G_AND [[COPY]], [[C]] + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s8) = G_ICMP intpred(eq), [[AND]](s64), [[C1]] + ; CHECK-NEXT: $al = COPY [[ICMP]](s8) + ; CHECK-NEXT: RET 0, implicit $al + %0:_(s64) = COPY $xmm0 + %1:_(s1) = nofpexcept G_IS_FPCLASS %0(s64), 516, 3 + %2:_(s8) = G_ANYEXT %1(s1) + $al = COPY %2(s8) + RET 0, implicit $al + +... +--- +name: isfinite_d +alignment: 16 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } + - { id: 2, class: _, preferred-register: '' } +body: | + bb.1.entry: + liveins: $xmm0 + + ; CHECK-LABEL: name: isfinite_d + ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $xmm0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 9223372036854775807 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 9218868437227405312 + ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s64) = G_AND [[COPY]], [[C]] + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s8) = G_ICMP intpred(sgt), [[C1]](s64), [[AND]] + ; CHECK-NEXT: $al = COPY [[ICMP]](s8) + ; CHECK-NEXT: RET 0, implicit $al + %0:_(s64) = COPY $xmm0 + %1:_(s1) = nofpexcept G_IS_FPCLASS %0(s64), 504, 3 + %2:_(s8) = G_ANYEXT %1(s1) + $al = COPY %2(s8) + RET 0, implicit $al + +... +--- +name: isnormal_d +alignment: 16 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } + - { id: 2, class: _, preferred-register: '' } +body: | + bb.1.entry: + liveins: $xmm0 + + ; CHECK-LABEL: name: isnormal_d + ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $xmm0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 9223372036854775807 + ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s64) = G_AND [[COPY]], [[C]] + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 4503599627370496 + ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s64) = G_SUB [[AND]], [[C1]] + ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 9214364837600034816 + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s8) = G_ICMP intpred(ult), [[SUB]](s64), [[C2]] + ; CHECK-NEXT: $al = COPY [[ICMP]](s8) + ; CHECK-NEXT: RET 0, implicit $al + %0:_(s64) = COPY $xmm0 + %1:_(s1) = nofpexcept G_IS_FPCLASS %0(s64), 264, 3 + %2:_(s8) = G_ANYEXT %1(s1) + $al = COPY %2(s8) + RET 0, implicit $al + +... +--- +name: issubnormal_d +alignment: 16 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } + - { id: 2, class: _, preferred-register: '' } +body: | + bb.1.entry: + liveins: $xmm0 + + ; CHECK-LABEL: name: issubnormal_d + ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $xmm0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 9223372036854775807 + ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s64) = G_AND [[COPY]], [[C]] + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 4503599627370495 + ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 1 + ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s64) = G_SUB [[AND]], [[C2]] + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s8) = G_ICMP intpred(ult), [[SUB]](s64), [[C1]] + ; CHECK-NEXT: $al = COPY [[ICMP]](s8) + ; CHECK-NEXT: RET 0, implicit $al + %0:_(s64) = COPY $xmm0 + %1:_(s1) = nofpexcept G_IS_FPCLASS %0(s64), 144, 3 + %2:_(s8) = G_ANYEXT %1(s1) + $al = COPY %2(s8) + RET 0, implicit $al + +... +--- +name: iszero_d +alignment: 16 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } + - { id: 2, class: _, preferred-register: '' } +body: | + bb.1.entry: + liveins: $xmm0 + + ; CHECK-LABEL: name: iszero_d + ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $xmm0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_FCONSTANT double 0.000000e+00 + ; CHECK-NEXT: [[FCMP:%[0-9]+]]:_(s8) = G_FCMP floatpred(oeq), [[COPY]](s64), [[C]] + ; CHECK-NEXT: $al = COPY [[FCMP]](s8) + ; CHECK-NEXT: RET 0, implicit $al + %0:_(s64) = COPY $xmm0 + %1:_(s1) = nofpexcept G_IS_FPCLASS %0(s64), 96, 3 + %2:_(s8) = G_ANYEXT %1(s1) + $al = COPY %2(s8) + RET 0, implicit $al + +... +--- +name: issignaling_d +alignment: 16 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } + - { id: 2, class: _, preferred-register: '' } +body: | + bb.1.entry: + liveins: $xmm0 + + ; CHECK-LABEL: name: issignaling_d + ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $xmm0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 9223372036854775807 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 9218868437227405312 + ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s64) = G_AND [[COPY]], [[C]] + ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 9221120237041090560 + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s8) = G_ICMP intpred(sgt), [[AND]](s64), [[C1]] + ; CHECK-NEXT: [[ICMP1:%[0-9]+]]:_(s8) = G_ICMP intpred(slt), [[AND]](s64), [[C2]] + ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s8) = G_AND [[ICMP]], [[ICMP1]] + ; CHECK-NEXT: $al = COPY [[AND1]](s8) + ; CHECK-NEXT: RET 0, implicit $al + %0:_(s64) = COPY $xmm0 + %1:_(s1) = nofpexcept G_IS_FPCLASS %0(s64), 1, 3 + %2:_(s8) = G_ANYEXT %1(s1) + $al = COPY %2(s8) + RET 0, implicit $al + +... +--- +name: isquiet_d +alignment: 16 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } + - { id: 2, class: _, preferred-register: '' } +body: | + bb.1.entry: + liveins: $xmm0 + + ; CHECK-LABEL: name: isquiet_d + ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $xmm0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 9223372036854775807 + ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s64) = G_AND [[COPY]], [[C]] + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 9221120237041090560 + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s8) = G_ICMP intpred(sge), [[AND]](s64), [[C1]] + ; CHECK-NEXT: $al = COPY [[ICMP]](s8) + ; CHECK-NEXT: RET 0, implicit $al + %0:_(s64) = COPY $xmm0 + %1:_(s1) = nofpexcept G_IS_FPCLASS %0(s64), 2, 3 + %2:_(s8) = G_ANYEXT %1(s1) + $al = COPY %2(s8) + RET 0, implicit $al + +... +--- +name: isnan_d_strictfp +alignment: 16 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } + - { id: 2, class: _, preferred-register: '' } +body: | + bb.1.entry: + liveins: $xmm0 + + ; CHECK-LABEL: name: isnan_d_strictfp + ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $xmm0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 9223372036854775807 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 9218868437227405312 + ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s64) = G_AND [[COPY]], [[C]] + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s8) = G_ICMP intpred(sgt), [[AND]](s64), [[C1]] + ; CHECK-NEXT: $al = COPY [[ICMP]](s8) + ; CHECK-NEXT: RET 0, implicit $al + %0:_(s64) = COPY $xmm0 + %1:_(s1) = nofpexcept G_IS_FPCLASS %0(s64), 3, 3 + %2:_(s8) = G_ANYEXT %1(s1) + $al = COPY %2(s8) + RET 0, implicit $al + +... +--- +name: iszero_d_strictfp +alignment: 16 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } + - { id: 2, class: _, preferred-register: '' } +body: | + bb.1.entry: + liveins: $xmm0 + + ; CHECK-LABEL: name: iszero_d_strictfp + ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $xmm0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 9223372036854775807 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 + ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s64) = G_AND [[COPY]], [[C]] + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s8) = G_ICMP intpred(eq), [[AND]](s64), [[C1]] + ; CHECK-NEXT: $al = COPY [[ICMP]](s8) + ; CHECK-NEXT: RET 0, implicit $al + %0:_(s64) = COPY $xmm0 + %1:_(s1) = nofpexcept G_IS_FPCLASS %0(s64), 96, 3 + %2:_(s8) = G_ANYEXT %1(s1) + $al = COPY %2(s8) + RET 0, implicit $al + +...