private static void ToReductionList( IEnumerable <ValueTag> arguments, InstructionPrototype prototype, List <ValueTag> reductionArgs, HashSet <ValueTag> reductionOps, ValueUses uses, FlowGraph graph) { foreach (var arg in arguments) { NamedInstruction insn; if (graph.TryGetInstruction(arg, out insn)) { ToReductionList( insn, prototype, reductionArgs, reductionOps, uses); } else { reductionArgs.Add(arg); } } }
private static bool TrySimplifyReduction( ref List <ValueTag> args, InstructionPrototype prototype, NamedInstructionBuilder insertionPoint) { bool changed = false; var newArgs = new List <ValueTag>(); foreach (var operand in args) { if (newArgs.Count > 0) { var prevOperand = newArgs[newArgs.Count - 1]; var folded = ConstantFold(prevOperand, operand, prototype, insertionPoint); if (folded == null) { newArgs.Add(operand); } else { newArgs[newArgs.Count - 1] = folded; changed = true; } } else { newArgs.Add(operand); } } args = newArgs; return(changed); }
/// <summary> /// Tests if an instruction prototype is a intrinsic prototype /// with a particular name defined in the current namespace. /// </summary> /// <param name="prototype"> /// The prototype to examine. /// </param> /// <param name="name"> /// The prototype name to expect. /// </param> /// <returns> /// <c>true</c> if the prototype is a namespaced intrinsic prototype /// with a name equal to <paramref name="name"/>; otherwise, <c>false</c>. /// </returns> public bool IsIntrinsicPrototype(InstructionPrototype prototype, string name) { string opName; return(prototype is IntrinsicPrototype && TryParseIntrinsicName(((IntrinsicPrototype)prototype).Name, out opName) && name == opName); }
/// <summary> /// Tells if a particular instruction prototype is a recursive call. /// </summary> /// <param name="prototype">The instruction prototype to inspect.</param> /// <returns> /// <c>true</c> if <paramref name="prototype"/> describes a recursive call; /// otherwise, <c>false</c>. /// </returns> private bool IsSelfCallPrototype(InstructionPrototype prototype) { if (prototype is CallPrototype) { var callProto = (CallPrototype)prototype; return(callProto.Lookup == MethodLookup.Static && callProto.Callee.Equals(Method)); } else { return(false); } }
/// <inheritdoc/> public override bool CanDelayExceptions(InstructionPrototype prototype) { if (prototype is UnboxPrototype || prototype is GetFieldPointerPrototype || prototype is NewDelegatePrototype) { return(true); } else if (prototype is IntrinsicPrototype) { var intrinsicProto = (IntrinsicPrototype)prototype; return(delayableIntrinsics.Contains(intrinsicProto.Name)); } else { return(false); } }
/// <summary> /// Tells if syntactically equivalent instances of a particular prototype /// are semantically equivalent. /// </summary> /// <param name="prototype">A prototype to consider.</param> /// <returns> /// <c>true</c> if syntactically equivalent instances of /// <paramref name="prototype"/> are semantically equivalent; /// otherwise, <c>false</c>. /// </returns> private static bool IsCopyablePrototype(InstructionPrototype prototype) { if (prototype is IntrinsicPrototype) { return(IsCopyableIntrinsic((IntrinsicPrototype)prototype)); } else { return(prototype is ConstantPrototype || prototype is CopyPrototype || prototype is DynamicCastPrototype || prototype is GetFieldPointerPrototype || prototype is GetStaticFieldPointerPrototype || prototype is NewDelegatePrototype || prototype is ReinterpretCastPrototype || prototype is UnboxPrototype); } }
/// <summary> /// The default constant instruction evaluation function. /// </summary> /// <param name="prototype"> /// The prorotype of the instruction to evaluate. /// </param> /// <param name="arguments"> /// A list of arguments to the instruction, all of which /// must be constants. /// </param> /// <returns> /// <c>null</c> if the instruction cannot be evaluated; otherwise, the constant /// to which the instruction evaluates. /// </returns> public static Constant EvaluateDefault( InstructionPrototype prototype, IReadOnlyList <Constant> arguments) { if (prototype is CopyPrototype || prototype is ReinterpretCastPrototype) { return(arguments[0]); } else if (prototype is ConstantPrototype) { var constProto = (ConstantPrototype)prototype; if (constProto.Value is DefaultConstant) { // Try to specialize 'default' constants. var intSpec = constProto.ResultType.GetIntegerSpecOrNull(); if (intSpec != null) { return(new IntegerConstant(0, intSpec)); } } return(constProto.Value); } else if (prototype is IntrinsicPrototype) { string arithOp; Constant result; if (ArithmeticIntrinsics.TryParseArithmeticIntrinsicName( ((IntrinsicPrototype)prototype).Name, out arithOp) && ArithmeticIntrinsics.TryEvaluate( arithOp, prototype.ResultType, arguments, out result)) { return(result); } } return(null); }
private static void MaterializeReduction( IReadOnlyList <ValueTag> args, InstructionPrototype prototype, NamedInstructionBuilder result) { if (args.Count == 1) { result.Instruction = Instruction.CreateCopy(result.ResultType, args[0]); return; } var accumulator = args[0]; for (int i = 1; i < args.Count - 1; i++) { accumulator = result.InsertBefore( prototype.Instantiate(new[] { accumulator, args[i] })); } result.Instruction = prototype.Instantiate(new[] { accumulator, args[args.Count - 1] }); }
public TSpec GetSpecification(InstructionPrototype prototype) { if (prototype is IntrinsicPrototype) { var intrinsic = (IntrinsicPrototype)prototype; Func <IntrinsicPrototype, TSpec> getIntrinsicSpec; if (intrinsicSpecs.TryGetValue(intrinsic.Name, out getIntrinsicSpec)) { return(getIntrinsicSpec(intrinsic)); } } Func <InstructionPrototype, TSpec> getInstructionSpec; if (instructionSpecs.TryGetValue(prototype.GetType(), out getInstructionSpec)) { return(getInstructionSpec(prototype)); } return(DefaultSpec); }
/// <inheritdoc/> public override ExceptionSpecification GetExceptionSpecification(InstructionPrototype prototype) { if (prototype is IntrinsicPrototype) { var intrinsic = (IntrinsicPrototype)prototype; Func <IntrinsicPrototype, ExceptionSpecification> getIntrinsicSpec; if (intrinsicSpecs.TryGetValue(intrinsic.Name, out getIntrinsicSpec)) { return(getIntrinsicSpec(intrinsic)); } } Func <InstructionPrototype, ExceptionSpecification> getInstructionSpec; if (instructionSpecs.TryGetValue(prototype.GetType(), out getInstructionSpec)) { return(getInstructionSpec(prototype)); } return(ExceptionSpecification.ThrowAny); }
private static bool IsDereferenceable(InstructionPrototype prototype) { // * Allocas always produce non-null pointers that // are dereferenceable. // // * Unbox instructions that succeed always produce // non-null pointers that are dereferenceable. If // they don't succeed, then an exception is thrown // and the result can't be used. // // * Get-field-pointer instructions that succeed // always produce non-null pointers that are // dereferenceable. If they don't succeed, then // an exception is thrown and the result can't be used. // // * Ditto for get-static-field-pointer instructions. return(prototype is AllocaPrototype || prototype is UnboxPrototype || prototype is GetFieldPointerPrototype || prototype is GetStaticFieldPointerPrototype || prototype is NewObjectPrototype); }
private static NamedInstructionBuilder ConstantFold( ValueTag first, ValueTag second, InstructionPrototype prototype, NamedInstructionBuilder insertionPoint) { var graph = insertionPoint.Graph; Constant firstConstant; Constant secondConstant; if (IsConstant(first, insertionPoint.Graph.ToImmutable(), out firstConstant) && IsConstant(second, insertionPoint.Graph.ToImmutable(), out secondConstant)) { var newConstant = ConstantPropagation.EvaluateDefault( prototype, new[] { firstConstant, secondConstant }); if (newConstant != null) { return(insertionPoint.InsertBefore( Instruction.CreateConstant(newConstant, prototype.ResultType))); } } return(null); }
private static void ToReductionList( NamedInstruction instruction, InstructionPrototype prototype, List <ValueTag> reductionArgs, HashSet <ValueTag> reductionOps, ValueUses uses) { if (uses.GetUseCount(instruction) == 1 && instruction.Prototype == prototype) { ToReductionList( instruction.Instruction.Arguments, prototype, reductionArgs, reductionOps, uses, instruction.Block.Graph); reductionOps.Add(instruction); } else { reductionArgs.Add(instruction); } }
internal static bool IsDereferenceableOrNull(InstructionPrototype prototype) { return(IsDereferenceable(prototype)); }
public static void Add(this IList <Instruction> source, InstructionPrototype prototype, int[] args = null) { source.Add(new Instruction(prototype, args)); }
/// <summary> /// Tests if an instruction prototype is a intrinsic prototype /// defined in the current namespace. /// </summary> /// <param name="prototype"> /// The prototype to examine. /// </param> /// <returns> /// <c>true</c> if the prototype is a namespaced intrinsic prototype; /// otherwise, <c>false</c>. /// </returns> public bool IsIntrinsicPrototype(InstructionPrototype prototype) { return(prototype is IntrinsicPrototype && IsIntrinsicName(((IntrinsicPrototype)prototype).Name)); }
/// <summary> /// Gets the memory access specification for a particular instruction /// prototype. /// </summary> /// <param name="prototype">The prototype to examine.</param> /// <returns>A memory specification for <paramref name="prototype"/>.</returns> public abstract MemorySpecification GetMemorySpecification(InstructionPrototype prototype);
/// <summary> /// Tells if it is permissible to delay exceptions thrown by a /// particular instruction until the instruction's result is used /// by an effectful instruction. /// If the instruction's result is never used that way, /// the exception may even be deleted altogether. /// </summary> /// <param name="prototype"> /// An instruction prototype to examine. /// </param> /// <returns> /// <c>true</c> if exceptions thrown by instances of <paramref name="prototype"/> /// may be delayed until the instances' values are used by effectful instructions; /// otherwise, <c>false</c>. /// </returns> public abstract bool CanDelayExceptions(InstructionPrototype prototype);
/// <inheritdoc/> public override MemorySpecification GetMemorySpecification(InstructionPrototype prototype) { return(store.GetSpecification(prototype)); }
/// <inheritdoc/> public override bool CanDelayExceptions(InstructionPrototype prototype) { return(false); }
/// <summary> /// Encodes an instruction prototype. /// </summary> /// <param name="prototype">The instruction prototype to encode.</param> /// <returns> /// An encoded instruction prototype. /// </returns> public LNode Encode(InstructionPrototype prototype) { return(Codec.Instructions.Encode(prototype, this)); }
private static bool IsJump(InstructionPrototype proto) => proto == Jump || proto == JumpIf || proto == Invoke || proto == Return;
/// <summary> /// Gets the exception specification for a particular instruction /// prototype. /// </summary> /// <param name="prototype">The prototype to examine.</param> /// <returns>An exception specification for <paramref name="prototype"/>.</returns> public abstract ExceptionSpecification GetExceptionSpecification(InstructionPrototype prototype);
private static bool IsLabel(InstructionPrototype proto) => proto == Label;
/// <inheritdoc/> public override ExceptionSpecification GetExceptionSpecification(InstructionPrototype prototype) { return(store.GetSpecification(prototype)); }
protected Instruction Insn(InstructionPrototype proto, params int[] args) => new Instruction(proto, args);