shader: Make typed IR
This commit is contained in:
parent
dc04a50ac2
commit
be94ee88d2
19 changed files with 494 additions and 268 deletions
|
@ -32,16 +32,16 @@ U32 IREmitter::Imm32(s32 value) const {
|
|||
return U32{Value{static_cast<u32>(value)}};
|
||||
}
|
||||
|
||||
U32 IREmitter::Imm32(f32 value) const {
|
||||
return U32{Value{Common::BitCast<u32>(value)}};
|
||||
F32 IREmitter::Imm32(f32 value) const {
|
||||
return F32{Value{value}};
|
||||
}
|
||||
|
||||
U64 IREmitter::Imm64(u64 value) const {
|
||||
return U64{Value{value}};
|
||||
}
|
||||
|
||||
U64 IREmitter::Imm64(f64 value) const {
|
||||
return U64{Value{Common::BitCast<u64>(value)}};
|
||||
F64 IREmitter::Imm64(f64 value) const {
|
||||
return F64{Value{value}};
|
||||
}
|
||||
|
||||
void IREmitter::Branch(IR::Block* label) {
|
||||
|
@ -121,11 +121,11 @@ void IREmitter::SetOFlag(const U1& value) {
|
|||
Inst(Opcode::SetOFlag, value);
|
||||
}
|
||||
|
||||
U32 IREmitter::GetAttribute(IR::Attribute attribute) {
|
||||
return Inst<U32>(Opcode::GetAttribute, attribute);
|
||||
F32 IREmitter::GetAttribute(IR::Attribute attribute) {
|
||||
return Inst<F32>(Opcode::GetAttribute, attribute);
|
||||
}
|
||||
|
||||
void IREmitter::SetAttribute(IR::Attribute attribute, const U32& value) {
|
||||
void IREmitter::SetAttribute(IR::Attribute attribute, const F32& value) {
|
||||
Inst(Opcode::SetAttribute, attribute, value);
|
||||
}
|
||||
|
||||
|
@ -225,50 +225,113 @@ U1 IREmitter::GetOverflowFromOp(const Value& op) {
|
|||
return Inst<U1>(Opcode::GetOverflowFromOp, op);
|
||||
}
|
||||
|
||||
U16U32U64 IREmitter::FPAdd(const U16U32U64& a, const U16U32U64& b, FpControl control) {
|
||||
F16F32F64 IREmitter::FPAdd(const F16F32F64& a, const F16F32F64& b, FpControl control) {
|
||||
if (a.Type() != a.Type()) {
|
||||
throw InvalidArgument("Mismatching types {} and {}", a.Type(), b.Type());
|
||||
}
|
||||
switch (a.Type()) {
|
||||
case Type::U16:
|
||||
return Inst<U16>(Opcode::FPAdd16, Flags{control}, a, b);
|
||||
case Type::U32:
|
||||
return Inst<U32>(Opcode::FPAdd32, Flags{control}, a, b);
|
||||
case Type::U64:
|
||||
return Inst<U64>(Opcode::FPAdd64, Flags{control}, a, b);
|
||||
case Type::F16:
|
||||
return Inst<F16>(Opcode::FPAdd16, Flags{control}, a, b);
|
||||
case Type::F32:
|
||||
return Inst<F32>(Opcode::FPAdd32, Flags{control}, a, b);
|
||||
case Type::F64:
|
||||
return Inst<F64>(Opcode::FPAdd64, Flags{control}, a, b);
|
||||
default:
|
||||
ThrowInvalidType(a.Type());
|
||||
}
|
||||
}
|
||||
|
||||
Value IREmitter::CompositeConstruct(const UAny& e1, const UAny& e2) {
|
||||
Value IREmitter::CompositeConstruct(const Value& e1, const Value& e2) {
|
||||
if (e1.Type() != e2.Type()) {
|
||||
throw InvalidArgument("Mismatching types {} and {}", e1.Type(), e2.Type());
|
||||
}
|
||||
return Inst(Opcode::CompositeConstruct2, e1, e2);
|
||||
switch (e1.Type()) {
|
||||
case Type::U32:
|
||||
return Inst(Opcode::CompositeConstructU32x2, e1, e2);
|
||||
case Type::F16:
|
||||
return Inst(Opcode::CompositeConstructF16x2, e1, e2);
|
||||
case Type::F32:
|
||||
return Inst(Opcode::CompositeConstructF32x2, e1, e2);
|
||||
case Type::F64:
|
||||
return Inst(Opcode::CompositeConstructF64x2, e1, e2);
|
||||
default:
|
||||
ThrowInvalidType(e1.Type());
|
||||
}
|
||||
}
|
||||
|
||||
Value IREmitter::CompositeConstruct(const UAny& e1, const UAny& e2, const UAny& e3) {
|
||||
Value IREmitter::CompositeConstruct(const Value& e1, const Value& e2, const Value& e3) {
|
||||
if (e1.Type() != e2.Type() || e1.Type() != e3.Type()) {
|
||||
throw InvalidArgument("Mismatching types {}, {}, and {}", e1.Type(), e2.Type(), e3.Type());
|
||||
}
|
||||
return Inst(Opcode::CompositeConstruct3, e1, e2, e3);
|
||||
switch (e1.Type()) {
|
||||
case Type::U32:
|
||||
return Inst(Opcode::CompositeConstructU32x3, e1, e2, e3);
|
||||
case Type::F16:
|
||||
return Inst(Opcode::CompositeConstructF16x3, e1, e2, e3);
|
||||
case Type::F32:
|
||||
return Inst(Opcode::CompositeConstructF32x3, e1, e2, e3);
|
||||
case Type::F64:
|
||||
return Inst(Opcode::CompositeConstructF64x3, e1, e2, e3);
|
||||
default:
|
||||
ThrowInvalidType(e1.Type());
|
||||
}
|
||||
}
|
||||
|
||||
Value IREmitter::CompositeConstruct(const UAny& e1, const UAny& e2, const UAny& e3,
|
||||
const UAny& e4) {
|
||||
Value IREmitter::CompositeConstruct(const Value& e1, const Value& e2, const Value& e3,
|
||||
const Value& e4) {
|
||||
if (e1.Type() != e2.Type() || e1.Type() != e3.Type() || e1.Type() != e4.Type()) {
|
||||
throw InvalidArgument("Mismatching types {}, {}, {}, and {}", e1.Type(), e2.Type(),
|
||||
e3.Type(), e4.Type());
|
||||
}
|
||||
return Inst(Opcode::CompositeConstruct4, e1, e2, e3, e4);
|
||||
switch (e1.Type()) {
|
||||
case Type::U32:
|
||||
return Inst(Opcode::CompositeConstructU32x4, e1, e2, e3, e4);
|
||||
case Type::F16:
|
||||
return Inst(Opcode::CompositeConstructF16x4, e1, e2, e3, e4);
|
||||
case Type::F32:
|
||||
return Inst(Opcode::CompositeConstructF32x4, e1, e2, e3, e4);
|
||||
case Type::F64:
|
||||
return Inst(Opcode::CompositeConstructF64x4, e1, e2, e3, e4);
|
||||
default:
|
||||
ThrowInvalidType(e1.Type());
|
||||
}
|
||||
}
|
||||
|
||||
UAny IREmitter::CompositeExtract(const Value& vector, size_t element) {
|
||||
if (element >= 4) {
|
||||
throw InvalidArgument("Out of bounds element {}", element);
|
||||
Value IREmitter::CompositeExtract(const Value& vector, size_t element) {
|
||||
const auto read = [&](Opcode opcode, size_t limit) -> Value {
|
||||
if (element >= limit) {
|
||||
throw InvalidArgument("Out of bounds element {}", element);
|
||||
}
|
||||
return Inst(opcode, vector, Value{static_cast<u32>(element)});
|
||||
};
|
||||
switch (vector.Type()) {
|
||||
case Type::U32x2:
|
||||
return read(Opcode::CompositeExtractU32x2, 2);
|
||||
case Type::U32x3:
|
||||
return read(Opcode::CompositeExtractU32x3, 3);
|
||||
case Type::U32x4:
|
||||
return read(Opcode::CompositeExtractU32x4, 4);
|
||||
case Type::F16x2:
|
||||
return read(Opcode::CompositeExtractF16x2, 2);
|
||||
case Type::F16x3:
|
||||
return read(Opcode::CompositeExtractF16x3, 3);
|
||||
case Type::F16x4:
|
||||
return read(Opcode::CompositeExtractF16x4, 4);
|
||||
case Type::F32x2:
|
||||
return read(Opcode::CompositeExtractF32x2, 2);
|
||||
case Type::F32x3:
|
||||
return read(Opcode::CompositeExtractF32x3, 3);
|
||||
case Type::F32x4:
|
||||
return read(Opcode::CompositeExtractF32x4, 4);
|
||||
case Type::F64x2:
|
||||
return read(Opcode::CompositeExtractF64x2, 2);
|
||||
case Type::F64x3:
|
||||
return read(Opcode::CompositeExtractF64x3, 3);
|
||||
case Type::F64x4:
|
||||
return read(Opcode::CompositeExtractF64x4, 4);
|
||||
default:
|
||||
ThrowInvalidType(vector.Type());
|
||||
}
|
||||
return Inst<UAny>(Opcode::CompositeExtract, vector, Imm32(static_cast<u32>(element)));
|
||||
}
|
||||
|
||||
UAny IREmitter::Select(const U1& condition, const UAny& true_value, const UAny& false_value) {
|
||||
|
@ -289,6 +352,36 @@ UAny IREmitter::Select(const U1& condition, const UAny& true_value, const UAny&
|
|||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
IR::U32 IREmitter::BitCast<IR::U32, IR::F32>(const IR::F32& value) {
|
||||
return Inst<IR::U32>(Opcode::BitCastU32F32, value);
|
||||
}
|
||||
|
||||
template <>
|
||||
IR::F32 IREmitter::BitCast<IR::F32, IR::U32>(const IR::U32& value) {
|
||||
return Inst<IR::F32>(Opcode::BitCastF32U32, value);
|
||||
}
|
||||
|
||||
template <>
|
||||
IR::U16 IREmitter::BitCast<IR::U16, IR::F16>(const IR::F16& value) {
|
||||
return Inst<IR::U16>(Opcode::BitCastU16F16, value);
|
||||
}
|
||||
|
||||
template <>
|
||||
IR::F16 IREmitter::BitCast<IR::F16, IR::U16>(const IR::U16& value) {
|
||||
return Inst<IR::F16>(Opcode::BitCastF16U16, value);
|
||||
}
|
||||
|
||||
template <>
|
||||
IR::U64 IREmitter::BitCast<IR::U64, IR::F64>(const IR::F64& value) {
|
||||
return Inst<IR::U64>(Opcode::BitCastU64F64, value);
|
||||
}
|
||||
|
||||
template <>
|
||||
IR::F64 IREmitter::BitCast<IR::F64, IR::U64>(const IR::U64& value) {
|
||||
return Inst<IR::F64>(Opcode::BitCastF64U64, value);
|
||||
}
|
||||
|
||||
U64 IREmitter::PackUint2x32(const Value& vector) {
|
||||
return Inst<U64>(Opcode::PackUint2x32, vector);
|
||||
}
|
||||
|
@ -305,75 +398,75 @@ Value IREmitter::UnpackFloat2x16(const U32& value) {
|
|||
return Inst<Value>(Opcode::UnpackFloat2x16, value);
|
||||
}
|
||||
|
||||
U64 IREmitter::PackDouble2x32(const Value& vector) {
|
||||
return Inst<U64>(Opcode::PackDouble2x32, vector);
|
||||
F64 IREmitter::PackDouble2x32(const Value& vector) {
|
||||
return Inst<F64>(Opcode::PackDouble2x32, vector);
|
||||
}
|
||||
|
||||
Value IREmitter::UnpackDouble2x32(const U64& value) {
|
||||
Value IREmitter::UnpackDouble2x32(const F64& value) {
|
||||
return Inst<Value>(Opcode::UnpackDouble2x32, value);
|
||||
}
|
||||
|
||||
U16U32U64 IREmitter::FPMul(const U16U32U64& a, const U16U32U64& b, FpControl control) {
|
||||
F16F32F64 IREmitter::FPMul(const F16F32F64& a, const F16F32F64& b, FpControl control) {
|
||||
if (a.Type() != b.Type()) {
|
||||
throw InvalidArgument("Mismatching types {} and {}", a.Type(), b.Type());
|
||||
}
|
||||
switch (a.Type()) {
|
||||
case Type::U16:
|
||||
return Inst<U16>(Opcode::FPMul16, Flags{control}, a, b);
|
||||
case Type::U32:
|
||||
return Inst<U32>(Opcode::FPMul32, Flags{control}, a, b);
|
||||
case Type::U64:
|
||||
return Inst<U64>(Opcode::FPMul64, Flags{control}, a, b);
|
||||
case Type::F16:
|
||||
return Inst<F16>(Opcode::FPMul16, Flags{control}, a, b);
|
||||
case Type::F32:
|
||||
return Inst<F32>(Opcode::FPMul32, Flags{control}, a, b);
|
||||
case Type::F64:
|
||||
return Inst<F64>(Opcode::FPMul64, Flags{control}, a, b);
|
||||
default:
|
||||
ThrowInvalidType(a.Type());
|
||||
}
|
||||
}
|
||||
|
||||
U16U32U64 IREmitter::FPFma(const U16U32U64& a, const U16U32U64& b, const U16U32U64& c,
|
||||
F16F32F64 IREmitter::FPFma(const F16F32F64& a, const F16F32F64& b, const F16F32F64& c,
|
||||
FpControl control) {
|
||||
if (a.Type() != b.Type() || a.Type() != c.Type()) {
|
||||
throw InvalidArgument("Mismatching types {}, {}, and {}", a.Type(), b.Type(), c.Type());
|
||||
}
|
||||
switch (a.Type()) {
|
||||
case Type::U16:
|
||||
return Inst<U16>(Opcode::FPFma16, Flags{control}, a, b, c);
|
||||
case Type::U32:
|
||||
return Inst<U32>(Opcode::FPFma32, Flags{control}, a, b, c);
|
||||
case Type::U64:
|
||||
return Inst<U64>(Opcode::FPFma64, Flags{control}, a, b, c);
|
||||
case Type::F16:
|
||||
return Inst<F16>(Opcode::FPFma16, Flags{control}, a, b, c);
|
||||
case Type::F32:
|
||||
return Inst<F32>(Opcode::FPFma32, Flags{control}, a, b, c);
|
||||
case Type::F64:
|
||||
return Inst<F64>(Opcode::FPFma64, Flags{control}, a, b, c);
|
||||
default:
|
||||
ThrowInvalidType(a.Type());
|
||||
}
|
||||
}
|
||||
|
||||
U16U32U64 IREmitter::FPAbs(const U16U32U64& value) {
|
||||
F16F32F64 IREmitter::FPAbs(const F16F32F64& value) {
|
||||
switch (value.Type()) {
|
||||
case Type::U16:
|
||||
return Inst<U16>(Opcode::FPAbs16, value);
|
||||
return Inst<F16>(Opcode::FPAbs16, value);
|
||||
case Type::U32:
|
||||
return Inst<U32>(Opcode::FPAbs32, value);
|
||||
return Inst<F32>(Opcode::FPAbs32, value);
|
||||
case Type::U64:
|
||||
return Inst<U64>(Opcode::FPAbs64, value);
|
||||
return Inst<F64>(Opcode::FPAbs64, value);
|
||||
default:
|
||||
ThrowInvalidType(value.Type());
|
||||
}
|
||||
}
|
||||
|
||||
U16U32U64 IREmitter::FPNeg(const U16U32U64& value) {
|
||||
F16F32F64 IREmitter::FPNeg(const F16F32F64& value) {
|
||||
switch (value.Type()) {
|
||||
case Type::U16:
|
||||
return Inst<U16>(Opcode::FPNeg16, value);
|
||||
return Inst<F16>(Opcode::FPNeg16, value);
|
||||
case Type::U32:
|
||||
return Inst<U32>(Opcode::FPNeg32, value);
|
||||
return Inst<F32>(Opcode::FPNeg32, value);
|
||||
case Type::U64:
|
||||
return Inst<U64>(Opcode::FPNeg64, value);
|
||||
return Inst<F64>(Opcode::FPNeg64, value);
|
||||
default:
|
||||
ThrowInvalidType(value.Type());
|
||||
}
|
||||
}
|
||||
|
||||
U16U32U64 IREmitter::FPAbsNeg(const U16U32U64& value, bool abs, bool neg) {
|
||||
U16U32U64 result{value};
|
||||
F16F32F64 IREmitter::FPAbsNeg(const F16F32F64& value, bool abs, bool neg) {
|
||||
F16F32F64 result{value};
|
||||
if (abs) {
|
||||
result = FPAbs(value);
|
||||
}
|
||||
|
@ -383,108 +476,108 @@ U16U32U64 IREmitter::FPAbsNeg(const U16U32U64& value, bool abs, bool neg) {
|
|||
return result;
|
||||
}
|
||||
|
||||
U32 IREmitter::FPCosNotReduced(const U32& value) {
|
||||
return Inst<U32>(Opcode::FPCosNotReduced, value);
|
||||
F32 IREmitter::FPCosNotReduced(const F32& value) {
|
||||
return Inst<F32>(Opcode::FPCosNotReduced, value);
|
||||
}
|
||||
|
||||
U32 IREmitter::FPExp2NotReduced(const U32& value) {
|
||||
return Inst<U32>(Opcode::FPExp2NotReduced, value);
|
||||
F32 IREmitter::FPExp2NotReduced(const F32& value) {
|
||||
return Inst<F32>(Opcode::FPExp2NotReduced, value);
|
||||
}
|
||||
|
||||
U32 IREmitter::FPLog2(const U32& value) {
|
||||
return Inst<U32>(Opcode::FPLog2, value);
|
||||
F32 IREmitter::FPLog2(const F32& value) {
|
||||
return Inst<F32>(Opcode::FPLog2, value);
|
||||
}
|
||||
|
||||
U32U64 IREmitter::FPRecip(const U32U64& value) {
|
||||
F32F64 IREmitter::FPRecip(const F32F64& value) {
|
||||
switch (value.Type()) {
|
||||
case Type::U32:
|
||||
return Inst<U32>(Opcode::FPRecip32, value);
|
||||
return Inst<F32>(Opcode::FPRecip32, value);
|
||||
case Type::U64:
|
||||
return Inst<U64>(Opcode::FPRecip64, value);
|
||||
return Inst<F64>(Opcode::FPRecip64, value);
|
||||
default:
|
||||
ThrowInvalidType(value.Type());
|
||||
}
|
||||
}
|
||||
|
||||
U32U64 IREmitter::FPRecipSqrt(const U32U64& value) {
|
||||
F32F64 IREmitter::FPRecipSqrt(const F32F64& value) {
|
||||
switch (value.Type()) {
|
||||
case Type::U32:
|
||||
return Inst<U32>(Opcode::FPRecipSqrt32, value);
|
||||
return Inst<F32>(Opcode::FPRecipSqrt32, value);
|
||||
case Type::U64:
|
||||
return Inst<U64>(Opcode::FPRecipSqrt64, value);
|
||||
return Inst<F64>(Opcode::FPRecipSqrt64, value);
|
||||
default:
|
||||
ThrowInvalidType(value.Type());
|
||||
}
|
||||
}
|
||||
|
||||
U32 IREmitter::FPSinNotReduced(const U32& value) {
|
||||
return Inst<U32>(Opcode::FPSinNotReduced, value);
|
||||
F32 IREmitter::FPSinNotReduced(const F32& value) {
|
||||
return Inst<F32>(Opcode::FPSinNotReduced, value);
|
||||
}
|
||||
|
||||
U32 IREmitter::FPSqrt(const U32& value) {
|
||||
return Inst<U32>(Opcode::FPSqrt, value);
|
||||
F32 IREmitter::FPSqrt(const F32& value) {
|
||||
return Inst<F32>(Opcode::FPSqrt, value);
|
||||
}
|
||||
|
||||
U16U32U64 IREmitter::FPSaturate(const U16U32U64& value) {
|
||||
F16F32F64 IREmitter::FPSaturate(const F16F32F64& value) {
|
||||
switch (value.Type()) {
|
||||
case Type::U16:
|
||||
return Inst<U16>(Opcode::FPSaturate16, value);
|
||||
return Inst<F16>(Opcode::FPSaturate16, value);
|
||||
case Type::U32:
|
||||
return Inst<U32>(Opcode::FPSaturate32, value);
|
||||
return Inst<F32>(Opcode::FPSaturate32, value);
|
||||
case Type::U64:
|
||||
return Inst<U64>(Opcode::FPSaturate64, value);
|
||||
return Inst<F64>(Opcode::FPSaturate64, value);
|
||||
default:
|
||||
ThrowInvalidType(value.Type());
|
||||
}
|
||||
}
|
||||
|
||||
U16U32U64 IREmitter::FPRoundEven(const U16U32U64& value) {
|
||||
F16F32F64 IREmitter::FPRoundEven(const F16F32F64& value) {
|
||||
switch (value.Type()) {
|
||||
case Type::U16:
|
||||
return Inst<U16>(Opcode::FPRoundEven16, value);
|
||||
return Inst<F16>(Opcode::FPRoundEven16, value);
|
||||
case Type::U32:
|
||||
return Inst<U32>(Opcode::FPRoundEven32, value);
|
||||
return Inst<F32>(Opcode::FPRoundEven32, value);
|
||||
case Type::U64:
|
||||
return Inst<U64>(Opcode::FPRoundEven64, value);
|
||||
return Inst<F64>(Opcode::FPRoundEven64, value);
|
||||
default:
|
||||
ThrowInvalidType(value.Type());
|
||||
}
|
||||
}
|
||||
|
||||
U16U32U64 IREmitter::FPFloor(const U16U32U64& value) {
|
||||
F16F32F64 IREmitter::FPFloor(const F16F32F64& value) {
|
||||
switch (value.Type()) {
|
||||
case Type::U16:
|
||||
return Inst<U16>(Opcode::FPFloor16, value);
|
||||
return Inst<F16>(Opcode::FPFloor16, value);
|
||||
case Type::U32:
|
||||
return Inst<U32>(Opcode::FPFloor32, value);
|
||||
return Inst<F32>(Opcode::FPFloor32, value);
|
||||
case Type::U64:
|
||||
return Inst<U64>(Opcode::FPFloor64, value);
|
||||
return Inst<F64>(Opcode::FPFloor64, value);
|
||||
default:
|
||||
ThrowInvalidType(value.Type());
|
||||
}
|
||||
}
|
||||
|
||||
U16U32U64 IREmitter::FPCeil(const U16U32U64& value) {
|
||||
F16F32F64 IREmitter::FPCeil(const F16F32F64& value) {
|
||||
switch (value.Type()) {
|
||||
case Type::U16:
|
||||
return Inst<U16>(Opcode::FPCeil16, value);
|
||||
return Inst<F16>(Opcode::FPCeil16, value);
|
||||
case Type::U32:
|
||||
return Inst<U32>(Opcode::FPCeil32, value);
|
||||
return Inst<F32>(Opcode::FPCeil32, value);
|
||||
case Type::U64:
|
||||
return Inst<U64>(Opcode::FPCeil64, value);
|
||||
return Inst<F64>(Opcode::FPCeil64, value);
|
||||
default:
|
||||
ThrowInvalidType(value.Type());
|
||||
}
|
||||
}
|
||||
|
||||
U16U32U64 IREmitter::FPTrunc(const U16U32U64& value) {
|
||||
F16F32F64 IREmitter::FPTrunc(const F16F32F64& value) {
|
||||
switch (value.Type()) {
|
||||
case Type::U16:
|
||||
return Inst<U16>(Opcode::FPTrunc16, value);
|
||||
return Inst<F16>(Opcode::FPTrunc16, value);
|
||||
case Type::U32:
|
||||
return Inst<U32>(Opcode::FPTrunc32, value);
|
||||
return Inst<F32>(Opcode::FPTrunc32, value);
|
||||
case Type::U64:
|
||||
return Inst<U64>(Opcode::FPTrunc64, value);
|
||||
return Inst<F64>(Opcode::FPTrunc64, value);
|
||||
default:
|
||||
ThrowInvalidType(value.Type());
|
||||
}
|
||||
|
@ -605,7 +698,7 @@ U1 IREmitter::LogicalNot(const U1& value) {
|
|||
return Inst<U1>(Opcode::LogicalNot, value);
|
||||
}
|
||||
|
||||
U32U64 IREmitter::ConvertFToS(size_t bitsize, const U16U32U64& value) {
|
||||
U32U64 IREmitter::ConvertFToS(size_t bitsize, const F16F32F64& value) {
|
||||
switch (bitsize) {
|
||||
case 16:
|
||||
switch (value.Type()) {
|
||||
|
@ -645,7 +738,7 @@ U32U64 IREmitter::ConvertFToS(size_t bitsize, const U16U32U64& value) {
|
|||
}
|
||||
}
|
||||
|
||||
U32U64 IREmitter::ConvertFToU(size_t bitsize, const U16U32U64& value) {
|
||||
U32U64 IREmitter::ConvertFToU(size_t bitsize, const F16F32F64& value) {
|
||||
switch (bitsize) {
|
||||
case 16:
|
||||
switch (value.Type()) {
|
||||
|
@ -685,7 +778,7 @@ U32U64 IREmitter::ConvertFToU(size_t bitsize, const U16U32U64& value) {
|
|||
}
|
||||
}
|
||||
|
||||
U32U64 IREmitter::ConvertFToI(size_t bitsize, bool is_signed, const U16U32U64& value) {
|
||||
U32U64 IREmitter::ConvertFToI(size_t bitsize, bool is_signed, const F16F32F64& value) {
|
||||
if (is_signed) {
|
||||
return ConvertFToS(bitsize, value);
|
||||
} else {
|
||||
|
|
|
@ -27,9 +27,9 @@ public:
|
|||
[[nodiscard]] U16 Imm16(u16 value) const;
|
||||
[[nodiscard]] U32 Imm32(u32 value) const;
|
||||
[[nodiscard]] U32 Imm32(s32 value) const;
|
||||
[[nodiscard]] U32 Imm32(f32 value) const;
|
||||
[[nodiscard]] F32 Imm32(f32 value) const;
|
||||
[[nodiscard]] U64 Imm64(u64 value) const;
|
||||
[[nodiscard]] U64 Imm64(f64 value) const;
|
||||
[[nodiscard]] F64 Imm64(f64 value) const;
|
||||
|
||||
void Branch(IR::Block* label);
|
||||
void BranchConditional(const U1& cond, IR::Block* true_label, IR::Block* false_label);
|
||||
|
@ -55,8 +55,8 @@ public:
|
|||
void SetCFlag(const U1& value);
|
||||
void SetOFlag(const U1& value);
|
||||
|
||||
[[nodiscard]] U32 GetAttribute(IR::Attribute attribute);
|
||||
void SetAttribute(IR::Attribute attribute, const U32& value);
|
||||
[[nodiscard]] F32 GetAttribute(IR::Attribute attribute);
|
||||
void SetAttribute(IR::Attribute attribute, const F32& value);
|
||||
|
||||
[[nodiscard]] U32 WorkgroupIdX();
|
||||
[[nodiscard]] U32 WorkgroupIdY();
|
||||
|
@ -87,44 +87,47 @@ public:
|
|||
[[nodiscard]] U1 GetCarryFromOp(const Value& op);
|
||||
[[nodiscard]] U1 GetOverflowFromOp(const Value& op);
|
||||
|
||||
[[nodiscard]] Value CompositeConstruct(const UAny& e1, const UAny& e2);
|
||||
[[nodiscard]] Value CompositeConstruct(const UAny& e1, const UAny& e2, const UAny& e3);
|
||||
[[nodiscard]] Value CompositeConstruct(const UAny& e1, const UAny& e2, const UAny& e3,
|
||||
const UAny& e4);
|
||||
[[nodiscard]] UAny CompositeExtract(const Value& vector, size_t element);
|
||||
[[nodiscard]] Value CompositeConstruct(const Value& e1, const Value& e2);
|
||||
[[nodiscard]] Value CompositeConstruct(const Value& e1, const Value& e2, const Value& e3);
|
||||
[[nodiscard]] Value CompositeConstruct(const Value& e1, const Value& e2, const Value& e3,
|
||||
const Value& e4);
|
||||
[[nodiscard]] Value CompositeExtract(const Value& vector, size_t element);
|
||||
|
||||
[[nodiscard]] UAny Select(const U1& condition, const UAny& true_value, const UAny& false_value);
|
||||
|
||||
template <typename Dest, typename Source>
|
||||
[[nodiscard]] Dest BitCast(const Source& value);
|
||||
|
||||
[[nodiscard]] U64 PackUint2x32(const Value& vector);
|
||||
[[nodiscard]] Value UnpackUint2x32(const U64& value);
|
||||
|
||||
[[nodiscard]] U32 PackFloat2x16(const Value& vector);
|
||||
[[nodiscard]] Value UnpackFloat2x16(const U32& value);
|
||||
|
||||
[[nodiscard]] U64 PackDouble2x32(const Value& vector);
|
||||
[[nodiscard]] Value UnpackDouble2x32(const U64& value);
|
||||
[[nodiscard]] F64 PackDouble2x32(const Value& vector);
|
||||
[[nodiscard]] Value UnpackDouble2x32(const F64& value);
|
||||
|
||||
[[nodiscard]] U16U32U64 FPAdd(const U16U32U64& a, const U16U32U64& b, FpControl control = {});
|
||||
[[nodiscard]] U16U32U64 FPMul(const U16U32U64& a, const U16U32U64& b, FpControl control = {});
|
||||
[[nodiscard]] U16U32U64 FPFma(const U16U32U64& a, const U16U32U64& b, const U16U32U64& c,
|
||||
[[nodiscard]] F16F32F64 FPAdd(const F16F32F64& a, const F16F32F64& b, FpControl control = {});
|
||||
[[nodiscard]] F16F32F64 FPMul(const F16F32F64& a, const F16F32F64& b, FpControl control = {});
|
||||
[[nodiscard]] F16F32F64 FPFma(const F16F32F64& a, const F16F32F64& b, const F16F32F64& c,
|
||||
FpControl control = {});
|
||||
|
||||
[[nodiscard]] U16U32U64 FPAbs(const U16U32U64& value);
|
||||
[[nodiscard]] U16U32U64 FPNeg(const U16U32U64& value);
|
||||
[[nodiscard]] U16U32U64 FPAbsNeg(const U16U32U64& value, bool abs, bool neg);
|
||||
[[nodiscard]] F16F32F64 FPAbs(const F16F32F64& value);
|
||||
[[nodiscard]] F16F32F64 FPNeg(const F16F32F64& value);
|
||||
[[nodiscard]] F16F32F64 FPAbsNeg(const F16F32F64& value, bool abs, bool neg);
|
||||
|
||||
[[nodiscard]] U32 FPCosNotReduced(const U32& value);
|
||||
[[nodiscard]] U32 FPExp2NotReduced(const U32& value);
|
||||
[[nodiscard]] U32 FPLog2(const U32& value);
|
||||
[[nodiscard]] U32U64 FPRecip(const U32U64& value);
|
||||
[[nodiscard]] U32U64 FPRecipSqrt(const U32U64& value);
|
||||
[[nodiscard]] U32 FPSinNotReduced(const U32& value);
|
||||
[[nodiscard]] U32 FPSqrt(const U32& value);
|
||||
[[nodiscard]] U16U32U64 FPSaturate(const U16U32U64& value);
|
||||
[[nodiscard]] U16U32U64 FPRoundEven(const U16U32U64& value);
|
||||
[[nodiscard]] U16U32U64 FPFloor(const U16U32U64& value);
|
||||
[[nodiscard]] U16U32U64 FPCeil(const U16U32U64& value);
|
||||
[[nodiscard]] U16U32U64 FPTrunc(const U16U32U64& value);
|
||||
[[nodiscard]] F32 FPCosNotReduced(const F32& value);
|
||||
[[nodiscard]] F32 FPExp2NotReduced(const F32& value);
|
||||
[[nodiscard]] F32 FPLog2(const F32& value);
|
||||
[[nodiscard]] F32F64 FPRecip(const F32F64& value);
|
||||
[[nodiscard]] F32F64 FPRecipSqrt(const F32F64& value);
|
||||
[[nodiscard]] F32 FPSinNotReduced(const F32& value);
|
||||
[[nodiscard]] F32 FPSqrt(const F32& value);
|
||||
[[nodiscard]] F16F32F64 FPSaturate(const F16F32F64& value);
|
||||
[[nodiscard]] F16F32F64 FPRoundEven(const F16F32F64& value);
|
||||
[[nodiscard]] F16F32F64 FPFloor(const F16F32F64& value);
|
||||
[[nodiscard]] F16F32F64 FPCeil(const F16F32F64& value);
|
||||
[[nodiscard]] F16F32F64 FPTrunc(const F16F32F64& value);
|
||||
|
||||
[[nodiscard]] U32U64 IAdd(const U32U64& a, const U32U64& b);
|
||||
[[nodiscard]] U32U64 ISub(const U32U64& a, const U32U64& b);
|
||||
|
@ -154,9 +157,9 @@ public:
|
|||
[[nodiscard]] U1 LogicalXor(const U1& a, const U1& b);
|
||||
[[nodiscard]] U1 LogicalNot(const U1& value);
|
||||
|
||||
[[nodiscard]] U32U64 ConvertFToS(size_t bitsize, const U16U32U64& value);
|
||||
[[nodiscard]] U32U64 ConvertFToU(size_t bitsize, const U16U32U64& value);
|
||||
[[nodiscard]] U32U64 ConvertFToI(size_t bitsize, bool is_signed, const U16U32U64& value);
|
||||
[[nodiscard]] U32U64 ConvertFToS(size_t bitsize, const F16F32F64& value);
|
||||
[[nodiscard]] U32U64 ConvertFToU(size_t bitsize, const F16F32F64& value);
|
||||
[[nodiscard]] U32U64 ConvertFToI(size_t bitsize, bool is_signed, const F16F32F64& value);
|
||||
|
||||
[[nodiscard]] U32U64 ConvertU(size_t result_bitsize, const U32U64& value);
|
||||
|
||||
|
|
|
@ -52,15 +52,15 @@ OPCODE(LoadGlobalS8, U32, U64,
|
|||
OPCODE(LoadGlobalU16, U32, U64, )
|
||||
OPCODE(LoadGlobalS16, U32, U64, )
|
||||
OPCODE(LoadGlobal32, U32, U64, )
|
||||
OPCODE(LoadGlobal64, Opaque, U64, )
|
||||
OPCODE(LoadGlobal128, Opaque, U64, )
|
||||
OPCODE(LoadGlobal64, U32x2, U64, )
|
||||
OPCODE(LoadGlobal128, U32x4, U64, )
|
||||
OPCODE(WriteGlobalU8, Void, U64, U32, )
|
||||
OPCODE(WriteGlobalS8, Void, U64, U32, )
|
||||
OPCODE(WriteGlobalU16, Void, U64, U32, )
|
||||
OPCODE(WriteGlobalS16, Void, U64, U32, )
|
||||
OPCODE(WriteGlobal32, Void, U64, U32, )
|
||||
OPCODE(WriteGlobal64, Void, U64, Opaque, )
|
||||
OPCODE(WriteGlobal128, Void, U64, Opaque, )
|
||||
OPCODE(WriteGlobal64, Void, U64, U32x2, )
|
||||
OPCODE(WriteGlobal128, Void, U64, U32x4, )
|
||||
|
||||
// Storage buffer operations
|
||||
OPCODE(LoadStorageU8, U32, U32, U32, )
|
||||
|
@ -68,21 +68,41 @@ OPCODE(LoadStorageS8, U32, U32,
|
|||
OPCODE(LoadStorageU16, U32, U32, U32, )
|
||||
OPCODE(LoadStorageS16, U32, U32, U32, )
|
||||
OPCODE(LoadStorage32, U32, U32, U32, )
|
||||
OPCODE(LoadStorage64, Opaque, U32, U32, )
|
||||
OPCODE(LoadStorage128, Opaque, U32, U32, )
|
||||
OPCODE(WriteStorageU8, Void, U32, U32, U32, )
|
||||
OPCODE(WriteStorageS8, Void, U32, U32, U32, )
|
||||
OPCODE(WriteStorageU16, Void, U32, U32, U32, )
|
||||
OPCODE(WriteStorageS16, Void, U32, U32, U32, )
|
||||
OPCODE(WriteStorage32, Void, U32, U32, U32, )
|
||||
OPCODE(WriteStorage64, Void, U32, U32, Opaque, )
|
||||
OPCODE(WriteStorage128, Void, U32, U32, Opaque, )
|
||||
OPCODE(LoadStorage64, U32x2, U32, U32, )
|
||||
OPCODE(LoadStorage128, U32x4, U32, U32, )
|
||||
OPCODE(WriteStorageU8, Void, U32, U32, U32, )
|
||||
OPCODE(WriteStorageS8, Void, U32, U32, U32, )
|
||||
OPCODE(WriteStorageU16, Void, U32, U32, U32, )
|
||||
OPCODE(WriteStorageS16, Void, U32, U32, U32, )
|
||||
OPCODE(WriteStorage32, Void, U32, U32, U32, )
|
||||
OPCODE(WriteStorage64, Void, U32, U32, U32x2, )
|
||||
OPCODE(WriteStorage128, Void, U32, U32, U32x4, )
|
||||
|
||||
// Vector utility
|
||||
OPCODE(CompositeConstruct2, Opaque, Opaque, Opaque, )
|
||||
OPCODE(CompositeConstruct3, Opaque, Opaque, Opaque, Opaque, )
|
||||
OPCODE(CompositeConstruct4, Opaque, Opaque, Opaque, Opaque, Opaque, )
|
||||
OPCODE(CompositeExtract, Opaque, Opaque, U32, )
|
||||
OPCODE(CompositeConstructU32x2, U32x2, U32, U32, )
|
||||
OPCODE(CompositeConstructU32x3, U32x3, U32, U32, U32, )
|
||||
OPCODE(CompositeConstructU32x4, U32x4, U32, U32, U32, U32, )
|
||||
OPCODE(CompositeExtractU32x2, U32, U32x2, U32, )
|
||||
OPCODE(CompositeExtractU32x3, U32, U32x3, U32, )
|
||||
OPCODE(CompositeExtractU32x4, U32, U32x4, U32, )
|
||||
OPCODE(CompositeConstructF16x2, F16x2, F16, F16, )
|
||||
OPCODE(CompositeConstructF16x3, F16x3, F16, F16, F16, )
|
||||
OPCODE(CompositeConstructF16x4, F16x4, F16, F16, F16, F16, )
|
||||
OPCODE(CompositeExtractF16x2, F16, F16x2, U32, )
|
||||
OPCODE(CompositeExtractF16x3, F16, F16x3, U32, )
|
||||
OPCODE(CompositeExtractF16x4, F16, F16x4, U32, )
|
||||
OPCODE(CompositeConstructF32x2, F32x2, F32, F32, )
|
||||
OPCODE(CompositeConstructF32x3, F32x3, F32, F32, F32, )
|
||||
OPCODE(CompositeConstructF32x4, F32x4, F32, F32, F32, F32, )
|
||||
OPCODE(CompositeExtractF32x2, F32, F32x2, U32, )
|
||||
OPCODE(CompositeExtractF32x3, F32, F32x3, U32, )
|
||||
OPCODE(CompositeExtractF32x4, F32, F32x4, U32, )
|
||||
OPCODE(CompositeConstructF64x2, F64x2, F64, F64, )
|
||||
OPCODE(CompositeConstructF64x3, F64x3, F64, F64, F64, )
|
||||
OPCODE(CompositeConstructF64x4, F64x4, F64, F64, F64, F64, )
|
||||
OPCODE(CompositeExtractF64x2, F64, F64x2, U32, )
|
||||
OPCODE(CompositeExtractF64x3, F64, F64x3, U32, )
|
||||
OPCODE(CompositeExtractF64x4, F64, F64x4, U32, )
|
||||
|
||||
// Select operations
|
||||
OPCODE(Select8, U8, U1, U8, U8, )
|
||||
|
@ -91,12 +111,18 @@ OPCODE(Select32, U32, U1,
|
|||
OPCODE(Select64, U64, U1, U64, U64, )
|
||||
|
||||
// Bitwise conversions
|
||||
OPCODE(PackUint2x32, U64, Opaque, )
|
||||
OPCODE(UnpackUint2x32, Opaque, U64, )
|
||||
OPCODE(PackFloat2x16, U32, Opaque, )
|
||||
OPCODE(UnpackFloat2x16, Opaque, U32, )
|
||||
OPCODE(PackDouble2x32, U64, Opaque, )
|
||||
OPCODE(UnpackDouble2x32, Opaque, U64, )
|
||||
OPCODE(BitCastU16F16, U16, F16, )
|
||||
OPCODE(BitCastU32F32, U32, F32, )
|
||||
OPCODE(BitCastU64F64, U64, F64, )
|
||||
OPCODE(BitCastF16U16, F16, U16, )
|
||||
OPCODE(BitCastF32U32, F32, U32, )
|
||||
OPCODE(BitCastF64U64, F64, U64, )
|
||||
OPCODE(PackUint2x32, U64, U32x2, )
|
||||
OPCODE(UnpackUint2x32, U32x2, U64, )
|
||||
OPCODE(PackFloat2x16, U32, F16x2, )
|
||||
OPCODE(UnpackFloat2x16, F16x2, U32, )
|
||||
OPCODE(PackDouble2x32, U64, U32x2, )
|
||||
OPCODE(UnpackDouble2x32, U32x2, U64, )
|
||||
|
||||
// Pseudo-operation, handled specially at final emit
|
||||
OPCODE(GetZeroFromOp, U1, Opaque, )
|
||||
|
@ -105,52 +131,52 @@ OPCODE(GetCarryFromOp, U1, Opaq
|
|||
OPCODE(GetOverflowFromOp, U1, Opaque, )
|
||||
|
||||
// Floating-point operations
|
||||
OPCODE(FPAbs16, U16, U16, )
|
||||
OPCODE(FPAbs32, U32, U32, )
|
||||
OPCODE(FPAbs64, U64, U64, )
|
||||
OPCODE(FPAdd16, U16, U16, U16, )
|
||||
OPCODE(FPAdd32, U32, U32, U32, )
|
||||
OPCODE(FPAdd64, U64, U64, U64, )
|
||||
OPCODE(FPFma16, U16, U16, U16, U16, )
|
||||
OPCODE(FPFma32, U32, U32, U32, U32, )
|
||||
OPCODE(FPFma64, U64, U64, U64, U64, )
|
||||
OPCODE(FPMax32, U32, U32, U32, )
|
||||
OPCODE(FPMax64, U64, U64, U64, )
|
||||
OPCODE(FPMin32, U32, U32, U32, )
|
||||
OPCODE(FPMin64, U64, U64, U64, )
|
||||
OPCODE(FPMul16, U16, U16, U16, )
|
||||
OPCODE(FPMul32, U32, U32, U32, )
|
||||
OPCODE(FPMul64, U64, U64, U64, )
|
||||
OPCODE(FPNeg16, U16, U16, )
|
||||
OPCODE(FPNeg32, U32, U32, )
|
||||
OPCODE(FPNeg64, U64, U64, )
|
||||
OPCODE(FPRecip32, U32, U32, )
|
||||
OPCODE(FPRecip64, U64, U64, )
|
||||
OPCODE(FPRecipSqrt32, U32, U32, )
|
||||
OPCODE(FPRecipSqrt64, U64, U64, )
|
||||
OPCODE(FPSqrt, U32, U32, )
|
||||
OPCODE(FPSin, U32, U32, )
|
||||
OPCODE(FPSinNotReduced, U32, U32, )
|
||||
OPCODE(FPExp2, U32, U32, )
|
||||
OPCODE(FPExp2NotReduced, U32, U32, )
|
||||
OPCODE(FPCos, U32, U32, )
|
||||
OPCODE(FPCosNotReduced, U32, U32, )
|
||||
OPCODE(FPLog2, U32, U32, )
|
||||
OPCODE(FPSaturate16, U16, U16, )
|
||||
OPCODE(FPSaturate32, U32, U32, )
|
||||
OPCODE(FPSaturate64, U64, U64, )
|
||||
OPCODE(FPRoundEven16, U16, U16, )
|
||||
OPCODE(FPRoundEven32, U32, U32, )
|
||||
OPCODE(FPRoundEven64, U64, U64, )
|
||||
OPCODE(FPFloor16, U16, U16, )
|
||||
OPCODE(FPFloor32, U32, U32, )
|
||||
OPCODE(FPFloor64, U64, U64, )
|
||||
OPCODE(FPCeil16, U16, U16, )
|
||||
OPCODE(FPCeil32, U32, U32, )
|
||||
OPCODE(FPCeil64, U64, U64, )
|
||||
OPCODE(FPTrunc16, U16, U16, )
|
||||
OPCODE(FPTrunc32, U32, U32, )
|
||||
OPCODE(FPTrunc64, U64, U64, )
|
||||
OPCODE(FPAbs16, F16, F16, )
|
||||
OPCODE(FPAbs32, F32, F32, )
|
||||
OPCODE(FPAbs64, F64, F64, )
|
||||
OPCODE(FPAdd16, F16, F16, F16, )
|
||||
OPCODE(FPAdd32, F32, F32, F32, )
|
||||
OPCODE(FPAdd64, F64, F64, F64, )
|
||||
OPCODE(FPFma16, F16, F16, F16, F16, )
|
||||
OPCODE(FPFma32, F32, F32, F32, F32, )
|
||||
OPCODE(FPFma64, F64, F64, F64, F64, )
|
||||
OPCODE(FPMax32, F32, F32, F32, )
|
||||
OPCODE(FPMax64, F64, F64, F64, )
|
||||
OPCODE(FPMin32, F32, F32, F32, )
|
||||
OPCODE(FPMin64, F64, F64, F64, )
|
||||
OPCODE(FPMul16, F16, F16, F16, )
|
||||
OPCODE(FPMul32, F32, F32, F32, )
|
||||
OPCODE(FPMul64, F64, F64, F64, )
|
||||
OPCODE(FPNeg16, F16, F16, )
|
||||
OPCODE(FPNeg32, F32, F32, )
|
||||
OPCODE(FPNeg64, F64, F64, )
|
||||
OPCODE(FPRecip32, F32, F32, )
|
||||
OPCODE(FPRecip64, F64, F64, )
|
||||
OPCODE(FPRecipSqrt32, F32, F32, )
|
||||
OPCODE(FPRecipSqrt64, F64, F64, )
|
||||
OPCODE(FPSqrt, F32, F32, )
|
||||
OPCODE(FPSin, F32, F32, )
|
||||
OPCODE(FPSinNotReduced, F32, F32, )
|
||||
OPCODE(FPExp2, F32, F32, )
|
||||
OPCODE(FPExp2NotReduced, F32, F32, )
|
||||
OPCODE(FPCos, F32, F32, )
|
||||
OPCODE(FPCosNotReduced, F32, F32, )
|
||||
OPCODE(FPLog2, F32, F32, )
|
||||
OPCODE(FPSaturate16, F16, F16, )
|
||||
OPCODE(FPSaturate32, F32, F32, )
|
||||
OPCODE(FPSaturate64, F64, F64, )
|
||||
OPCODE(FPRoundEven16, F16, F16, )
|
||||
OPCODE(FPRoundEven32, F32, F32, )
|
||||
OPCODE(FPRoundEven64, F64, F64, )
|
||||
OPCODE(FPFloor16, F16, F16, )
|
||||
OPCODE(FPFloor32, F32, F32, )
|
||||
OPCODE(FPFloor64, F64, F64, )
|
||||
OPCODE(FPCeil16, F16, F16, )
|
||||
OPCODE(FPCeil32, F32, F32, )
|
||||
OPCODE(FPCeil64, F64, F64, )
|
||||
OPCODE(FPTrunc16, F16, F16, )
|
||||
OPCODE(FPTrunc32, F32, F32, )
|
||||
OPCODE(FPTrunc64, F64, F64, )
|
||||
|
||||
// Integer operations
|
||||
OPCODE(IAdd32, U32, U32, U32, )
|
||||
|
@ -188,24 +214,24 @@ OPCODE(LogicalXor, U1, U1,
|
|||
OPCODE(LogicalNot, U1, U1, )
|
||||
|
||||
// Conversion operations
|
||||
OPCODE(ConvertS16F16, U32, U16, )
|
||||
OPCODE(ConvertS16F32, U32, U32, )
|
||||
OPCODE(ConvertS16F64, U32, U64, )
|
||||
OPCODE(ConvertS32F16, U32, U16, )
|
||||
OPCODE(ConvertS32F32, U32, U32, )
|
||||
OPCODE(ConvertS32F64, U32, U64, )
|
||||
OPCODE(ConvertS64F16, U64, U16, )
|
||||
OPCODE(ConvertS64F32, U64, U32, )
|
||||
OPCODE(ConvertS64F64, U64, U64, )
|
||||
OPCODE(ConvertU16F16, U32, U16, )
|
||||
OPCODE(ConvertU16F32, U32, U32, )
|
||||
OPCODE(ConvertU16F64, U32, U64, )
|
||||
OPCODE(ConvertU32F16, U32, U16, )
|
||||
OPCODE(ConvertU32F32, U32, U32, )
|
||||
OPCODE(ConvertU32F64, U32, U64, )
|
||||
OPCODE(ConvertU64F16, U64, U16, )
|
||||
OPCODE(ConvertU64F32, U64, U32, )
|
||||
OPCODE(ConvertU64F64, U64, U64, )
|
||||
OPCODE(ConvertS16F16, U32, F16, )
|
||||
OPCODE(ConvertS16F32, U32, F32, )
|
||||
OPCODE(ConvertS16F64, U32, F64, )
|
||||
OPCODE(ConvertS32F16, U32, F16, )
|
||||
OPCODE(ConvertS32F32, U32, F32, )
|
||||
OPCODE(ConvertS32F64, U32, F64, )
|
||||
OPCODE(ConvertS64F16, U64, F16, )
|
||||
OPCODE(ConvertS64F32, U64, F32, )
|
||||
OPCODE(ConvertS64F64, U64, F64, )
|
||||
OPCODE(ConvertU16F16, U32, F16, )
|
||||
OPCODE(ConvertU16F32, U32, F32, )
|
||||
OPCODE(ConvertU16F64, U32, F64, )
|
||||
OPCODE(ConvertU32F16, U32, F16, )
|
||||
OPCODE(ConvertU32F32, U32, F32, )
|
||||
OPCODE(ConvertU32F64, U32, F64, )
|
||||
OPCODE(ConvertU64F16, U64, F16, )
|
||||
OPCODE(ConvertU64F32, U64, F32, )
|
||||
OPCODE(ConvertU64F64, U64, F64, )
|
||||
|
||||
OPCODE(ConvertU64U32, U64, U32, )
|
||||
OPCODE(ConvertU32U64, U32, U64, )
|
||||
|
|
|
@ -11,7 +11,9 @@ namespace Shader::IR {
|
|||
|
||||
std::string NameOf(Type type) {
|
||||
static constexpr std::array names{
|
||||
"Opaque", "Label", "Reg", "Pred", "Attribute", "U1", "U8", "U16", "U32", "U64",
|
||||
"Opaque", "Label", "Reg", "Pred", "Attribute", "U1", "U8", "U16", "U32",
|
||||
"U64", "F16", "F32", "F64", "U32x2", "U32x3", "U32x4", "F16x2", "F16x3",
|
||||
"F16x4", "F32x2", "F32x3", "F32x4", "F64x2", "F64x3", "F64x4",
|
||||
};
|
||||
const size_t bits{static_cast<size_t>(type)};
|
||||
if (bits == 0) {
|
||||
|
|
|
@ -25,6 +25,21 @@ enum class Type {
|
|||
U16 = 1 << 7,
|
||||
U32 = 1 << 8,
|
||||
U64 = 1 << 9,
|
||||
F16 = 1 << 10,
|
||||
F32 = 1 << 11,
|
||||
F64 = 1 << 12,
|
||||
U32x2 = 1 << 13,
|
||||
U32x3 = 1 << 14,
|
||||
U32x4 = 1 << 15,
|
||||
F16x2 = 1 << 16,
|
||||
F16x3 = 1 << 17,
|
||||
F16x4 = 1 << 18,
|
||||
F32x2 = 1 << 19,
|
||||
F32x3 = 1 << 20,
|
||||
F32x4 = 1 << 21,
|
||||
F64x2 = 1 << 22,
|
||||
F64x3 = 1 << 23,
|
||||
F64x4 = 1 << 24,
|
||||
};
|
||||
DECLARE_ENUM_FLAG_OPERATORS(Type)
|
||||
|
||||
|
|
|
@ -26,8 +26,12 @@ Value::Value(u16 value) noexcept : type{Type::U16}, imm_u16{value} {}
|
|||
|
||||
Value::Value(u32 value) noexcept : type{Type::U32}, imm_u32{value} {}
|
||||
|
||||
Value::Value(f32 value) noexcept : type{Type::F32}, imm_f32{value} {}
|
||||
|
||||
Value::Value(u64 value) noexcept : type{Type::U64}, imm_u64{value} {}
|
||||
|
||||
Value::Value(f64 value) noexcept : type{Type::F64}, imm_f64{value} {}
|
||||
|
||||
bool Value::IsIdentity() const noexcept {
|
||||
return type == Type::Opaque && inst->Opcode() == Opcode::Identity;
|
||||
}
|
||||
|
@ -122,6 +126,14 @@ u32 Value::U32() const {
|
|||
return imm_u32;
|
||||
}
|
||||
|
||||
f32 Value::F32() const {
|
||||
if (IsIdentity()) {
|
||||
return inst->Arg(0).F32();
|
||||
}
|
||||
ValidateAccess(Type::F32);
|
||||
return imm_f32;
|
||||
}
|
||||
|
||||
u64 Value::U64() const {
|
||||
if (IsIdentity()) {
|
||||
return inst->Arg(0).U64();
|
||||
|
@ -152,11 +164,27 @@ bool Value::operator==(const Value& other) const {
|
|||
case Type::U8:
|
||||
return imm_u8 == other.imm_u8;
|
||||
case Type::U16:
|
||||
case Type::F16:
|
||||
return imm_u16 == other.imm_u16;
|
||||
case Type::U32:
|
||||
case Type::F32:
|
||||
return imm_u32 == other.imm_u32;
|
||||
case Type::U64:
|
||||
case Type::F64:
|
||||
return imm_u64 == other.imm_u64;
|
||||
case Type::U32x2:
|
||||
case Type::U32x3:
|
||||
case Type::U32x4:
|
||||
case Type::F16x2:
|
||||
case Type::F16x3:
|
||||
case Type::F16x4:
|
||||
case Type::F32x2:
|
||||
case Type::F32x3:
|
||||
case Type::F32x4:
|
||||
case Type::F64x2:
|
||||
case Type::F64x3:
|
||||
case Type::F64x4:
|
||||
break;
|
||||
}
|
||||
throw LogicError("Invalid type {}", type);
|
||||
}
|
||||
|
|
|
@ -28,7 +28,9 @@ public:
|
|||
explicit Value(u8 value) noexcept;
|
||||
explicit Value(u16 value) noexcept;
|
||||
explicit Value(u32 value) noexcept;
|
||||
explicit Value(f32 value) noexcept;
|
||||
explicit Value(u64 value) noexcept;
|
||||
explicit Value(f64 value) noexcept;
|
||||
|
||||
[[nodiscard]] bool IsIdentity() const noexcept;
|
||||
[[nodiscard]] bool IsEmpty() const noexcept;
|
||||
|
@ -46,6 +48,7 @@ public:
|
|||
[[nodiscard]] u8 U8() const;
|
||||
[[nodiscard]] u16 U16() const;
|
||||
[[nodiscard]] u32 U32() const;
|
||||
[[nodiscard]] f32 F32() const;
|
||||
[[nodiscard]] u64 U64() const;
|
||||
|
||||
[[nodiscard]] bool operator==(const Value& other) const;
|
||||
|
@ -65,7 +68,9 @@ private:
|
|||
u8 imm_u8;
|
||||
u16 imm_u16;
|
||||
u32 imm_u32;
|
||||
f32 imm_f32;
|
||||
u64 imm_u64;
|
||||
f64 imm_f64;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -93,8 +98,13 @@ using U8 = TypedValue<Type::U8>;
|
|||
using U16 = TypedValue<Type::U16>;
|
||||
using U32 = TypedValue<Type::U32>;
|
||||
using U64 = TypedValue<Type::U64>;
|
||||
using F16 = TypedValue<Type::F16>;
|
||||
using F32 = TypedValue<Type::F32>;
|
||||
using F64 = TypedValue<Type::F64>;
|
||||
using U32U64 = TypedValue<Type::U32 | Type::U64>;
|
||||
using F32F64 = TypedValue<Type::F32 | Type::F64>;
|
||||
using U16U32U64 = TypedValue<Type::U16 | Type::U32 | Type::U64>;
|
||||
using F16F32F64 = TypedValue<Type::F16 | Type::F32 | Type::F64>;
|
||||
using UAny = TypedValue<Type::U8 | Type::U16 | Type::U32 | Type::U64>;
|
||||
|
||||
} // namespace Shader::IR
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue