// Copyright Advanced Micro Devices, Inc., or its affiliates. // SPDX-License-Identifier: MIT #include #include #include namespace rocRoller { template <> std::shared_ptr> GetGenerator(Register::ValuePtr dst, Register::ValuePtr lhs, Register::ValuePtr rhs, Expression::Subtract const&) { AssertFatal(dst != nullptr, "Null destination"); // Choose the proper generator, based on the context, register type // and datatype. return Component::Get>( getContextFromValues(dst, lhs, rhs), promoteRegisterType(dst, lhs, rhs), promoteDataType(dst, lhs, rhs)); } template <> Generator SubtractGenerator::generate( Register::ValuePtr dest, Register::ValuePtr lhs, Register::ValuePtr rhs, Expression::Subtract const&) { AssertFatal(lhs != nullptr); AssertFatal(rhs != nullptr); co_yield ScalarSubInt32(m_context, dest, lhs, rhs); } template <> Generator SubtractGenerator::generate( Register::ValuePtr dest, Register::ValuePtr lhs, Register::ValuePtr rhs, Expression::Subtract const&) { AssertFatal(lhs != nullptr); AssertFatal(rhs != nullptr); auto const& gpu = m_context->targetArchitecture().target(); if(gpu.isCDNAGPU()) { co_yield_(Instruction("v_sub_i32", {dest}, {lhs, rhs}, {}, "")); } else if(gpu.isRDNAGPU()) { co_yield_(Instruction("v_sub_nc_i32", {dest}, {lhs, rhs}, {}, "")); } else { Throw(fmt::format("SubtractGenerator<{}, {}> not implemented for {}\n", toString(Register::Type::Vector), toString(DataType::Int32), gpu.toString())); } } template <> Generator SubtractGenerator::generate( Register::ValuePtr dest, Register::ValuePtr lhs, Register::ValuePtr rhs, Expression::Subtract const&) { AssertFatal(lhs != nullptr); AssertFatal(rhs != nullptr); co_yield ScalarSubUInt32(m_context, dest, lhs, rhs); } template <> Generator SubtractGenerator::generate( Register::ValuePtr dest, Register::ValuePtr lhs, Register::ValuePtr rhs, Expression::Subtract const&) { AssertFatal(lhs != nullptr); AssertFatal(rhs != nullptr); co_yield VectorSubUInt32(m_context, dest, lhs, rhs); } template <> Generator SubtractGenerator::generate( Register::ValuePtr dest, Register::ValuePtr lhs, Register::ValuePtr rhs, Expression::Subtract const&) { co_yield describeOpArgs("dest", dest, "lhs", lhs, "rhs", rhs); Register::ValuePtr l0, l1, r0, r1; co_yield get2DwordsScalar(l0, l1, lhs); co_yield get2DwordsScalar(r0, r1, rhs); co_yield(Instruction::Lock(Scheduling::Dependency::SCC, "Start of Int64 sub, locking SCC")); co_yield ScalarSubUInt32( m_context, dest->subset({0}), l0, r0, "least significant half; sets scc"); co_yield ScalarSubUInt32CarryInOut( m_context, dest->subset({1}), l1, r1, "most significant half; uses scc"); co_yield(Instruction::Unlock("End of Int64 sub, unlocking SCC")); } template <> Generator SubtractGenerator::generate( Register::ValuePtr dest, Register::ValuePtr lhs, Register::ValuePtr rhs, Expression::Subtract const&) { co_yield describeOpArgs("dest", dest, "lhs", lhs, "rhs", rhs); Register::ValuePtr l0, l1, r0, r1; co_yield get2DwordsVector(l0, l1, lhs); co_yield get2DwordsVector(r0, r1, rhs); auto borrow = m_context->getVCC(); co_yield VectorSubUInt32CarryOut( m_context, dest->subset({0}), l0, r0, "least significant half") .lock(Scheduling::Dependency::VCC, "Start of Int64 sub, locking VCC"); co_yield VectorSubUInt32CarryInOut( m_context, dest->subset({1}), l1, r1, "most significant half") .unlock("End of Int64 sub, unlocking VCC"); } template <> Generator SubtractGenerator::generate( Register::ValuePtr dest, Register::ValuePtr lhs, Register::ValuePtr rhs, Expression::Subtract const&) { AssertFatal(lhs != nullptr); AssertFatal(rhs != nullptr); co_yield_(Instruction("v_sub_f32", {dest}, {lhs, rhs}, {}, "")); } template <> Generator SubtractGenerator::generate( Register::ValuePtr dest, Register::ValuePtr lhs, Register::ValuePtr rhs, Expression::Subtract const&) { AssertFatal(lhs != nullptr); AssertFatal(rhs != nullptr); auto nrhs = rhs->negate(); co_yield_(Instruction("v_add_f64", {dest}, {lhs, nrhs}, {}, "")); } }