public void OptimizeTrivial() { var asm = DecodeAssembly(@" #assembly(Test, { #type(Int32, #(), #(), { #fn(Factorial, true, #(), Int32, #(#param(Int32, value)), #(), { #entry_point(ep, #(#param(Int32, value)), { }, #switch( copy(Int32)(value), recurse(), { #case(#(0, 1), base_case()); })); #block(base_case, #(), { }, #return(const(1, Int32)())); #block(recurse, #(), { one = const(1, Int32)(); value_minus_one = intrinsic(`int.add`, Int32, #(Int32, Int32))(value, one); prev_fac = call(Int32.Factorial(Int32) => Int32, static)(value_minus_one); result = intrinsic(`int.mul`, Int32, #(Int32, Int32))(prev_fac, value); }, #return(copy(Int32)(result))); }); }); });"); var optimizer = new OnDemandOptimizer(EmptyArray <Optimization> .Value); var factorial = asm.Types.Single().Methods.Single(); Assert.AreEqual( OnDemandOptimizer.GetInitialMethodBodyDefault(factorial), optimizer.GetBodyAsync(factorial).Result); }
private static Task <AssemblyContentDescription> CreateContentDescriptionAsync( IMethod method, IEnumerable <ITypeMember> memberRoots, IEnumerable <IType> typeRoots, ClrAssembly assembly) { // TODO: deduplicate this logic (it also appears in IL2LLVM and ILOpt) var typeSystem = assembly.Resolver.TypeEnvironment; var pipeline = new Optimization[] { new ConstantPropagation(), MemoryAccessElimination.Instance, DeadValueElimination.Instance, new JumpThreading(true), SwitchSimplification.Instance, DuplicateReturns.Instance, TailRecursionElimination.Instance, BlockFusion.Instance }; var optimizer = new OnDemandOptimizer( pipeline, m => GetInitialMethodBody(m, typeSystem)); return(AssemblyContentDescription.CreateTransitiveAsync( new SimpleName("kernel").Qualify(), assembly.Attributes, null, new ITypeMember[] { method }.Concat(memberRoots), typeRoots, optimizer)); }
private static Flame.Compiler.MethodBody GetInitialMethodBody(IMethod method, TypeEnvironment typeSystem) { // TODO: deduplicate this logic (it also appears in IL2LLVM and ILOpt) var body = OnDemandOptimizer.GetInitialMethodBodyDefault(method); if (body == null) { return(null); } // Validate the method body. var errors = body.Validate(); if (errors.Count > 0) { var sourceIr = FormatIr(body); var exceptionLog = new TestLog(new[] { Severity.Error }, NullLog.Instance); exceptionLog.Log( new LogEntry( Severity.Error, "invalid IR", Quotation.QuoteEvenInBold( "the Flame IR produced by the CIL analyzer for ", method.FullName.ToString(), " is erroneous."), CreateRemark( "errors in IR:", new BulletedList(errors.Select(x => new Text(x)).ToArray())), CreateRemark( "generated Flame IR:", new Paragraph(new WrapBox(sourceIr, 0, -sourceIr.Length))))); return(null); } // Register some analyses and clean up the CFG before we actually start to optimize it. return(body.WithImplementation( body.Implementation .WithAnalysis( new ConstantAnalysis <SubtypingRules>( typeSystem.Subtyping)) .WithAnalysis( new ConstantAnalysis <PermissiveExceptionDelayability>( PermissiveExceptionDelayability.Instance)) .Transform( AllocaToRegister.Instance, CopyPropagation.Instance, new ConstantPropagation(), CanonicalizeDelegates.Instance, InstructionSimplification.Instance))); }
public void OptimizeDependency() { var asm = DecodeAssembly(@" #assembly(Test, { #type(Float64, #(), #(), { #fn(Id1, true, #(), Float64, #(#param(Float64, value)), #(), { #entry_point(ep, #(#param(Float64, value)), { }, #return(copy(Float64)(value))); }); #fn(Id2, true, #(), Float64, #(#param(Float64, value)), #(), { #entry_point(ep, #(#param(Float64, value)), { ptr = alloca(Float64)(); value_copy1 = store(Float64)(ptr, value); value_copy2 = load(Float64)(ptr); ret_val = call(Float64.Id1(Float64) => Float64, static)(value_copy2); }, #return(copy(Float64)(ret_val))); }); }); });"); var id1 = asm.Types.Single().Methods.Single(m => m.Name.ToString() == "Id1"); var id2 = asm.Types.Single().Methods.Single(m => m.Name.ToString() == "Id2"); var optimizer1 = new OnDemandOptimizer(new Optimization[] { new BlockingOptimization(id1), AllocaToRegister.Instance, new JumpThreading(true) }); optimizer1.GetBodyAsync(id1).Wait(); Assert.AreNotEqual( OnDemandOptimizer.GetInitialMethodBodyDefault(id2), optimizer1.GetBodyAsync(id2).Result); var optimizer2 = new OnDemandOptimizer(new Optimization[] { new BlockingOptimization(id1), AllocaToRegister.Instance, new JumpThreading(true) }); Assert.AreNotEqual( OnDemandOptimizer.GetInitialMethodBodyDefault(id2), optimizer2.GetBodyAsync(id2).Result); }