/// <summary cref="IBackendCodeGenerator.GenerateCode(AtomicCAS)"/> public void GenerateCode(AtomicCAS atomicCAS) { var target = Load(atomicCAS.Target); var value = Load(atomicCAS.Value); var compare = Load(atomicCAS.CompareValue); // The internal AtomicCAS value "returns" the old value that was stored // at the memory location. If the emitted operation fails the comparison // check, we will "return" the updated value stored in "targetVariable". If // the operation succeeds we will return the old value stored in // "targetVariable". Consequently, we will always assign the value stored in // "targetVariable" the be the "result" of the computation. var targetVariable = Allocate(atomicCAS); // Copy the compare value into the target variable to avoid modifications of // the input value using (var statement = BeginStatement(targetVariable)) statement.Append(value); // Perform the atomic operation and ignore the resulting bool value using (var statement = BeginStatement(CLInstructions.AtomicCASOperation)) { statement.BeginArguments(); statement.AppendAtomicCast(atomicCAS.ArithmeticBasicValueType); statement.AppendArgument(target); statement.AppendArgumentAddressWithCast( targetVariable, atomicCAS.ArithmeticBasicValueType); statement.AppendArgumentWithCast( compare, atomicCAS.ArithmeticBasicValueType); statement.EndArguments(); } }
/// <summary cref="IBackendCodeGenerator.GenerateCode(AtomicCAS)"/> public void GenerateCode(AtomicCAS atomicCAS) { var target = LoadHardware(atomicCAS.Target); var value = LoadPrimitive(atomicCAS.Value); var compare = LoadPrimitive(atomicCAS.CompareValue); var targetRegister = AllocateHardware(atomicCAS); using var command = BeginCommand(PTXInstructions.AtomicCASOperation); command.AppendNonLocalAddressSpace( (atomicCAS.Target.Type as AddressSpaceType).AddressSpace); command.AppendSuffix(atomicCAS.BasicValueType); command.AppendArgument(targetRegister); command.AppendArgumentValue(target); command.AppendArgument(value); command.AppendArgument(compare); }
/// <summary cref="IValueVisitor.Visit(AtomicCAS)"/> public void Visit(AtomicCAS atomicCAS) { var target = Load(atomicCAS.Target); var value = Load(atomicCAS.Value); var compare = Load(atomicCAS.CompareValue); var tempVariable = AllocateType(BasicValueType.Int1) as PrimitiveVariable; var targetVariable = Allocate(atomicCAS); using (var statement = BeginStatement(tempVariable)) { statement.AppendCommand(CLInstructions.AtomicCASOperation); statement.BeginArguments(); statement.AppendAtomicCast(atomicCAS.ArithmeticBasicValueType); statement.AppendArgument(target); statement.AppendArgumentAddressWithCast(value, $"{CLInstructions.GetAddressSpacePrefix(MemoryAddressSpace.Generic)} {CLTypeGenerator.GetBasicValueType(atomicCAS.ArithmeticBasicValueType)} {CLInstructions.DereferenceOperation}"); statement.AppendArgument(compare); statement.EndArguments(); } // The OpenCL way is not compatible with the internal CAS semantic // We should adapt to the more general way of returning a bool in the future // For now, check the result of the operation and emit an atomic load // in the case of a failure. using (var statement = BeginStatement(targetVariable)) { statement.Append(tempVariable); statement.AppendCommand(CLInstructions.SelectOperation1); statement.Append(value); statement.AppendCommand(CLInstructions.SelectOperation2); statement.AppendCommand(CLInstructions.AtomicLoadOperation); statement.BeginArguments(); statement.AppendAtomicCast(atomicCAS.ArithmeticBasicValueType); statement.AppendArgument(target); statement.EndArguments(); } }
public void Visit(AtomicCAS atomicCAS) { }
/// <summary cref="IValueVisitor.Visit(AtomicCAS)"/> public void Visit(AtomicCAS atomicCAS) => CodeGenerator.GenerateCode(atomicCAS);