Пример #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
        // todo. verify that init and iter can live outside the thread loop (when insideThreadLoop is false)
        private void TransformLoop(Loop loop, Block xregion, bool insideThreadLoop)
        {
            var x_init = new Block(); TransformBlock(loop.Init, x_init, true);
            var x_test = TransformExpression(loop.Test, insideThreadLoop);
            var x_body = new Block(); TransformBlock(loop.Body, x_body, insideThreadLoop);
            var x_iter = new Block(); TransformBlock(loop.Iter, x_iter, true);

            var x_loop = new Loop(x_test, x_body);
            x_loop.Locals.SetElements(loop.Locals);
            x_loop.Init = new Block(x_init.Children);
            x_loop.Iter = new Block(x_iter.Children);
            xregion.Add(x_loop);
        }
Пример #3
0
 private void TransformExpression(Expression e, Block xregion, bool insideThreadLoop)
 {
     var xe = TransformExpression(e, insideThreadLoop);
     if (xe != null) xregion.Add(xe);
 }
Пример #4
0
 private void TransformIf(If @if, Block xregion, bool insideThreadLoop)
 {
     var x_test = TransformExpression(@if.Test, insideThreadLoop);
     var x_iftrue = new Block(); TransformBlock(@if.IfTrue, x_iftrue, insideThreadLoop);
     var x_iffalse = new Block(); TransformBlock(@if.IfFalse, x_iffalse, insideThreadLoop);
     xregion.Add(new If(x_test, x_iftrue, x_iffalse));
 }
Пример #5
0
        private void TransformBlock(Block hir, Block xhir, bool insideThreadLoop)
        {
            if (hir == null) return;

            var deepFission = new List<Node>();
            var regions = new List<ReadOnlyCollection<Node>>();
            var curr_region = new List<Node>();
            foreach (var stmt in hir)
            {
                if (_callsToSyncThreads.Contains(stmt as Eval))
                {
                    if (curr_region.IsNotEmpty()) regions.Add(curr_region.ToReadOnly());
                    curr_region = new List<Node>();
                }
                else if (_callsToSyncThreads.Any(c => Set.Intersect(c.Hierarchy(), stmt.MkArray()).IsNotEmpty()))
                {
                    if (curr_region.IsNotEmpty()) regions.Add(curr_region.ToReadOnly());
                    curr_region = new List<Node>();

                    deepFission.Add(stmt);
                    regions.Add(stmt.MkArray().ToReadOnly());
                }
                else
                {
                    curr_region.Add(stmt);
                }
            }
            if (curr_region.IsNotEmpty()) regions.Add(curr_region.ToReadOnly());
            curr_region = null;

            var privateLocals = hir.Locals.Where(l => Alloc(l) == allocPrivate).ToReadOnly();
            var privateUsages = privateLocals.ToDictionary(l => l, 
                l => regions.Where(r => r.UsagesOfLocal(l).IsNotEmpty()).ToReadOnly());
            privateUsages.ForEach(kvp =>
            {
                var needsReplication = kvp.Value.Count() > 1;
                _needsReplication[kvp.Key] = needsReplication;
                if (needsReplication)
                {
                    _xhir.Insert(_lastIndex++, _replicatedInits[kvp.Key]);
                    _xhir.Locals.Add(_replicatedLocals[kvp.Key]);
                }
            });

            foreach (var region in regions)
            {
                var xregion = new Block();

                var needsToBeWrapped = !deepFission.Contains(region.SingleOrDefault2());
                var regionIsInsideThreadLoop = insideThreadLoop || needsToBeWrapped;
                foreach (var stmt in region)
                {
                    if (stmt is Expression)
                    {
                        TransformExpression(((Expression)stmt), xregion, regionIsInsideThreadLoop);
                    }
                    else if (stmt is If)
                    {
                        TransformIf(((If)stmt), xregion, regionIsInsideThreadLoop);
                    }
                    else if (stmt is Loop)
                    {
                        TransformLoop(((Loop)stmt), xregion, regionIsInsideThreadLoop);
                    }
                    else
                    {
                        throw AssertionHelper.Fail();
                    }
                }

                if (needsToBeWrapped && !insideThreadLoop)
                {
                    xhir.Add(new Loop
                    {
                        Init = new Block(new Assign(new Ref(_tids["z"]), new Const(0))),
                        Test = Operator.LessThan(new Ref(_tids["z"]), new Fld(typeof(int3).GetField("Z"), new Prop(typeof(IGridApi).GetProperty("BlockDim"), new Ref(_this), true))),
                        Body = new Block(new Loop
                        {
                            Init = new Block(new Assign(new Ref(_tids["y"]), new Const(0))),
                            Test = Operator.LessThan(new Ref(_tids["y"]), new Fld(typeof(int3).GetField("Y"), new Prop(typeof(IGridApi).GetProperty("BlockDim"), new Ref(_this), true))),
                            Body = new Block(new Loop
                            {
                                Init = new Block(new Assign(new Ref(_tids["x"]), new Const(0))),
                                Test = Operator.LessThan(new Ref(_tids["x"]), new Fld(typeof(int3).GetField("X"), new Prop(typeof(IGridApi).GetProperty("BlockDim"), new Ref(_this), true))),
                                Body = new Block(xregion.Children),
                                Iter = new Block(Operator.PreIncrement(new Ref(_tids["x"]))),
                            }),
                            Iter = new Block(Operator.PreIncrement(new Ref(_tids["y"]))),
                        }),
                        Iter = new Block(Operator.PreIncrement(new Ref(_tids["z"]))),
                    });
                }
                else
                {
                    xhir.AddElements(xregion.Children);
                }
            }

            var locals = hir.Locals.Except(_liftedLocals).ToReadOnly();
            locals.ForEach(l => xhir.Locals.Add(l.DeepClone()));
        }