Index: llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp +++ llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp @@ -462,6 +462,14 @@ bool SelectCVTFixedPosOperand(SDValue N, SDValue &FixedPos, unsigned Width); + template + bool SelectCVTFixedPosRecipOperand(SDValue N, SDValue &FixedPos) { + return SelectCVTFixedPosRecipOperand(N, FixedPos, RegWidth); + } + + bool SelectCVTFixedPosRecipOperand(SDValue N, SDValue &FixedPos, + unsigned Width); + bool SelectCMP_SWAP(SDNode *N); bool SelectSVEAddSubImm(SDValue N, MVT VT, SDValue &Imm, SDValue &Shift); @@ -3625,9 +3633,10 @@ return true; } -bool -AArch64DAGToDAGISel::SelectCVTFixedPosOperand(SDValue N, SDValue &FixedPos, - unsigned RegWidth) { +static bool checkCVTFixedPointOperandWithFBits(SelectionDAG *CurDAG, SDValue N, + SDValue &FixedPos, + unsigned RegWidth, + bool isReciprocal) { APFloat FVal(0.0); if (ConstantFPSDNode *CN = dyn_cast(N)) FVal = CN->getValueAPF(); @@ -3652,13 +3661,18 @@ // integers. bool IsExact; + if (isReciprocal) + if (!FVal.getExactInverse(&FVal)) + return false; + // fbits is between 1 and 64 in the worst-case, which means the fmul // could have 2^64 as an actual operand. Need 65 bits of precision. APSInt IntVal(65, true); FVal.convertToInteger(IntVal, APFloat::rmTowardZero, &IsExact); // N.b. isPowerOf2 also checks for > 0. - if (!IsExact || !IntVal.isPowerOf2()) return false; + if (!IsExact || !IntVal.isPowerOf2()) + return false; unsigned FBits = IntVal.logBase2(); // Checks above should have guaranteed that we haven't lost information in @@ -3669,6 +3683,19 @@ return true; } +bool AArch64DAGToDAGISel::SelectCVTFixedPosOperand(SDValue N, SDValue &FixedPos, + unsigned RegWidth) { + return checkCVTFixedPointOperandWithFBits(CurDAG, N, FixedPos, RegWidth, + false); +} + +bool AArch64DAGToDAGISel::SelectCVTFixedPosRecipOperand(SDValue N, + SDValue &FixedPos, + unsigned RegWidth) { + return checkCVTFixedPointOperandWithFBits(CurDAG, N, FixedPos, RegWidth, + true); +} + // Inspects a register string of the form o0:op1:CRn:CRm:op2 gets the fields // of the string and obtains the integer values from them and combines these // into a single value to be used in the MRS/MSR instruction. Index: llvm/lib/Target/AArch64/AArch64ISelLowering.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -16609,11 +16609,45 @@ return FixConv; } -/// Fold a floating-point divide by power of two into fixed-point to -/// floating-point conversion. -static SDValue performFDivCombine(SDNode *N, SelectionDAG &DAG, - TargetLowering::DAGCombinerInfo &DCI, - const AArch64Subtarget *Subtarget) { +static SDValue tryCombineFDivWithFMul(SDNode *N, SelectionDAG &DAG, + TargetLowering::DAGCombinerInfo &DCI, + const AArch64Subtarget *Subtarget) { + SDValue Op0 = N->getOperand(0); + SDValue Op1 = N->getOperand(1); + EVT VT = N->getValueType(0); + SDLoc DL(N); + + if (Op0.getOpcode() != ISD::SINT_TO_FP) + return SDValue(); + + ConstantFPSDNode *CstFP = dyn_cast(Op1); + if (!CstFP) + return SDValue(); + + APFloat InverseAPFImm(0.0); + if (!CstFP->getValueAPF().getExactInverse(&InverseAPFImm)) + return SDValue(); + + bool IsExact; + APSInt InverseAPSIImm(65, true); + InverseAPFImm.convertToInteger(InverseAPSIImm, APFloat::rmTowardZero, + &IsExact); + + if (!IsExact || !InverseAPSIImm.isPowerOf2()) + return SDValue(); + + unsigned FBits = InverseAPSIImm.logBase2(); + if (FBits == 0 || FBits > VT.getScalarSizeInBits()) + return SDValue(); + + return DAG.getNode(ISD::FMUL, DL, VT, Op0, + DAG.getConstantFP(InverseAPFImm, DL, VT)); +} + +static SDValue +tryCombineFDivWithNeonIntrinsic(SDNode *N, SelectionDAG &DAG, + TargetLowering::DAGCombinerInfo &DCI, + const AArch64Subtarget *Subtarget) { if (!Subtarget->hasNEON()) return SDValue(); @@ -16678,6 +16712,18 @@ DAG.getConstant(C, DL, MVT::i32)); } +/// Fold a floating-point divide by power of two into fixed-point to +/// floating-point conversion. +static SDValue performFDivCombine(SDNode *N, SelectionDAG &DAG, + TargetLowering::DAGCombinerInfo &DCI, + const AArch64Subtarget *Subtarget) { + SDValue Op = N->getOperand(0); + if (Op.getValueType().isVector()) + return tryCombineFDivWithNeonIntrinsic(N, DAG, DCI, Subtarget); + else + return tryCombineFDivWithFMul(N, DAG, DCI, Subtarget); +} + /// An EXTR instruction is made up of two shifts, ORed together. This helper /// searches for and classifies those shifts. static bool findEXTRHalf(SDValue N, SDValue &Src, uint32_t &ShiftAmount, Index: llvm/lib/Target/AArch64/AArch64InstrFormats.td =================================================================== --- llvm/lib/Target/AArch64/AArch64InstrFormats.td +++ llvm/lib/Target/AArch64/AArch64InstrFormats.td @@ -703,6 +703,30 @@ def fixedpoint_f32_i64 : fixedpoint_i64; def fixedpoint_f64_i64 : fixedpoint_i64; +class fixedpoint_recip_i32 + : Operand, + ComplexPattern", [fpimm, ld]> { + let EncoderMethod = "getFixedPointScaleOpValue"; + let DecoderMethod = "DecodeFixedPointScaleImm32"; + let ParserMatchClass = Imm1_32Operand; +} + +class fixedpoint_recip_i64 + : Operand, + ComplexPattern", [fpimm, ld]> { + let EncoderMethod = "getFixedPointScaleOpValue"; + let DecoderMethod = "DecodeFixedPointScaleImm64"; + let ParserMatchClass = Imm1_64Operand; +} + +def fixedpoint_recip_f16_i32 : fixedpoint_recip_i32; +def fixedpoint_recip_f32_i32 : fixedpoint_recip_i32; +def fixedpoint_recip_f64_i32 : fixedpoint_recip_i32; + +def fixedpoint_recip_f16_i64 : fixedpoint_recip_i64; +def fixedpoint_recip_f32_i64 : fixedpoint_recip_i64; +def fixedpoint_recip_f64_i64 : fixedpoint_recip_i64; + def vecshiftR8 : Operand, ImmLeaf 0) && (((uint32_t)Imm) < 9); }]> { @@ -4981,8 +5005,8 @@ // Scaled def SWHri: BaseIntegerToFP { + (fmul (node GPR32:$Rn), + fixedpoint_recip_f16_i32:$scale))]> { let Inst{31} = 0; // 32-bit GPR flag let Inst{23-22} = 0b11; // 16-bit FPR flag let scale{5} = 1; @@ -4991,8 +5015,8 @@ def SWSri: BaseIntegerToFP { + (fmul (node GPR32:$Rn), + fixedpoint_recip_f32_i32:$scale))]> { let Inst{31} = 0; // 32-bit GPR flag let Inst{23-22} = 0b00; // 32-bit FPR flag let scale{5} = 1; @@ -5000,8 +5024,8 @@ def SWDri: BaseIntegerToFP { + (fmul (node GPR32:$Rn), + fixedpoint_recip_f64_i32:$scale))]> { let Inst{31} = 0; // 32-bit GPR flag let Inst{23-22} = 0b01; // 64-bit FPR flag let scale{5} = 1; @@ -5009,8 +5033,8 @@ def SXHri: BaseIntegerToFP { + (fmul (node GPR64:$Rn), + fixedpoint_recip_f16_i64:$scale))]> { let Inst{31} = 1; // 64-bit GPR flag let Inst{23-22} = 0b11; // 16-bit FPR flag let Predicates = [HasFullFP16]; @@ -5018,16 +5042,16 @@ def SXSri: BaseIntegerToFP { + (fmul (node GPR64:$Rn), + fixedpoint_recip_f32_i64:$scale))]> { let Inst{31} = 1; // 64-bit GPR flag let Inst{23-22} = 0b00; // 32-bit FPR flag } def SXDri: BaseIntegerToFP { + (fmul (node GPR64:$Rn), + fixedpoint_recip_f64_i64:$scale))]> { let Inst{31} = 1; // 64-bit GPR flag let Inst{23-22} = 0b01; // 64-bit FPR flag } Index: llvm/test/CodeGen/AArch64/fcvt-fixed.ll =================================================================== --- llvm/test/CodeGen/AArch64/fcvt-fixed.ll +++ llvm/test/CodeGen/AArch64/fcvt-fixed.ll @@ -331,7 +331,9 @@ define float @scvtf_f32_i32_7(i32 %int) { ; CHECK-LABEL: scvtf_f32_i32_7: ; CHECK: // %bb.0: -; CHECK-NEXT: scvtf s0, w0, #7 +; CHECK-NEXT: movi v0.2s, #67, lsl #24 +; CHECK-NEXT: scvtf s1, w0 +; CHECK-NEXT: fdiv s0, s1, s0 ; CHECK-NEXT: ret %cvt = sitofp i32 %int to float %fix = fdiv float %cvt, 128.0 @@ -341,7 +343,10 @@ define float @scvtf_f32_i32_32(i32 %int) { ; CHECK-LABEL: scvtf_f32_i32_32: ; CHECK: // %bb.0: -; CHECK-NEXT: scvtf s0, w0, #32 +; CHECK-NEXT: mov w8, #1333788672 // =0x4f800000 +; CHECK-NEXT: scvtf s0, w0 +; CHECK-NEXT: fmov s1, w8 +; CHECK-NEXT: fdiv s0, s0, s1 ; CHECK-NEXT: ret %cvt = sitofp i32 %int to float %fix = fdiv float %cvt, 4294967296.0 @@ -351,7 +356,9 @@ define float @scvtf_f32_i64_7(i64 %long) { ; CHECK-LABEL: scvtf_f32_i64_7: ; CHECK: // %bb.0: -; CHECK-NEXT: scvtf s0, x0, #7 +; CHECK-NEXT: movi v0.2s, #67, lsl #24 +; CHECK-NEXT: scvtf s1, x0 +; CHECK-NEXT: fdiv s0, s1, s0 ; CHECK-NEXT: ret %cvt = sitofp i64 %long to float %fix = fdiv float %cvt, 128.0 @@ -361,7 +368,10 @@ define float @scvtf_f32_i64_64(i64 %long) { ; CHECK-LABEL: scvtf_f32_i64_64: ; CHECK: // %bb.0: -; CHECK-NEXT: scvtf s0, x0, #64 +; CHECK-NEXT: mov w8, #1602224128 // =0x5f800000 +; CHECK-NEXT: scvtf s0, x0 +; CHECK-NEXT: fmov s1, w8 +; CHECK-NEXT: fdiv s0, s0, s1 ; CHECK-NEXT: ret %cvt = sitofp i64 %long to float %fix = fdiv float %cvt, 18446744073709551616.0 @@ -371,7 +381,10 @@ define double @scvtf_f64_i32_7(i32 %int) { ; CHECK-LABEL: scvtf_f64_i32_7: ; CHECK: // %bb.0: -; CHECK-NEXT: scvtf d0, w0, #7 +; CHECK-NEXT: mov x8, #4638707616191610880 // =0x4060000000000000 +; CHECK-NEXT: scvtf d0, w0 +; CHECK-NEXT: fmov d1, x8 +; CHECK-NEXT: fdiv d0, d0, d1 ; CHECK-NEXT: ret %cvt = sitofp i32 %int to double %fix = fdiv double %cvt, 128.0 @@ -381,7 +394,10 @@ define double @scvtf_f64_i32_32(i32 %int) { ; CHECK-LABEL: scvtf_f64_i32_32: ; CHECK: // %bb.0: -; CHECK-NEXT: scvtf d0, w0, #32 +; CHECK-NEXT: mov x8, #4751297606875873280 // =0x41f0000000000000 +; CHECK-NEXT: scvtf d0, w0 +; CHECK-NEXT: fmov d1, x8 +; CHECK-NEXT: fdiv d0, d0, d1 ; CHECK-NEXT: ret %cvt = sitofp i32 %int to double %fix = fdiv double %cvt, 4294967296.0 @@ -391,7 +407,10 @@ define double @scvtf_f64_i64_7(i64 %long) { ; CHECK-LABEL: scvtf_f64_i64_7: ; CHECK: // %bb.0: -; CHECK-NEXT: scvtf d0, x0, #7 +; CHECK-NEXT: mov x8, #4638707616191610880 // =0x4060000000000000 +; CHECK-NEXT: scvtf d0, x0 +; CHECK-NEXT: fmov d1, x8 +; CHECK-NEXT: fdiv d0, d0, d1 ; CHECK-NEXT: ret %cvt = sitofp i64 %long to double %fix = fdiv double %cvt, 128.0 @@ -401,7 +420,10 @@ define double @scvtf_f64_i64_64(i64 %long) { ; CHECK-LABEL: scvtf_f64_i64_64: ; CHECK: // %bb.0: -; CHECK-NEXT: scvtf d0, x0, #64 +; CHECK-NEXT: mov x8, #4895412794951729152 // =0x43f0000000000000 +; CHECK-NEXT: scvtf d0, x0 +; CHECK-NEXT: fmov d1, x8 +; CHECK-NEXT: fdiv d0, d0, d1 ; CHECK-NEXT: ret %cvt = sitofp i64 %long to double %fix = fdiv double %cvt, 18446744073709551616.0 @@ -421,7 +443,10 @@ ; ; CHECK-FP16-LABEL: scvtf_f16_i32_7: ; CHECK-FP16: // %bb.0: -; CHECK-FP16-NEXT: scvtf h0, w0, #7 +; CHECK-FP16-NEXT: mov w8, #22528 // =0x5800 +; CHECK-FP16-NEXT: scvtf h0, w0 +; CHECK-FP16-NEXT: fmov h1, w8 +; CHECK-FP16-NEXT: fdiv h0, h0, h1 ; CHECK-FP16-NEXT: ret %cvt = sitofp i32 %int to half %fix = fdiv half %cvt, 128.0 @@ -441,7 +466,10 @@ ; ; CHECK-FP16-LABEL: scvtf_f16_i32_15: ; CHECK-FP16: // %bb.0: -; CHECK-FP16-NEXT: scvtf h0, w0, #15 +; CHECK-FP16-NEXT: mov w8, #30720 // =0x7800 +; CHECK-FP16-NEXT: scvtf h0, w0 +; CHECK-FP16-NEXT: fmov h1, w8 +; CHECK-FP16-NEXT: fdiv h0, h0, h1 ; CHECK-FP16-NEXT: ret %cvt = sitofp i32 %int to half %fix = fdiv half %cvt, 32768.0 @@ -461,7 +489,10 @@ ; ; CHECK-FP16-LABEL: scvtf_f16_i64_7: ; CHECK-FP16: // %bb.0: -; CHECK-FP16-NEXT: scvtf h0, x0, #7 +; CHECK-FP16-NEXT: mov w8, #22528 // =0x5800 +; CHECK-FP16-NEXT: scvtf h0, x0 +; CHECK-FP16-NEXT: fmov h1, w8 +; CHECK-FP16-NEXT: fdiv h0, h0, h1 ; CHECK-FP16-NEXT: ret %cvt = sitofp i64 %long to half %fix = fdiv half %cvt, 128.0 @@ -481,7 +512,10 @@ ; ; CHECK-FP16-LABEL: scvtf_f16_i64_15: ; CHECK-FP16: // %bb.0: -; CHECK-FP16-NEXT: scvtf h0, x0, #15 +; CHECK-FP16-NEXT: mov w8, #30720 // =0x7800 +; CHECK-FP16-NEXT: scvtf h0, x0 +; CHECK-FP16-NEXT: fmov h1, w8 +; CHECK-FP16-NEXT: fdiv h0, h0, h1 ; CHECK-FP16-NEXT: ret %cvt = sitofp i64 %long to half %fix = fdiv half %cvt, 32768.0 @@ -493,7 +527,9 @@ define float @ucvtf_f32_i32_7(i32 %int) { ; CHECK-LABEL: ucvtf_f32_i32_7: ; CHECK: // %bb.0: -; CHECK-NEXT: ucvtf s0, w0, #7 +; CHECK-NEXT: movi v0.2s, #67, lsl #24 +; CHECK-NEXT: ucvtf s1, w0 +; CHECK-NEXT: fdiv s0, s1, s0 ; CHECK-NEXT: ret %cvt = uitofp i32 %int to float %fix = fdiv float %cvt, 128.0 @@ -503,7 +539,10 @@ define float @ucvtf_f32_i32_32(i32 %int) { ; CHECK-LABEL: ucvtf_f32_i32_32: ; CHECK: // %bb.0: -; CHECK-NEXT: ucvtf s0, w0, #32 +; CHECK-NEXT: mov w8, #1333788672 // =0x4f800000 +; CHECK-NEXT: ucvtf s0, w0 +; CHECK-NEXT: fmov s1, w8 +; CHECK-NEXT: fdiv s0, s0, s1 ; CHECK-NEXT: ret %cvt = uitofp i32 %int to float %fix = fdiv float %cvt, 4294967296.0 @@ -513,7 +552,9 @@ define float @ucvtf_f32_i64_7(i64 %long) { ; CHECK-LABEL: ucvtf_f32_i64_7: ; CHECK: // %bb.0: -; CHECK-NEXT: ucvtf s0, x0, #7 +; CHECK-NEXT: movi v0.2s, #67, lsl #24 +; CHECK-NEXT: ucvtf s1, x0 +; CHECK-NEXT: fdiv s0, s1, s0 ; CHECK-NEXT: ret %cvt = uitofp i64 %long to float %fix = fdiv float %cvt, 128.0 @@ -523,7 +564,10 @@ define float @ucvtf_f32_i64_64(i64 %long) { ; CHECK-LABEL: ucvtf_f32_i64_64: ; CHECK: // %bb.0: -; CHECK-NEXT: ucvtf s0, x0, #64 +; CHECK-NEXT: mov w8, #1602224128 // =0x5f800000 +; CHECK-NEXT: ucvtf s0, x0 +; CHECK-NEXT: fmov s1, w8 +; CHECK-NEXT: fdiv s0, s0, s1 ; CHECK-NEXT: ret %cvt = uitofp i64 %long to float %fix = fdiv float %cvt, 18446744073709551616.0 @@ -533,7 +577,10 @@ define double @ucvtf_f64_i32_7(i32 %int) { ; CHECK-LABEL: ucvtf_f64_i32_7: ; CHECK: // %bb.0: -; CHECK-NEXT: ucvtf d0, w0, #7 +; CHECK-NEXT: mov x8, #4638707616191610880 // =0x4060000000000000 +; CHECK-NEXT: ucvtf d0, w0 +; CHECK-NEXT: fmov d1, x8 +; CHECK-NEXT: fdiv d0, d0, d1 ; CHECK-NEXT: ret %cvt = uitofp i32 %int to double %fix = fdiv double %cvt, 128.0 @@ -543,7 +590,10 @@ define double @ucvtf_f64_i32_32(i32 %int) { ; CHECK-LABEL: ucvtf_f64_i32_32: ; CHECK: // %bb.0: -; CHECK-NEXT: ucvtf d0, w0, #32 +; CHECK-NEXT: mov x8, #4751297606875873280 // =0x41f0000000000000 +; CHECK-NEXT: ucvtf d0, w0 +; CHECK-NEXT: fmov d1, x8 +; CHECK-NEXT: fdiv d0, d0, d1 ; CHECK-NEXT: ret %cvt = uitofp i32 %int to double %fix = fdiv double %cvt, 4294967296.0 @@ -553,7 +603,10 @@ define double @ucvtf_f64_i64_7(i64 %long) { ; CHECK-LABEL: ucvtf_f64_i64_7: ; CHECK: // %bb.0: -; CHECK-NEXT: ucvtf d0, x0, #7 +; CHECK-NEXT: mov x8, #4638707616191610880 // =0x4060000000000000 +; CHECK-NEXT: ucvtf d0, x0 +; CHECK-NEXT: fmov d1, x8 +; CHECK-NEXT: fdiv d0, d0, d1 ; CHECK-NEXT: ret %cvt = uitofp i64 %long to double %fix = fdiv double %cvt, 128.0 @@ -563,7 +616,10 @@ define double @ucvtf_f64_i64_64(i64 %long) { ; CHECK-LABEL: ucvtf_f64_i64_64: ; CHECK: // %bb.0: -; CHECK-NEXT: ucvtf d0, x0, #64 +; CHECK-NEXT: mov x8, #4895412794951729152 // =0x43f0000000000000 +; CHECK-NEXT: ucvtf d0, x0 +; CHECK-NEXT: fmov d1, x8 +; CHECK-NEXT: fdiv d0, d0, d1 ; CHECK-NEXT: ret %cvt = uitofp i64 %long to double %fix = fdiv double %cvt, 18446744073709551616.0 @@ -583,7 +639,10 @@ ; ; CHECK-FP16-LABEL: ucvtf_f16_i32_7: ; CHECK-FP16: // %bb.0: -; CHECK-FP16-NEXT: ucvtf h0, w0, #7 +; CHECK-FP16-NEXT: mov w8, #22528 // =0x5800 +; CHECK-FP16-NEXT: ucvtf h0, w0 +; CHECK-FP16-NEXT: fmov h1, w8 +; CHECK-FP16-NEXT: fdiv h0, h0, h1 ; CHECK-FP16-NEXT: ret %cvt = uitofp i32 %int to half %fix = fdiv half %cvt, 128.0 @@ -603,7 +662,10 @@ ; ; CHECK-FP16-LABEL: ucvtf_f16_i32_15: ; CHECK-FP16: // %bb.0: -; CHECK-FP16-NEXT: ucvtf h0, w0, #15 +; CHECK-FP16-NEXT: mov w8, #30720 // =0x7800 +; CHECK-FP16-NEXT: ucvtf h0, w0 +; CHECK-FP16-NEXT: fmov h1, w8 +; CHECK-FP16-NEXT: fdiv h0, h0, h1 ; CHECK-FP16-NEXT: ret %cvt = uitofp i32 %int to half %fix = fdiv half %cvt, 32768.0 @@ -623,7 +685,10 @@ ; ; CHECK-FP16-LABEL: ucvtf_f16_i64_7: ; CHECK-FP16: // %bb.0: -; CHECK-FP16-NEXT: ucvtf h0, x0, #7 +; CHECK-FP16-NEXT: mov w8, #22528 // =0x5800 +; CHECK-FP16-NEXT: ucvtf h0, x0 +; CHECK-FP16-NEXT: fmov h1, w8 +; CHECK-FP16-NEXT: fdiv h0, h0, h1 ; CHECK-FP16-NEXT: ret %cvt = uitofp i64 %long to half %fix = fdiv half %cvt, 128.0 @@ -643,7 +708,10 @@ ; ; CHECK-FP16-LABEL: ucvtf_f16_i64_15: ; CHECK-FP16: // %bb.0: -; CHECK-FP16-NEXT: ucvtf h0, x0, #15 +; CHECK-FP16-NEXT: mov w8, #30720 // =0x7800 +; CHECK-FP16-NEXT: ucvtf h0, x0 +; CHECK-FP16-NEXT: fmov h1, w8 +; CHECK-FP16-NEXT: fdiv h0, h0, h1 ; CHECK-FP16-NEXT: ret %cvt = uitofp i64 %long to half %fix = fdiv half %cvt, 32768.0 Index: llvm/test/CodeGen/AArch64/svtcf-fmul-fdiv-combine.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/AArch64/svtcf-fmul-fdiv-combine.ll @@ -0,0 +1,112 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 +; RUN: llc -mtriple aarch64-none-linux-gnu < %s | FileCheck %s + +define float @scvtf_f32_2(i32 %state) { +; CHECK-LABEL: scvtf_f32_2: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: scvtf s0, w0, #1 +; CHECK-NEXT: ret +entry: + %conv = sitofp i32 %state to float + %div = fmul float %conv, 5.000000e-01 + ret float %div +} + +define float @scvtf_f32_4(i32 %state) { +; CHECK-LABEL: scvtf_f32_4: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: scvtf s0, w0, #2 +; CHECK-NEXT: ret +entry: + %conv = sitofp i32 %state to float + %div = fmul float %conv, 2.500000e-01 + ret float %div +} + +define float @scvtf_f32_8(i32 %state) { +; CHECK-LABEL: scvtf_f32_8: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: scvtf s0, w0, #3 +; CHECK-NEXT: ret +entry: + %conv = sitofp i32 %state to float + %div = fmul float %conv, 1.250000e-01 + ret float %div +} + +define float @scvtf_f32_16(i32 %state) { +; CHECK-LABEL: scvtf_f32_16: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: scvtf s0, w0, #4 +; CHECK-NEXT: ret +entry: + %conv = sitofp i32 %state to float + %div = fmul float %conv, 6.250000e-02 + ret float %div +} + +define float @scvtf_f32_32(i32 %state) { +; CHECK-LABEL: scvtf_f32_32: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: scvtf s0, w0, #5 +; CHECK-NEXT: ret +entry: + %conv = sitofp i32 %state to float + %div = fmul float %conv, 3.125000e-02 + ret float %div +} + +define double @scvtf_f64_2(i64 %state) { +; CHECK-LABEL: scvtf_f64_2: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: scvtf d0, x0, #1 +; CHECK-NEXT: ret +entry: + %conv = sitofp i64 %state to double + %div = fmul double %conv, 5.000000e-01 + ret double %div +} + +define double @scvtf_f64_4(i64 %state) { +; CHECK-LABEL: scvtf_f64_4: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: scvtf d0, x0, #2 +; CHECK-NEXT: ret +entry: + %conv = sitofp i64 %state to double + %div = fmul double %conv, 2.500000e-01 + ret double %div +} + +define double @scvtf_f64_8(i64 %state) { +; CHECK-LABEL: scvtf_f64_8: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: scvtf d0, x0, #3 +; CHECK-NEXT: ret +entry: + %conv = sitofp i64 %state to double + %div = fmul double %conv, 1.250000e-01 + ret double %div +} + +define double @scvtf_f64_16(i64 %state) { +; CHECK-LABEL: scvtf_f64_16: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: scvtf d0, x0, #4 +; CHECK-NEXT: ret +entry: + %conv = sitofp i64 %state to double + %div = fmul double %conv, 6.250000e-02 + ret double %div +} + +define double @scvtf_f64_32(i64 %state) { +; CHECK-LABEL: scvtf_f64_32: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: scvtf d0, x0, #5 +; CHECK-NEXT: ret +entry: + %conv = sitofp i64 %state to double + %div = fmul double %conv, 3.125000e-02 + ret double %div +}