/// <summary> /// Lowers generic values containing structure types that cannot be rewritten. /// </summary> private static void Keep( SSARewriterContext <FieldRef> context, LoweringData _, Value value) => DisassembleStructure( context, value.Type.As <StructureType>(value), value);
/// <summary> /// Keeps structure load operations. /// </summary> private static void Keep( SSARewriterContext <FieldRef> context, LoweringData _, Load load) => DisassembleStructure( context, load.Type as StructureType, load);
/// <summary> /// Lowers parameter values containing structure values. /// </summary> private static void Lower( SSARewriterContext <FieldRef> context, LoweringData _, Parameter value) => DisassembleStructure( context, value.Type as StructureType, value);
/// <summary> /// Lowers sub-warp shuffles. /// </summary> private static void Lower( SSARewriterContext <FieldRef> context, LoweringData _, SubWarpShuffle value) => LowerThreadValue < SubWarpShuffle, LowerThreadIntrinsics.SubWarpShuffleLowering>( context, value.Type as StructureType, value);
/// <summary> /// Lowers warp shuffles. /// </summary> private static void Lower( SSARewriterContext <FieldRef> context, LoweringData _, Broadcast value) => LowerThreadValue < Broadcast, LowerThreadIntrinsics.BroadcastLowering>( context, value.Type as StructureType, value);
/// <summary> /// Keeps structure store operations. /// </summary> private static void Keep( SSARewriterContext <FieldRef> context, LoweringData _, Store store) { var newValue = AssembleStructure( context, store.Value.Type as StructureType, store.Value); var newStore = context.Builder.CreateStore( store.Location, store.Target, newValue); context.ReplaceAndRemove(store, newStore); }
/// <summary> /// Lowers structure values into separate SSA values. /// </summary> private static void Lower( SSARewriterContext <FieldRef> context, LoweringData _, StructureValue structureValue) { foreach (var(_, fieldAccess) in structureValue.StructureType) { // Build the new target value var value = structureValue[fieldAccess.Index]; // Bind the new SSA value context.SetValue( context.Block, new FieldRef(structureValue, fieldAccess), value); } }
/// <summary> /// Applies the structure lowering transformation. /// </summary> protected override bool PerformTransformation(Method.Builder builder) { var ssaBuilder = SSABuilder <FieldRef> .Create(builder); var loweredPhis = new List <LoweredPhi>(); var loweringData = new LoweringData(loweredPhis); bool applied = LowerLoadStores ? LoadStoreRewriter.Rewrite(ssaBuilder, loweringData) : Rewriter.Rewrite(ssaBuilder, loweringData); // Seal all lowered phis foreach (var phi in loweredPhis) { var phiValue = phi.Seal(ssaBuilder); phiValue.TryRemoveTrivialPhi(builder); } return(applied); }
/// <summary> /// Lowers null values into separate SSA values. /// </summary> private static void Lower( SSARewriterContext <FieldRef> context, LoweringData _, NullValue nullValue) { foreach (var(fieldType, fieldAccess) in nullValue.Type as StructureType) { // Build the new target value var value = context.Builder.CreateNull( nullValue.Location, fieldType); context.MarkConverted(value); // Bind the new SSA value context.SetValue( context.Block, new FieldRef(nullValue, fieldAccess), value); } }
/// <summary> /// Lowers method calls involving structure types. /// </summary> private static void Lower( SSARewriterContext <FieldRef> context, LoweringData _, MethodCall call) { // Check for structure arguments that need to be rebuilt var newArgs = ImmutableArray.CreateBuilder <ValueReference>( call.NumArguments); foreach (Value argument in call) { Value newArgument = argument; if (argument.Type is StructureType argumentType) { newArgument = AssembleStructure( context, argumentType, argument); } newArgs.Add(newArgument); } // Create new call node var newCall = context.Builder.CreateCall( call.Location, call.Target, newArgs.MoveToImmutable()); context.ReplaceAndRemove(call, newCall); // Convert the return value if (call.Type is StructureType callType) { DisassembleStructure( context, callType, newCall); } }
/// <summary> /// Lowers return terminators returning structure values. /// </summary> private static void Lower( SSARewriterContext <FieldRef> context, LoweringData _, ReturnTerminator value) { // Move the block builder to a valid insert position in the source block var blockBuilder = context.GetMethodBuilder()[value.BasicBlock]; blockBuilder.SetupInsertPositionToEnd(); // Assemble return value Value returnValue = value.ReturnValue; var returnType = returnValue.Type.As <StructureType>(value); var newReturnValue = AssembleStructure( context.SpecializeBuilder(blockBuilder), returnType, returnValue); // Replace return terminator with a new terminator context.Builder.Terminator = context.Builder.CreateReturn( value.Location, newReturnValue); }
/// <summary> /// Lowers return terminators returning structure values. /// </summary> private static void Lower( SSARewriterContext <FieldRef> context, LoweringData _, ReturnTerminator value) { Value returnValue = value.ReturnValue; var returnType = returnValue.Type as StructureType; Debug.Assert(returnType != null, "Invalid structure type"); // Assemble a new structure that can be returned var blockBuilder = context.GetMethodBuilder()[value.BasicBlock]; blockBuilder.SetupInsertPosition(returnValue); var newReturnValue = AssembleStructure( context.SpecializeBuilder(blockBuilder), returnType, returnValue); // Replace return and remove return value returnValue.Replace(newReturnValue); }
/// <summary> /// Lowers set field operations into separate SSA values. /// </summary> private static void Lower( SSARewriterContext <FieldRef> context, LoweringData _, SetField setField) { foreach (var(_, fieldAccess) in setField.Type as StructureType) { Value value; if (setField.FieldSpan.Contains(fieldAccess)) { // Get value from the source value value = setField.Value; if (value.Type is StructureType) { var getFieldAccess = fieldAccess.Subtract( setField.FieldSpan.Index); value = context.GetValue( context.Block, new FieldRef(value, getFieldAccess)); } } else { // Load the currently registered SSA value value = context.GetValue( context.Block, new FieldRef(setField.ObjectValue, fieldAccess)); } // Bind the mapped SSA value context.SetValue( context.Block, new FieldRef(setField, fieldAccess), value); } context.Remove(setField); }