コード例 #1
0
        /// <summary>
        /// Applies the UCE transformation.
        /// </summary>
        protected override bool PerformTransformation(Method.Builder builder)
        {
            var scope = builder.CreateScope();

            // Fold branch targets (if possible)
            bool updated = false;

            foreach (var block in scope)
            {
                // Get the conditional terminator
                var terminator = block.GetTerminatorAs <ConditionalBranch>();
                if (terminator == null || !terminator.CanFold)
                {
                    continue;
                }

                // Fold branch
                var blockBuilder = builder[block];
                terminator.Fold(blockBuilder);

                updated = true;
            }

            // Check for changes
            if (!updated)
            {
                return(false);
            }

            // Find all unreachable blocks
            var updatedScope = builder.CreateScope();

            foreach (var block in scope)
            {
                if (!updatedScope.Contains(block))
                {
                    // Block is unreachable -> remove all operations
                    var blockBuilder = builder[block];
                    blockBuilder.Clear();
                }
            }

            // Update all phi values
            Rewriter.Rewrite(
                updatedScope,
                builder,
                new PhiArgumentRemapper(updatedScope));

            return(true);
        }
コード例 #2
0
ファイル: IntrinsicResolver.cs プロジェクト: adamreeve/ILGPU
        /// <summary>
        /// Applies an intrinsic implementation transformation.
        /// </summary>
        protected override bool PerformTransformation(
            Method.Builder builder,
            IntrinsicImplementationProvider <TDelegate> .
            IRSpecializationPhase specializationPhase)
        {
            // Check whether we are currently processing an intrinsic method
            var scope = builder.CreateScope();

            bool applied = false;

            // Analyze intrinsic nodes
            foreach (Value value in scope.Values)
            {
                if (value is MethodCall methodCall)
                {
                    applied |= specializationPhase.RegisterIntrinsic(methodCall.Target);
                }
                else
                {
                    applied |= specializationPhase.RegisterIntrinsic(value);
                }
            }

            return(applied);
        }
コード例 #3
0
ファイル: SSAConstruction.cs プロジェクト: adamreeve/ILGPU
        /// <summary>
        /// Applies the SSA construction transformation.
        /// </summary>
        protected override bool PerformTransformation(Method.Builder builder)
        {
            // Create scope and try to find SSA-convertible alloca nodes
            var scope = builder.CreateScope(ScopeFlags.AddAlreadyVisitedNodes);

            // Search for convertible allocas
            var allocas = new HashSet <Alloca>();

            scope.ForEachValue <Alloca>(alloca =>
            {
                if (!alloca.IsSimpleAllocation ||
                    alloca.AddressSpace != MemoryAddressSpace.Local ||
                    RequiresAddress(alloca))
                {
                    return;
                }

                allocas.Add(alloca);
            });
            if (allocas.Count < 1)
            {
                return(false);
            }

            // Perform SSA construction
            var ssaBuilder = SSABuilder <Value> .Create(builder, scope);

            return(Rewriter.Rewrite(ssaBuilder, new ConstructionData(allocas)));
        }
コード例 #4
0
        protected bool PerformTransformation(
            Method.Builder builder,
            Rewriter <TypeLowering <TType> > rewriter)
        {
            var scope         = builder.CreateScope();
            var typeConverter = CreateLoweringConverter(builder, scope);

            // Use a static rewriter phase
            bool canRewriteBody = rewriter.TryBeginRewrite(
                scope,
                builder,
                typeConverter,
                out var rewriting);

            // Update return type
            if (typeConverter.IsTypeDependent(builder.Method.ReturnType))
            {
                builder.UpdateReturnType(typeConverter);
            }

            // Update parameter types
            builder.UpdateParameterTypes(typeConverter);

            // Apply the lowering logic
            return(canRewriteBody && rewriting.Rewrite());
        }
コード例 #5
0
ファイル: LowerArrays.cs プロジェクト: nguyenvuduc/ILGPU
        /// <summary cref="UnorderedTransformation.PerformTransformation(Method.Builder)"/>
        protected override bool PerformTransformation(Method.Builder builder)
        {
            // Detect all array values and their associated operations
            var scope  = builder.CreateScope();
            var arrays = FindConvertibleArrays(scope);

            // Transform dynamic arrays that requires dynamic addresses
            // to allocation nodes using memory operations
            foreach (var arrayBinding in arrays)
            {
                var array        = arrayBinding.Key;
                var arrayType    = array.Type as ArrayType;
                var blockBuilder = builder[array.BasicBlock];

                // Allocate a new raw allocation node
                blockBuilder.InsertPosition = 0;
                var arrayLength = blockBuilder.CreatePrimitiveValue(arrayType.Length);
                var rawArray    = blockBuilder.CreateAlloca(
                    arrayLength,
                    arrayType.ElementType,
                    MemoryAddressSpace.Local);
                blockBuilder.Remove(array);

                // Convert all operations to memory operations
                foreach (var operation in arrayBinding.Value)
                {
                    var currentBlockBuilder = builder[operation.BasicBlock];
                    currentBlockBuilder.SetupInsertPosition(operation);

                    var elementAddress = currentBlockBuilder.CreateLoadElementAddress(rawArray, operation.Index);

                    if (operation is SetElement setElement)
                    {
                        currentBlockBuilder.CreateStore(elementAddress, setElement.Value);
                        operation.Replace(rawArray);
                    }
                    else
                    {
                        var load = currentBlockBuilder.CreateLoad(elementAddress);
                        operation.Replace(load);
                    }
                    currentBlockBuilder.Remove(operation);
                }
            }

            return(arrays.Count > 0);
        }
コード例 #6
0
        /// <summary cref="UnorderedTransformation.PerformTransformation(Method.Builder)"/>
        protected override bool PerformTransformation(Method.Builder builder)
        {
            var scope = builder.CreateScope();
            var cfg   = scope.CreateCFG();

            bool result = false;

            var mergedNodes = new HashSet <CFG.Node>();

            foreach (var cfgNode in cfg)
            {
                if (mergedNodes.Contains(cfgNode))
                {
                    continue;
                }

                result |= MergeChain(builder, cfgNode, mergedNodes);
            }

            return(result);
        }
コード例 #7
0
        /// <summary cref="UnorderedTransformation.PerformTransformation(Method.Builder)"/>
        protected override bool PerformTransformation(Method.Builder builder)
        {
            var scope      = builder.CreateScope();
            var liveValues = FindLiveValues(scope);

            bool result = false;

            foreach (Value value in scope.Values)
            {
                if (liveValues.Contains(value))
                {
                    continue;
                }

                Debug.Assert(!(value is MemoryValue), "Invalid memory value");
                var blockBuilder = builder[value.BasicBlock];
                blockBuilder.Remove(value);
                result = true;
            }

            return(result);
        }
コード例 #8
0
        /// <summary cref="UnorderedTransformation.PerformTransformation(Method.Builder)"/>
        protected override bool PerformTransformation(Method.Builder builder)
        {
            var scope = builder.CreateScope();

            bool result = false;

            foreach (var block in scope)
            {
                var blockBuilder = builder[block];

                foreach (var valueEntry in block)
                {
                    if (valueEntry.Value is AddressSpaceCast cast && IsRedundant(cast))
                    {
                        cast.Replace(cast.Value);
                        blockBuilder.Remove(cast);
                        result = true;
                    }
                }
            }

            return(result);
        }
コード例 #9
0
        /// <summary cref="UnorderedTransformation.PerformTransformation(Method.Builder)"/>
        protected override bool PerformTransformation(Method.Builder builder)
        {
            // Create scope and try to find SSA-convertible alloca nodes
            var scope   = builder.CreateScope(ScopeFlags.AddAlreadyVisitedNodes);
            var allocas = FindConvertibleAllocas(scope);

            if (allocas.Count < 1)
            {
                return(false);
            }

            // Perform SSA construction
            var cfg        = scope.CreateCFG();
            var ssaBuilder = SSABuilder <Value> .Create(builder, cfg);

            var convertedNodes = new Dictionary <Value, FieldRef>();

            foreach (var block in scope)
            {
                if (!ssaBuilder.ProcessAndSeal(block))
                {
                    continue;
                }

                var blockBuilder = builder[block];
                foreach (var valueEntry in blockBuilder)
                {
                    // Move insert position to the current instruction
                    blockBuilder.SetupInsertPosition(valueEntry);

                    Value value = valueEntry;
                    switch (value)
                    {
                    case Alloca alloca:
                        if (allocas.Contains(alloca))
                        {
                            Debug.Assert(!alloca.IsArrayAllocation, "Unsupported dynamic allocation");
                            ssaBuilder.SetValue(
                                block,
                                alloca,
                                blockBuilder.CreateNull(alloca.AllocaType));

                            convertedNodes.Add(alloca, new FieldRef(alloca));
                            blockBuilder.Remove(alloca);
                        }
                        break;

                    case Load load:
                        if (convertedNodes.TryGetValue(load.Source, out FieldRef loadRef))
                        {
                            var ssaValue = ssaBuilder.GetValue(block, loadRef.Source);
                            ssaValue = blockBuilder.CreateGetField(ssaValue, loadRef.AccessChain);

                            load.Replace(ssaValue);
                            blockBuilder.Remove(load);
                        }
                        else if (!load.Uses.HasAny)
                        {
                            blockBuilder.Remove(load);
                        }
                        break;

                    case Store store:
                        if (convertedNodes.TryGetValue(store.Target, out FieldRef storeRef))
                        {
                            var ssaValue = ssaBuilder.GetValue(block, storeRef.Source);
                            ssaValue = blockBuilder.CreateSetField(
                                ssaValue,
                                storeRef.AccessChain,
                                store.Value);

                            ssaBuilder.SetValue(block, storeRef.Source, ssaValue);
                            blockBuilder.Remove(store);
                        }
                        break;

                    case LoadFieldAddress loadFieldAddress:
                        if (convertedNodes.TryGetValue(loadFieldAddress.Source, out FieldRef fieldRef))
                        {
                            convertedNodes.Add(
                                loadFieldAddress,
                                fieldRef.Access(loadFieldAddress.FieldIndex));
                            blockBuilder.Remove(loadFieldAddress);
                        }
                        break;

                    case AddressSpaceCast addressSpaceCast:
                        if (convertedNodes.TryGetValue(addressSpaceCast.Value, out FieldRef castRef))
                        {
                            convertedNodes.Add(
                                addressSpaceCast,
                                castRef);
                            blockBuilder.Remove(addressSpaceCast);
                        }
                        break;
                    }
                }
            }

            return(true);
        }
コード例 #10
0
ファイル: IfConversion.cs プロジェクト: nguyenvuduc/ILGPU
        /// <summary cref="UnorderedTransformation.PerformTransformation(Method.Builder)"/>
        protected override bool PerformTransformation(Method.Builder builder)
        {
            var scope   = builder.CreateScope();
            var cfg     = scope.CreateCFG();
            var ifInfos = IfInfos.Create(cfg);

            bool converted = false;

            foreach (IfInfo ifInfo in ifInfos)
            {
                // Check for an extremely simple if block to convert
                if (!ifInfo.IsSimpleIf())
                {
                    continue;
                }

                // Check size constraints
                int ifBlockSize   = ifInfo.IfBlock.Count;
                int elseBlockSize = ifInfo.ElseBlock.Count;
                int blockSizeDiff = IntrinsicMath.Abs(ifBlockSize - elseBlockSize);

                if (ifBlockSize > MaxBlockSize ||
                    elseBlockSize > MaxBlockSize ||
                    blockSizeDiff > DefaultMaxSizeDifference)
                {
                    continue;
                }

                // Check for side effects
                if (ifInfo.HasSideEffects())
                {
                    continue;
                }

                // Convert the current if block
                var variableInfo = ifInfo.ResolveVariableInfo();

                var blockBuilder = builder[ifInfo.EntryBlock];
                blockBuilder.MergeBlock(ifInfo.IfBlock);
                blockBuilder.MergeBlock(ifInfo.ElseBlock);
                blockBuilder.MergeBlock(ifInfo.ExitBlock);

                // Convert all phi values
                var condition = ifInfo.Condition;
                foreach (var variableEntry in variableInfo)
                {
                    var variable = variableEntry.Value;

                    blockBuilder.SetupInsertPosition(variableEntry.Key);
                    var predicate = blockBuilder.CreatePredicate(
                        condition,
                        variable.TrueValue,
                        variable.FalseValue);

                    // Replace the phi node
                    variableEntry.Key.Replace(predicate);
                    blockBuilder.Remove(variableEntry.Key);
                }

                converted = true;
            }

            return(converted);
        }
コード例 #11
0
        /// <summary>
        /// Applies a DCE transformation.
        /// </summary>
        protected override bool PerformTransformation(Method.Builder builder)
        {
            var scope     = builder.CreateScope();
            var toProcess = new Stack <Value>();

            // Mark all terminators and their values as non dead
            scope.ForEachTerminator <TerminatorValue>(terminator =>
            {
                foreach (var node in terminator.Nodes)
                {
                    toProcess.Push(node);
                }
            });

            // Mark all memory values as non dead (except dead loads)
            scope.ForEachValue <MemoryValue>(value =>
            {
                if (value.ValueKind != ValueKind.Load)
                {
                    toProcess.Push(value);
                }
            });

            // Mark all calls as non dead
            scope.ForEachValue <MethodCall>(call => toProcess.Push(call));

            // Mark all nodes as live
            var liveValues = new HashSet <Value>();

            while (toProcess.Count > 0)
            {
                var current = toProcess.Pop();
                if (!liveValues.Add(current))
                {
                    continue;
                }

                foreach (var node in current.Nodes)
                {
                    toProcess.Push(node.Resolve());
                }
            }

            // Remove all dead values
            bool updated = false;

            scope.ForEachValue <Value>(value =>
            {
                if (liveValues.Contains(value))
                {
                    return;
                }

                Debug.Assert(
                    !(value is MemoryValue) || value.ValueKind == ValueKind.Load,
                    "Invalid memory value");
                var blockBuilder = builder[value.BasicBlock];
                blockBuilder.Remove(value);

                updated = true;
            });

            return(updated);
        }