Пример #1
0
        [DebuggerNonUserCode] public BlockExpander(Block source, ExpansionContext ctx)
        {
            Source = source;
            Ctx = ctx;

            Stmts = new Block();
            ctx.Scope = Stmts;
            var cloned_locals = source.Locals.Select(l => l.DeepClone());
            cloned_locals.ForEach(local => ctx.Scope.Locals.Add(local));

            var is_root = Ctx.Parent == null || (Ctx.Parent.Stack.Count() != Ctx.Stack.Count());
            if (is_root) RetLabel = new Label();
            else RetLabel.AssertNotNull();

            source.ForEach(Expand);
            if (is_root && Stmts.LastOrDefault() is Goto) Stmts.RemoveLast();
            var gotos = Stmts.Family().OfType<Goto>().Where(@goto => @goto.LabelId == RetLabel.Id).ToReadOnly();
            if (is_root && gotos.IsNotEmpty()) Stmts.Add(RetLabel);
        }
Пример #2
0
        private JitCompiler(CpuConfig config, Type t_kernel, TypeBuilder t_xformed)
        {
            _config = config;
            _t_kernel = t_kernel;
            _m_kernel = _t_kernel.GetMethod("RunKernel", BF.All);
            ValidateInputParameters();

            // todo. think how to support multiple methods: *Dims, *Idxes, synchronization points
            // todo. I'd even say that we should embed constants instead of Dims and cache such bodies between calls
            // todo. if some dimension is equal to 1, then strip off corresponding loop
            var lam = _m_kernel.Decompile();
            _hir = lam.Body;
            _params = lam.Sig.Syms;
            _locals = lam.Body.LocalsRecursive();
            _xhir = new Block();
            _tids.Add("x", new Local("tid_x", typeof(int)));
            _tids.Add("y", new Local("tid_y", typeof(int)));
            _tids.Add("z", new Local("tid_z", typeof(int)));
            _xhir.Locals.AddElements(_tids.Values);
            InferLocalAllocationHints();
            ReplicatePrivatelyAllocatedLocals();
            LiftLocallyAllocatedLocals();
            HoistGloballyAllocatedLocals();
            _callsToSyncThreads = _hir.Family().OfType<Eval>().Where(eval =>
            {
                var m1 = eval.InvokedMethod();
                var syncapi_syncThreads = typeof(ISyncApi).GetMethod("SyncThreads");
                return m1.Api() == syncapi_syncThreads;
            }).ToReadOnly(); 
            TransformBlock(_hir, _xhir, false);

            // todo. currently we don't support debuggable IL
            // the latter implies correct PDB-mappings and working watch for replicated vars
            _config.EmitDebuggableIL.AssertFalse();

            _t_xformed = t_xformed;
            _t_xformed.AddInterfaceImplementation(typeof(IBlockRunner));
            _m_xformed = _t_xformed.DefineMethod("RunBlock", MA.Public, typeof(void), typeof(int3).MkArray());
            _m_xformed.DefineParameter(1, ParmA.None, "blockIdx");
            CompileTransformedHir();
        }
Пример #3
0
        public static Block DoRestoreTypeIs(Block hir)
        {
            if (hir.Family().OfType<TypeAs>().None()) return hir;
            else
            {
                return hir.Transform((Operator op) =>
                {
                    var is_rel = op.OperatorType.IsRelational();
                    if (is_rel)
                    {
                        var bin = op.AssertCast<BinaryOperator>();
                        var opt = bin.OperatorType;

                        var needs_xform = bin.Lhs is TypeAs ^ bin.Rhs is TypeAs;
                        if (needs_xform)
                        {
                            var type_as = bin.Lhs as TypeAs ?? bin.Rhs as TypeAs;
                            var other = bin.Lhs == type_as ? bin.Rhs : bin.Lhs;
                            other.AssertCast<Const>().AssertThat(c => c.Value == null);

                            var pos = opt == OperatorType.NotEqual || opt == OperatorType.GreaterThan;
                            var neg = opt == OperatorType.Equal || opt == OperatorType.LessThanOrEqual;
                            (pos || neg).AssertTrue();

                            var type_is = new TypeIs(type_as.Type, type_as.Target) as Expression;
                            return pos ? type_is : Operator.Negate(type_is);
                        }
                        else
                        {
                            return op.DefaultTransform();
                        }
                    }
                    else
                    {
                        return op.DefaultTransform();
                    }
                }).AssertCast<Block>();
            }
        }
Пример #4
0
        public static void DoInferLoopIters(Block hir)
        {
            foreach (var loop in hir.Family().OfType<Loop>())
            {
                if (loop.Iter.IsNotEmpty())
                {
                    loop.Iter.RemoveElements(n => n == null);
                }
                else
                {
                    if (loop.Init.IsNotEmpty())
                    {
                        Func<Expression, bool> isLvalueOfLool = e =>
                        {
                            if (e == null)
                            {
                                return false;
                            }
                            else if (e is Ref)
                            {
                                var @ref = e.AssertCast<Ref>();
                                var local = @ref == null ? null : @ref.Sym as Local;
                                return local != null && loop.Locals.Contains(local);
                            }
                            else if (e is Slot)
                            {
                                var slot = e.AssertCast<Slot>();
                                var @ref = slot == null ? null : slot.This as Ref;
                                var local = @ref == null ? null : @ref.Sym as Local;
                                return local != null && loop.Locals.Contains(local);
                            }
                            else if (e is Apply)
                            {
                                var app = e.AssertCast<Apply>();
                                var callee = app == null ? null : app.Callee;
                                var prop = callee as Prop;
                                var @ref = prop == null ? null : prop.This as Ref;
                                var local = @ref == null ? null : @ref.Sym as Local;
                                return local != null && loop.Locals.Contains(local);
                            }
                            else
                            {
                                return false;
                            }
                        };

                        var lil = loop.Body.LastOrDefault() as Expression;
                        var lilIsIter = false;
                        if (lil is Assign)
                        {
                            var ass = lil.AssertCast<Assign>();
                            lilIsIter = isLvalueOfLool(ass.Lhs);
                        }
                        else if (lil is Operator)
                        {
                            var op = lil.AssertCast<Operator>();
                            if (op.OperatorType.IsAssign())
                            {
                                lilIsIter = isLvalueOfLool(op.Args.First());
                            }
                        }
                        else if (lil is Eval)
                        {
                            var m = lil.InvokedMethod();
                            if (m != null)
                            {
                                var args = lil.InvocationArgs();
                                if (m.IsInstance() || m.IsExtension())
                                {
                                    lilIsIter = isLvalueOfLool(args.FirstOrDefault());
                                }
                                else
                                {
                                    lilIsIter = args.Any(isLvalueOfLool);
                                }
                            }
                        }

                        if (lilIsIter)
                        {
                            loop.Iter = new Block();
                            loop.Iter.Add(lil);
                            loop.Body.Remove(lil);
                        }
                    }
                }
            }
        }