public static void I2F(EmitterContext context) { OpCodeAlu op = (OpCodeAlu)context.CurrOp; FPType dstType = (FPType)op.RawOpCode.Extract(8, 2); IntegerType srcType = (IntegerType)op.RawOpCode.Extract(10, 2); bool isSmallInt = srcType <= IntegerType.U16; bool isSignedInt = op.RawOpCode.Extract(13); bool negateB = op.RawOpCode.Extract(45); bool absoluteB = op.RawOpCode.Extract(49); Operand srcB = context.IAbsNeg(GetSrcB(context), absoluteB, negateB); if (isSmallInt) { int size = srcType == IntegerType.U16 ? 16 : 8; srcB = isSignedInt ? context.BitfieldExtractS32(srcB, Const(op.ByteSelection * 8), Const(size)) : context.BitfieldExtractU32(srcB, Const(op.ByteSelection * 8), Const(size)); } srcB = isSignedInt ? context.IConvertS32ToFP(srcB) : context.IConvertU32ToFP(srcB); WriteFP(context, dstType, srcB); // TODO: CC. }
public static void F2I(EmitterContext context) { OpCodeFArith op = (OpCodeFArith)context.CurrOp; IntegerType intType = (IntegerType)op.RawOpCode.Extract(8, 2); bool isSmallInt = intType <= IntegerType.U16; FPType floatType = (FPType)op.RawOpCode.Extract(10, 2); bool isSignedInt = op.RawOpCode.Extract(12); bool negateB = op.RawOpCode.Extract(45); bool absoluteB = op.RawOpCode.Extract(49); if (isSignedInt) { intType |= IntegerType.S8; } Operand srcB = context.FPAbsNeg(GetSrcB(context, floatType), absoluteB, negateB); switch (op.RoundingMode) { case RoundingMode.TowardsNegativeInfinity: srcB = context.FPFloor(srcB); break; case RoundingMode.TowardsPositiveInfinity: srcB = context.FPCeiling(srcB); break; case RoundingMode.TowardsZero: srcB = context.FPTruncate(srcB); break; } srcB = context.FPConvertToS32(srcB); // TODO: S/U64, conversion overflow handling. if (intType != IntegerType.S32) { int min = GetIntMin(intType); int max = GetIntMax(intType); srcB = isSignedInt ? context.IClampS32(srcB, Const(min), Const(max)) : context.IClampU32(srcB, Const(min), Const(max)); } Operand dest = GetDest(context); context.Copy(dest, srcB); // TODO: CC. }
public static void F2F(EmitterContext context) { OpCodeFArith op = (OpCodeFArith)context.CurrOp; FPType dstType = (FPType)op.RawOpCode.Extract(8, 2); FPType srcType = (FPType)op.RawOpCode.Extract(10, 2); bool round = op.RawOpCode.Extract(42); bool negateB = op.RawOpCode.Extract(45); bool absoluteB = op.RawOpCode.Extract(49); Operand srcB = context.FPAbsNeg(GetSrcB(context, srcType), absoluteB, negateB, srcType.ToInstFPType()); if (round && srcType == dstType) { switch (op.RoundingMode) { case RoundingMode.ToNearest: srcB = context.FPRound(srcB, srcType.ToInstFPType()); break; case RoundingMode.TowardsNegativeInfinity: srcB = context.FPFloor(srcB, srcType.ToInstFPType()); break; case RoundingMode.TowardsPositiveInfinity: srcB = context.FPCeiling(srcB, srcType.ToInstFPType()); break; case RoundingMode.TowardsZero: srcB = context.FPTruncate(srcB, srcType.ToInstFPType()); break; } } // We don't need to handle conversions between FP16 <-> FP32 // since we do FP16 operations as FP32 directly. // FP16 <-> FP64 conversions are invalid. if (srcType == FPType.FP32 && dstType == FPType.FP64) { srcB = context.FP32ConvertToFP64(srcB); } else if (srcType == FPType.FP64 && dstType == FPType.FP32) { srcB = context.FP64ConvertToFP32(srcB); } srcB = context.FPSaturate(srcB, op.Saturate, dstType.ToInstFPType()); WriteFP(context, dstType, srcB); // TODO: CC. }
public static IGpuHelper CreateHelper(ComputePlatform platform, ComputeDevice device, FPType fptype) { ComputeContextPropertyList properties = new ComputeContextPropertyList(platform); var context = new ComputeContext(new[] { device }, properties, null, IntPtr.Zero); if (fptype == FPType.Single) { return new GpuHelper<float>(context, fptype); } else { return new GpuHelper<double>(context, fptype); } }
private static void WriteFP(EmitterContext context, FPType type, Operand srcB) { Operand dest = GetDest(context); if (type == FPType.FP32) { context.Copy(dest, srcB); } else if (type == FPType.FP16) { context.Copy(dest, context.PackHalf2x16(srcB, ConstF(0))); } else { // TODO. } }
public static Operand GetSrcB(EmitterContext context, FPType floatType) { if (floatType == FPType.FP32) { return(GetSrcB(context)); } else if (floatType == FPType.FP16) { int h = context.CurrOp.RawOpCode.Extract(41, 1); return(GetHalfSources(context, GetSrcB(context), FPHalfSwizzle.FP16)[h]); } else if (floatType == FPType.FP64) { // TODO. } throw new ArgumentException($"Invalid floating point type \"{floatType}\"."); }
private static void WriteFP(EmitterContext context, FPType type, Operand srcB) { Operand dest = GetDest(context); if (type == FPType.FP32) { context.Copy(dest, srcB); } else if (type == FPType.FP16) { context.Copy(dest, context.PackHalf2x16(srcB, ConstF(0))); } else /* if (type == FPType.FP64) */ { Operand dest2 = GetDest2(context); context.Copy(dest, context.UnpackDouble2x32Low(srcB)); context.Copy(dest2, context.UnpackDouble2x32High(srcB)); } }
public static void F2F(EmitterContext context) { OpCodeFArith op = (OpCodeFArith)context.CurrOp; FPType dstType = (FPType)op.RawOpCode.Extract(8, 2); FPType srcType = (FPType)op.RawOpCode.Extract(10, 2); bool round = op.RawOpCode.Extract(42); bool negateB = op.RawOpCode.Extract(45); bool absoluteB = op.RawOpCode.Extract(49); Operand srcB = context.FPAbsNeg(GetSrcB(context, srcType), absoluteB, negateB); if (round) { switch (op.RoundingMode) { case RoundingMode.ToNearest: srcB = context.FPRound(srcB); break; case RoundingMode.TowardsNegativeInfinity: srcB = context.FPFloor(srcB); break; case RoundingMode.TowardsPositiveInfinity: srcB = context.FPCeiling(srcB); break; case RoundingMode.TowardsZero: srcB = context.FPTruncate(srcB); break; } } srcB = context.FPSaturate(srcB, op.Saturate); WriteFP(context, dstType, srcB); // TODO: CC. }
public static Operand GetSrcB(EmitterContext context, FPType floatType) { if (floatType == FPType.FP32) { return(GetSrcB(context)); } else if (floatType == FPType.FP16) { int h = context.CurrOp.RawOpCode.Extract(41, 1); return(GetHalfUnpacked(context, GetSrcB(context), FPHalfSwizzle.FP16)[h]); } else if (floatType == FPType.FP64) { // TODO: Double floating-point type support. } context.Config.PrintLog($"Invalid floating point type: {floatType}."); return(ConstF(0)); }
public static IGpuHelper CreateHelper(ComputePlatform platform, ComputeDevice device, FPType fptype) { ComputeContextPropertyList properties = new ComputeContextPropertyList(platform); var context = new ComputeContext(new[] { device }, properties, null, IntPtr.Zero); if (fptype == FPType.Single) { return(new GpuHelper <float>(context, fptype)); } else { return(new GpuHelper <double>(context, fptype)); } }
public GpuHelper(ComputeContext context, FPType fptype) { this.context = context; commands = new ComputeCommandQueue(context, context.Devices[0], ComputeCommandQueueFlags.None); this.fpType = fptype; }
public static Instruction ToInstFPType(this FPType type) { return(type == FPType.FP64 ? Instruction.FP64 : Instruction.FP32); }
public static GenericValue Create(FPType ty, double n) => LLVM.CreateGenericValueOfFloat(ty.Unwrap(), n).Wrap().MakeHandleOwner <GenericValue, LLVMGenericValueRef>();
public static void F2I(EmitterContext context) { OpCodeFArith op = (OpCodeFArith)context.CurrOp; IntegerType intType = (IntegerType)op.RawOpCode.Extract(8, 2); if (intType == IntegerType.U64) { context.Config.PrintLog("Unimplemented 64-bits F2I."); return; } bool isSmallInt = intType <= IntegerType.U16; FPType floatType = (FPType)op.RawOpCode.Extract(10, 2); bool isSignedInt = op.RawOpCode.Extract(12); bool negateB = op.RawOpCode.Extract(45); bool absoluteB = op.RawOpCode.Extract(49); if (isSignedInt) { intType |= IntegerType.S8; } Operand srcB = context.FPAbsNeg(GetSrcB(context, floatType), absoluteB, negateB); switch (op.RoundingMode) { case RoundingMode.ToNearest: srcB = context.FPRound(srcB); break; case RoundingMode.TowardsNegativeInfinity: srcB = context.FPFloor(srcB); break; case RoundingMode.TowardsPositiveInfinity: srcB = context.FPCeiling(srcB); break; case RoundingMode.TowardsZero: srcB = context.FPTruncate(srcB); break; } if (!isSignedInt) { // Negative float to uint cast is undefined, so we clamp // the value before conversion. srcB = context.FPMaximum(srcB, ConstF(0)); } srcB = isSignedInt ? context.FPConvertToS32(srcB) : context.FPConvertToU32(srcB); if (isSmallInt) { int min = (int)GetIntMin(intType); int max = (int)GetIntMax(intType); srcB = isSignedInt ? context.IClampS32(srcB, Const(min), Const(max)) : context.IClampU32(srcB, Const(min), Const(max)); } Operand dest = GetDest(context); context.Copy(dest, srcB); // TODO: CC. }
public static ConstantFP Get(FPType type, double value) => LLVM.ConstReal(type.Unwrap(), value).WrapAs <ConstantFP>();
private static Constant GetFP <TData>(FPType type, params TData[] data) => GetGeneric(type, (x, y) => ConstantFP.Get(x, y), data);