diff options
Diffstat (limited to 'source')
| -rw-r--r-- | source/slang/core.meta.slang | 82 | ||||
| -rw-r--r-- | source/slang/slang-emit-c-like.cpp | 8 | ||||
| -rw-r--r-- | source/slang/slang-emit-spirv.cpp | 4 | ||||
| -rw-r--r-- | source/slang/slang-hlsl-intrinsic-set.cpp | 6 | ||||
| -rw-r--r-- | source/slang/slang-ir-autodiff-fwd.cpp | 9 | ||||
| -rw-r--r-- | source/slang/slang-ir-constexpr.cpp | 48 | ||||
| -rw-r--r-- | source/slang/slang-ir-inline.cpp | 29 | ||||
| -rw-r--r-- | source/slang/slang-ir-inst-defs.h | 12 | ||||
| -rw-r--r-- | source/slang/slang-ir-insts.h | 13 | ||||
| -rw-r--r-- | source/slang/slang-ir-link.cpp | 1 | ||||
| -rw-r--r-- | source/slang/slang-ir-liveness.cpp | 14 | ||||
| -rw-r--r-- | source/slang/slang-ir-peephole.cpp | 3 | ||||
| -rw-r--r-- | source/slang/slang-ir-sccp.cpp | 19 | ||||
| -rw-r--r-- | source/slang/slang-ir-util.cpp | 29 | ||||
| -rw-r--r-- | source/slang/slang-ir-util.h | 1 | ||||
| -rw-r--r-- | source/slang/slang-ir.cpp | 8 | ||||
| -rw-r--r-- | source/slang/slang-lower-to-ir.cpp | 32 | ||||
| -rw-r--r-- | source/slang/slang-stdlib.cpp | 25 |
18 files changed, 299 insertions, 44 deletions
diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang index 73a004720..17af354ca 100644 --- a/source/slang/core.meta.slang +++ b/source/slang/core.meta.slang @@ -83,6 +83,7 @@ interface __BuiltinType {} /// A type that can be used for arithmetic operations [sealed] [builtin] +[TreatAsDifferentiable] interface __BuiltinArithmeticType : __BuiltinType { /// Initialize from a 32-bit signed integer value. @@ -140,6 +141,7 @@ interface __BuiltinRealType : __BuiltinSignedArithmeticType {} /// A type that uses a floating-point representation [sealed] [builtin] +[TreatAsDifferentiable] interface __BuiltinFloatingPointType : __BuiltinRealType, IDifferentiable { /// Initialize from a 32-bit floating-point value. @@ -201,7 +203,9 @@ extension __EnumType // interface, but right now the scoping for looking // up that type isn't working right. // + __intrinsic_op($(kIROp_IntCast)) __init(int value); + __intrinsic_op($(kIROp_IntCast)) __init(uint value); } @@ -302,8 +306,13 @@ ${{{{ ConversionCost conversionCost = getBaseTypeConversionCost( kBaseTypes[tt], kBaseTypes[ss]); + + IROp intrinsicOpCode = getBaseTypeConversionOp( + kBaseTypes[tt], + kBaseTypes[ss]); }}}} + __intrinsic_op($(intrinsicOpCode)) __implicit_conversion($(conversionCost)) __init($(kBaseTypes[ss].name) value); @@ -325,6 +334,7 @@ ${{{{ case BaseType::UInt: }}}} __generic<T:__EnumType> + __intrinsic_op($(kIROp_IntCast)) __init(T value); ${{{{ break; @@ -380,6 +390,7 @@ ${{{{ }}}} __generic<T> [__readNone] + __intrinsic_op($(kIROp_CastToVoid)) __init(T value) {} ${{{{ @@ -416,10 +427,10 @@ struct Ptr __intrinsic_op($(kIROp_BitCast)) __init(Ptr<U> ptr); - __intrinsic_op($(kIROp_BitCast)) + __intrinsic_op($(kIROp_CastIntToPtr)) __init(uint64_t val); - __intrinsic_op($(kIROp_BitCast)) + __intrinsic_op($(kIROp_CastIntToPtr)) __init(int64_t val); __subscript(int index) -> T @@ -491,7 +502,7 @@ extension bool extension uint64_t { __generic<T> - __intrinsic_op($(kIROp_Construct)) + __intrinsic_op($(kIROp_CastPtrToInt)) __init(Ptr<T> ptr); static const uint64_t maxValue = 0xFFFFFFFFFFFFFFFFULL; @@ -501,7 +512,7 @@ extension uint64_t extension int64_t { __generic<T> - __intrinsic_op($(kIROp_Construct)) + __intrinsic_op($(kIROp_CastPtrToInt)) __init(Ptr<T> ptr); static const int64_t maxValue = 0x7FFFFFFFFFFFFFFFLL; @@ -511,7 +522,7 @@ extension int64_t extension intptr_t { __generic<T> - __intrinsic_op($(kIROp_Construct)) + __intrinsic_op($(kIROp_CastPtrToInt)) __init(Ptr<T> ptr); static const intptr_t maxValue = $(SLANG_PROCESSOR_X86_64?"0x7FFFFFFFFFFFFFFFz":"0x7FFFFFFFz"); static const intptr_t minValue = $(SLANG_PROCESSOR_X86_64?"0x8000000000000000z":"0x80000000z"); @@ -521,7 +532,7 @@ extension intptr_t extension uintptr_t { __generic<T> - __intrinsic_op($(kIROp_Construct)) + __intrinsic_op($(kIROp_CastPtrToInt)) __init(Ptr<T> ptr); static const uintptr_t maxValue = $(SLANG_PROCESSOR_X86_64?"0xFFFFFFFFFFFFFFFFz":"0xFFFFFFFFz"); static const uintptr_t minValue = 0z; @@ -620,16 +631,22 @@ __intrinsic_type($(kIROp_StringType)) struct String { __target_intrinsic(cpp) + __intrinsic_op($(kIROp_makeString)) __init(int val); __target_intrinsic(cpp) + __intrinsic_op($(kIROp_makeString)) __init(uint val); __target_intrinsic(cpp) + __intrinsic_op($(kIROp_makeString)) __init(int64_t val); __target_intrinsic(cpp) + __intrinsic_op($(kIROp_makeString)) __init(uint64_t val); __target_intrinsic(cpp) + __intrinsic_op($(kIROp_makeString)) __init(float val); __target_intrinsic(cpp) + __intrinsic_op($(kIROp_makeString)) __init(double val); __target_intrinsic(cpp) @@ -750,6 +767,7 @@ struct vector /// Initialize a vector from a value of the same type // TODO: we should revise semantic checking so this kind of "identity" conversion is not required + __intrinsic_op(0) __init(vector<T,N> value); } @@ -871,22 +889,49 @@ struct Primitives __generic<T> __extension vector<T, 2> { + __intrinsic_op($(kIROp_makeVector)) __init(T x, T y); } __generic<T> __extension vector<T, 3> { + __intrinsic_op($(kIROp_makeVector)) __init(T x, T y, T z); + + [__unsafeForceInlineEarly] + __intrinsic_op($(kIROp_makeVector)) __init(vector<T,2> xy, T z); + + [__unsafeForceInlineEarly] + __intrinsic_op($(kIROp_makeVector)) __init(T x, vector<T,2> yz); } __generic<T> __extension vector<T, 4> { + __intrinsic_op($(kIROp_makeVector)) __init(T x, T y, T z, T w); + + [__unsafeForceInlineEarly] + __intrinsic_op($(kIROp_makeVector)) __init(vector<T,2> xy, T z, T w); + + [__unsafeForceInlineEarly] + __intrinsic_op($(kIROp_makeVector)) __init(T x, vector<T,2> yz, T w); + + [__unsafeForceInlineEarly] + __intrinsic_op($(kIROp_makeVector)) __init(T x, T y, vector<T,2> zw); + + [__unsafeForceInlineEarly] + __intrinsic_op($(kIROp_makeVector)) __init(vector<T,2> xy, vector<T,2> zw); + + [__unsafeForceInlineEarly] + __intrinsic_op($(kIROp_makeVector)) __init(vector<T,3> xyz, T w); + + [__unsafeForceInlineEarly] + __intrinsic_op($(kIROp_makeVector)) __init(T x, vector<T,3> yzw); } @@ -915,16 +960,24 @@ for (int tt = 0; tt < kBaseTypeCount; ++tt) auto cost = getBaseTypeConversionCost( kBaseTypes[tt], kBaseTypes[ff]); + auto op = getBaseTypeConversionOp( + kBaseTypes[tt], + kBaseTypes[ff]); // Implicit conversion from a vector of the same // size, but different element type. sb << " __implicit_conversion(" << cost << ")\n"; + sb << " __intrinsic_op(" << int(op) << ")\n"; sb << " __init(vector<" << kBaseTypes[ff].name << ",N> value);\n"; // Constructor to make a vector from a scalar of another type. - cost += kConversionCost_ScalarToVector; - sb << " __implicit_conversion(" << cost << ")\n"; - sb << " __init(" << kBaseTypes[ff].name << " value);\n"; + if (cost != kConversionCost_Impossible) + { + cost += kConversionCost_ScalarToVector; + sb << " __implicit_conversion(" << cost << ")\n"; + sb << " [__unsafeForceInlineEarly]\n"; + sb << " __init(" << kBaseTypes[ff].name << " value) { this = vector<" << kBaseTypes[tt].name << ",N>( " << kBaseTypes[tt].name << "(value)); }\n"; + } } } sb << "}\n"; @@ -936,7 +989,7 @@ for( int C = 2; C <= 4; ++C ) sb << "__generic<T> __extension matrix<T, " << R << "," << C << ">\n{\n"; // initialize from R*C scalars - sb << "__init("; + sb << "__intrinsic_op(" << int(kIROp_MakeMatrix) << ") __init("; for( int ii = 0; ii < R; ++ii ) for( int jj = 0; jj < C; ++jj ) { @@ -946,7 +999,7 @@ for( int C = 2; C <= 4; ++C ) sb << ");\n"; // Initialize from R C-vectors - sb << "__init("; + sb << "__intrinsic_op(" << int(kIROp_MakeMatrix) << ") __init("; for (int ii = 0; ii < R; ++ii) { if(ii != 0) sb << ", "; @@ -959,7 +1012,7 @@ for( int C = 2; C <= 4; ++C ) for( int cc = C; cc <= 4; ++cc ) { if(rr == R && cc == C) continue; - sb << "__init(matrix<T," << rr << "," << cc << "> value);\n"; + sb << "__intrinsic_op(" << int(kIROp_MatrixTruncate) << ") __init(matrix<T," << rr << "," << cc << "> value);\n"; } sb << "}\n"; } @@ -982,8 +1035,12 @@ ${{{{ kBaseTypes[tt], kBaseTypes[ff]); auto fromType = kBaseTypes[ff].name; + auto op = getBaseTypeConversionOp( + kBaseTypes[tt], + kBaseTypes[ff]); }}}} __implicit_conversion($(cost)) + __intrinsic_op($(op)) __init(matrix<$(fromType),R,C> value); ${{{{ } @@ -1026,6 +1083,7 @@ extension matrix<T, R, C> : IDifferentiable { typedef matrix<T, R, C> Differential; + __intrinsic_op($(kIROp_MakeMatrixFromScalar)) __init(T val); [__unsafeForceInlineEarly] diff --git a/source/slang/slang-emit-c-like.cpp b/source/slang/slang-emit-c-like.cpp index 1ac50b8a7..fa5e9a821 100644 --- a/source/slang/slang-emit-c-like.cpp +++ b/source/slang/slang-emit-c-like.cpp @@ -1779,6 +1779,12 @@ void CLikeSourceEmitter::defaultEmitInstExpr(IRInst* inst, const EmitOpInfo& inO case kIROp_Construct: case kIROp_makeVector: case kIROp_MakeMatrix: + case kIROp_MakeMatrixFromScalar: + case kIROp_MatrixTruncate: + case kIROp_CastFloatToInt: + case kIROp_CastIntToFloat: + case kIROp_IntCast: + case kIROp_FloatCast: // Simple constructor call emitType(inst->getDataType()); emitArgs(inst); @@ -1798,6 +1804,8 @@ void CLikeSourceEmitter::defaultEmitInstExpr(IRInst* inst, const EmitOpInfo& inO m_writer->emit(")"); break; case kIROp_constructVectorFromScalar: + case kIROp_CastPtrToInt: + case kIROp_CastIntToPtr: { // Simple constructor call auto prec = getInfo(EmitOp::Prefix); diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp index 85699ad95..c0431cbeb 100644 --- a/source/slang/slang-emit-spirv.cpp +++ b/source/slang/slang-emit-spirv.cpp @@ -1602,6 +1602,10 @@ struct SPIRVEmitContext case kIROp_swizzle: return emitSwizzle(parent, as<IRSwizzle>(inst)); case kIROp_Construct: + case kIROp_IntCast: + case kIROp_FloatCast: + case kIROp_CastIntToFloat: + case kIROp_CastFloatToInt: return emitConstruct(parent, inst); case kIROp_BitCast: return emitInst( diff --git a/source/slang/slang-hlsl-intrinsic-set.cpp b/source/slang/slang-hlsl-intrinsic-set.cpp index e6010bda2..8d5944112 100644 --- a/source/slang/slang-hlsl-intrinsic-set.cpp +++ b/source/slang/slang-hlsl-intrinsic-set.cpp @@ -256,12 +256,17 @@ SlangResult HLSLIntrinsicSet::makeIntrinsic(IRInst* inst, HLSLIntrinsic& out) switch (inst->getOp()) { case kIROp_constructVectorFromScalar: + case kIROp_MakeMatrixFromScalar: { SLANG_ASSERT(inst->getOperandCount() == 1); calcIntrinsic(Op::ConstructFromScalar, inst, 1, out); return SLANG_OK; } case kIROp_Construct: + case kIROp_IntCast: + case kIROp_FloatCast: + case kIROp_CastIntToFloat: + case kIROp_CastFloatToInt: { IRType* dstType = inst->getDataType(); IRType* srcType = inst->getOperand(0)->getDataType(); @@ -307,6 +312,7 @@ SlangResult HLSLIntrinsicSet::makeIntrinsic(IRInst* inst, HLSLIntrinsic& out) return SLANG_OK; } case kIROp_MakeMatrix: + case kIROp_MatrixTruncate: { // We only emit as if it has one operand, but we can tell how many it actually has from the return type calcIntrinsic(Op::Init, inst, inst->getOperandCount(), out); diff --git a/source/slang/slang-ir-autodiff-fwd.cpp b/source/slang/slang-ir-autodiff-fwd.cpp index c94342736..8a9fdaf6f 100644 --- a/source/slang/slang-ir-autodiff-fwd.cpp +++ b/source/slang/slang-ir-autodiff-fwd.cpp @@ -1582,7 +1582,14 @@ InstPair ForwardDerivativeTranscriber::transcribeInst(IRBuilder* builder, IRInst case kIROp_Leq: return transcribeBinaryLogic(builder, origInst); - case kIROp_Construct: + case kIROp_CastIntToFloat: + case kIROp_CastFloatToInt: + case kIROp_makeVector: + case kIROp_MakeMatrix: + case kIROp_MakeMatrixFromScalar: + case kIROp_MatrixTruncate: + case kIROp_IntCast: + case kIROp_FloatCast: return transcribeConstruct(builder, origInst); case kIROp_lookup_interface_method: diff --git a/source/slang/slang-ir-constexpr.cpp b/source/slang/slang-ir-constexpr.cpp index bc669fa6b..8a772485f 100644 --- a/source/slang/slang-ir-constexpr.cpp +++ b/source/slang/slang-ir-constexpr.cpp @@ -76,10 +76,56 @@ bool opCanBeConstExpr(IROp op) case kIROp_IRem: case kIROp_FRem: case kIROp_Neg: + case kIROp_Geq: + case kIROp_Leq: + case kIROp_Greater: + case kIROp_Less: + case kIROp_Neq: + case kIROp_Eql: + case kIROp_BitAnd: + case kIROp_BitOr: + case kIROp_BitXor: + case kIROp_BitNot: + case kIROp_Lsh: + case kIROp_Rsh: + case kIROp_Select: case kIROp_Construct: + case kIROp_constructVectorFromScalar: case kIROp_makeVector: - case kIROp_makeArray: case kIROp_MakeMatrix: + case kIROp_MakeMatrixFromScalar: + case kIROp_CastFloatToInt: + case kIROp_CastIntToFloat: + case kIROp_IntCast: + case kIROp_FloatCast: + case kIROp_CastIntToPtr: + case kIROp_CastPtrToInt: + case kIROp_CastPtrToBool: + case kIROp_Reinterpret: + case kIROp_BitCast: + case kIROp_MakeTuple: + case kIROp_MakeDifferentialPair: + case kIROp_MakeExistential: + case kIROp_MakeExistentialWithRTTI: + case kIROp_MakeOptionalNone: + case kIROp_MakeOptionalValue: + case kIROp_MakeResultError: + case kIROp_MakeResultValue: + case kIROp_makeString: + case kIROp_makeUInt64: + case kIROp_makeArray: + case kIROp_swizzle: + case kIROp_getElement: + case kIROp_FieldExtract: + case kIROp_ExtractExistentialType: + case kIROp_ExtractExistentialValue: + case kIROp_ExtractExistentialWitnessTable: + case kIROp_WrapExistential: + case kIROp_GetResultError: + case kIROp_GetResultValue: + case kIROp_GetOptionalValue: + case kIROp_DifferentialPairGetDifferential: + case kIROp_DifferentialPairGetPrimal: // TODO: more cases return true; diff --git a/source/slang/slang-ir-inline.cpp b/source/slang/slang-ir-inline.cpp index f49b52975..36eea8c54 100644 --- a/source/slang/slang-ir-inline.cpp +++ b/source/slang/slang-ir-inline.cpp @@ -198,6 +198,9 @@ struct InliningPassBase // outCallSite.callee = calleeFunc; + if (callee->findDecoration<IRIntrinsicOpDecoration>()) + return true; + // At this point the `CallSiteInfo` is complete and // could be used for inlining, but we have additional // checks to make. @@ -239,6 +242,27 @@ struct InliningPassBase IRBuilder builder(sharedBuilder); builder.setInsertBefore(call); + // If callee is an intrinsic op, just issue that intrinsic and be done. + if (auto intrinsicOpDecor = callee->findDecoration<IRIntrinsicOpDecoration>()) + { + List<IRInst*> args; + for (UInt i = 0; i < call->getArgCount(); i++) + args.add(call->getArg(i)); + auto op = intrinsicOpDecor->getIntrinsicOp(); + if (op == 0) + { + SLANG_RELEASE_ASSERT(call->getArgCount() >= 1); + call->replaceUsesWith(call->getArg(0)); + } + else + { + auto newCall = builder.emitIntrinsicInst(call->getFullType(), op, args.getCount(), args.getBuffer()); + call->replaceUsesWith(newCall); + } + call->removeAndDeallocate(); + return; + } + // If the callee is a generic function, then we will // need to include the substitution of generic parameters // with their argument values in our cloning. @@ -506,6 +530,8 @@ struct MandatoryEarlyInliningPass : InliningPassBase { if(info.callee->findDecoration<IRUnsafeForceInlineEarlyDecoration>()) return true; + if (info.callee->findDecoration<IRIntrinsicOpDecoration>()) + return true; return false; } }; @@ -618,7 +644,8 @@ struct ForceInliningPass : InliningPassBase bool shouldInline(CallSiteInfo const& info) { if (info.callee->findDecoration<IRForceInlineDecoration>() || - info.callee->findDecoration<IRUnsafeForceInlineEarlyDecoration>()) + info.callee->findDecoration<IRUnsafeForceInlineEarlyDecoration>()|| + info.callee->findDecoration<IRIntrinsicOpDecoration>()) return true; return false; } diff --git a/source/slang/slang-ir-inst-defs.h b/source/slang/slang-ir-inst-defs.h index c07200715..e5df5fc5c 100644 --- a/source/slang/slang-ir-inst-defs.h +++ b/source/slang/slang-ir-inst-defs.h @@ -289,6 +289,9 @@ INST(AllocObj, allocObj, 0, 0) INST(makeUInt64, makeUInt64, 2, 0) INST(makeVector, makeVector, 0, 0) INST(MakeMatrix, makeMatrix, 0, 0) +INST(MakeMatrixFromScalar, makeMatrixFromScalar, 1, 0) +INST(MatrixTruncate, matrixTrunc, 1, 0) + INST(makeArray, makeArray, 0, 0) INST(makeStruct, makeStruct, 0, 0) INST(MakeTuple, makeTuple, 0, 0) @@ -577,6 +580,7 @@ INST(GetOptiXSbtDataPtr, getOptiXSbtDataPointer, 0, 0) INST(HighLevelDeclDecoration, highLevelDecl, 1, 0) INST(LayoutDecoration, layout, 1, 0) INST(LoopControlDecoration, loopControl, 1, 0) + INST(IntrinsicOpDecoration, intrinsicOp, 1, 0) /* TargetSpecificDecoration */ INST(TargetDecoration, target, 1, 0) INST(TargetIntrinsicDecoration, targetIntrinsic, 2, 0) @@ -793,7 +797,15 @@ INST(ExtractTaggedUnionPayload, extractTaggedUnionPayload, 1, 0) INST(BitCast, bitCast, 1, 0) INST(Reinterpret, reinterpret, 1, 0) +INST(IntCast, intCast, 1, 0) +INST(FloatCast, floatCast, 1, 0) +INST(CastIntToFloat, castIntToFloat, 1, 0) +INST(CastFloatToInt, castFloatToInt, 1, 0) INST(CastPtrToBool, CastPtrToBool, 1, 0) +INST(CastPtrToInt, CastPtrToInt, 1, 0) +INST(CastIntToPtr, CastIntToPtr, 1, 0) +INST(CastToVoid, castToVoid, 1, 0) + INST(IsType, IsType, 3, 0) INST(ForwardDifferentiate, ForwardDifferentiate, 1, 0) INST(BackwardDifferentiate, BackwardDifferentiate, 1, 0) diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h index c45d187f4..ae6516ed0 100644 --- a/source/slang/slang-ir-insts.h +++ b/source/slang/slang-ir-insts.h @@ -95,6 +95,19 @@ struct IRTargetIntrinsicDecoration : IRTargetSpecificDecoration } }; +struct IRIntrinsicOpDecoration : IRDecoration +{ + enum { kOp = kIROp_IntrinsicOpDecoration }; + IR_LEAF_ISA(IntrinsicOpDecoration) + + IRIntLit* getIntrinsicOpOperand() { return cast<IRIntLit>(getOperand(0)); } + + IROp getIntrinsicOp() + { + return (IROp)getIntrinsicOpOperand()->getValue(); + } +}; + struct IRGLSLOuterArrayDecoration : IRDecoration { enum { kOp = kIROp_GLSLOuterArrayDecoration }; diff --git a/source/slang/slang-ir-link.cpp b/source/slang/slang-ir-link.cpp index 3e85cc40e..ea4bfb7b9 100644 --- a/source/slang/slang-ir-link.cpp +++ b/source/slang/slang-ir-link.cpp @@ -432,6 +432,7 @@ static void cloneExtraDecorationsFromInst( case kIROp_PublicDecoration: case kIROp_SequentialIDDecoration: case kIROp_ForwardDerivativeDecoration: + case kIROp_IntrinsicOpDecoration: if (!clonedInst->findDecorationImpl(decoration->getOp())) { cloneInst(context, builder, decoration); diff --git a/source/slang/slang-ir-liveness.cpp b/source/slang/slang-ir-liveness.cpp index b708307c2..4a39dc612 100644 --- a/source/slang/slang-ir-liveness.cpp +++ b/source/slang/slang-ir-liveness.cpp @@ -1023,9 +1023,21 @@ bool LivenessContext::_isAccessTerminator(IRTerminatorInst* terminator) // we have a cast between uint/int (for example) that isn't a problem // Strip construct - if (val->getOp() == kIROp_Construct && val->getOperandCount() == 1) + switch (val->getOp()) { + case kIROp_Construct: + if (val->getOperandCount() == 1) + val = val->getOperand(0); + break; + case kIROp_CastIntToFloat: + case kIROp_CastFloatToInt: + case kIROp_IntCast: + case kIROp_FloatCast: + case kIROp_CastIntToPtr: + case kIROp_CastPtrToInt: + case kIROp_CastPtrToBool: val = val->getOperand(0); + break; } // If it *is* the root it's an access diff --git a/source/slang/slang-ir-peephole.cpp b/source/slang/slang-ir-peephole.cpp index 788110330..a39f50dca 100644 --- a/source/slang/slang-ir-peephole.cpp +++ b/source/slang/slang-ir-peephole.cpp @@ -112,6 +112,9 @@ struct PeepholeContext : InstPassBase } break; case kIROp_Reinterpret: + case kIROp_BitCast: + case kIROp_IntCast: + case kIROp_FloatCast: { if (isTypeEqual(inst->getOperand(0)->getDataType(), inst->getDataType())) { diff --git a/source/slang/slang-ir-sccp.cpp b/source/slang/slang-ir-sccp.cpp index 0bee2565c..fbc00848b 100644 --- a/source/slang/slang-ir-sccp.cpp +++ b/source/slang/slang-ir-sccp.cpp @@ -136,7 +136,10 @@ struct SCCPContext case kIROp_BitXor: case kIROp_BitNot: case kIROp_BitCast: - case kIROp_Construct: + case kIROp_CastIntToFloat: + case kIROp_CastFloatToInt: + case kIROp_IntCast: + case kIROp_FloatCast: case kIROp_Select: return true; default: @@ -284,7 +287,7 @@ struct SCCPContext break; \ } - LatticeVal evalConstruct(IRType* type, LatticeVal v0) + LatticeVal evalCast(IRType* type, LatticeVal v0) { SLANG_SCCP_RETURN_IF_NONE_OR_ANY(v0) auto irConstant = as<IRConstant>(v0.value); @@ -838,18 +841,20 @@ struct SCCPContext switch (inst->getOp()) { - case kIROp_Construct: + case kIROp_IntCast: + case kIROp_FloatCast: + case kIROp_CastIntToFloat: + case kIROp_CastFloatToInt: switch (inst->getOperandCount()) { - case 0: - return evalDefaultConstruct(inst->getDataType()); - case 1: - return evalConstruct(inst->getDataType(), getLatticeVal(inst->getOperand(0))); + return evalCast(inst->getDataType(), getLatticeVal(inst->getOperand(0))); default: return LatticeVal::getAny(); } + case kIROp_DefaultConstruct: + return evalDefaultConstruct(inst->getDataType()); case kIROp_Add: return evalAdd( inst->getDataType(), diff --git a/source/slang/slang-ir-util.cpp b/source/slang/slang-ir-util.cpp index 214f10ef9..5c4590abe 100644 --- a/source/slang/slang-ir-util.cpp +++ b/source/slang/slang-ir-util.cpp @@ -100,4 +100,33 @@ IROp getTypeStyle(IROp op) } } +IROp getTypeStyle(BaseType op) +{ + switch (op) + { + case BaseType::Void: + return kIROp_VoidType; + case BaseType::Bool: + return kIROp_BoolType; + case BaseType::Char: + case BaseType::Int8: + case BaseType::Int16: + case BaseType::Int: + case BaseType::Int64: + case BaseType::IntPtr: + case BaseType::UInt8: + case BaseType::UInt16: + case BaseType::UInt: + case BaseType::UInt64: + case BaseType::UIntPtr: + return kIROp_IntType; + case BaseType::Half: + case BaseType::Float: + case BaseType::Double: + return kIROp_FloatType; + default: + return kIROp_Invalid; + } +} + } diff --git a/source/slang/slang-ir-util.h b/source/slang/slang-ir-util.h index b6690a28c..b09b2f4d0 100644 --- a/source/slang/slang-ir-util.h +++ b/source/slang/slang-ir-util.h @@ -26,6 +26,7 @@ bool isComInterfaceType(IRType* type); IROp getTypeStyle(IROp op); +IROp getTypeStyle(BaseType op); inline bool isScalarIntegerType(IRType* type) { diff --git a/source/slang/slang-ir.cpp b/source/slang/slang-ir.cpp index ecfcab7f5..fcf821b69 100644 --- a/source/slang/slang-ir.cpp +++ b/source/slang/slang-ir.cpp @@ -6319,6 +6319,8 @@ namespace Slang case kIROp_makeUInt64: case kIROp_makeVector: case kIROp_MakeMatrix: + case kIROp_MakeMatrixFromScalar: + case kIROp_MatrixTruncate: case kIROp_makeArray: case kIROp_makeStruct: case kIROp_makeString: @@ -6373,6 +6375,12 @@ namespace Slang case kIROp_ExtractExistentialWitnessTable: case kIROp_WrapExistential: case kIROp_BitCast: + case kIROp_CastFloatToInt: + case kIROp_CastIntToFloat: + case kIROp_IntCast: + case kIROp_FloatCast: + case kIROp_CastPtrToInt: + case kIROp_CastIntToPtr: case kIROp_AllocObj: case kIROp_PackAnyValue: case kIROp_UnpackAnyValue: diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp index f836824f7..7fd0bbee7 100644 --- a/source/slang/slang-lower-to-ir.cpp +++ b/source/slang/slang-lower-to-ir.cpp @@ -16,6 +16,7 @@ #include "slang-ir-sccp.h" #include "slang-ir-ssa.h" #include "slang-ir-strip.h" +#include "slang-ir-simplify-cfg.h" #include "slang-ir-validate.h" #include "slang-ir-string-hash.h" #include "slang-ir-clone.h" @@ -721,22 +722,9 @@ LoweredValInfo emitCallToDeclRef( if( auto ctorDeclRef = funcDeclRef.as<ConstructorDecl>() ) { - if(!ctorDeclRef.getDecl()->body && isFromStdLib(ctorDeclRef.decl)) + if(!ctorDeclRef.getDecl()->body && isFromStdLib(ctorDeclRef.decl) && !as<InterfaceDecl>(ctorDeclRef.decl->parentDecl)) { - // HACK: For legacy reasons, all of the built-in initializers - // in the standard library are declared without proper - // intrinsic-op modifiers, so we will assume that an - // initializer without a body should map to `kIROp_Construct`. - // - // TODO: We should make all the initializers in the - // standard library have either a body or a proper - // intrinsic-op modifier. - // - // TODO: We should eliminate `kIROp_Construct` from the - // IR completely, in favor of more detailed/specific ops - // that cover the cases we actually care about. - // - return LoweredValInfo::simple(builder->emitConstructorInst(type, argCount, args)); + SLANG_UNREACHABLE("stdlib error: __init() has no definition."); } } @@ -8328,6 +8316,12 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> getBuilder()->addDecoration(irFunc, kIROp_TreatAsDifferentiableDecoration); } + if (auto intrinsicOp = decl->findModifier<IntrinsicOpModifier>()) + { + auto op = getBuilder()->getIntValue(getBuilder()->getIntType(), intrinsicOp->op); + getBuilder()->addDecoration(irFunc, kIROp_IntrinsicOpDecoration, op); + } + // Register the value now, to avoid any possible infinite recursion when lowering ForwardDerivativeAttribute setGlobalValue(context, decl, LoweredValInfo::simple(findOuterMostGeneric(irFunc))); @@ -9060,12 +9054,10 @@ RefPtr<IRModule> generateIRForTranslationUnit( performMandatoryEarlyInlining(module); // Next, attempt to promote local variables to SSA - // temporaries whenever possible. - constructSSA(module); - - // Do basic constant folding and dead code elimination - // using Sparse Conditional Constant Propagation (SCCP) + // temporaries and do basic simplifications. // + constructSSA(module); + simplifyCFG(module); applySparseConditionalConstantPropagation(module); // Propagate `constexpr`-ness through the dataflow graph (and the diff --git a/source/slang/slang-stdlib.cpp b/source/slang/slang-stdlib.cpp index 6df9eea46..352d4ee27 100644 --- a/source/slang/slang-stdlib.cpp +++ b/source/slang/slang-stdlib.cpp @@ -3,7 +3,7 @@ #include "slang-compiler.h" #include "slang-ir.h" #include "slang-syntax.h" - +#include "slang-ir-util.h" #include "../core/slang-string-util.h" #define STRINGIZE(x) STRINGIZE2(x) @@ -193,6 +193,29 @@ namespace Slang } } + IROp getBaseTypeConversionOp( + BaseTypeConversionInfo const& toInfo, + BaseTypeConversionInfo const& fromInfo) + { + if (toInfo.tag == fromInfo.tag) + return (IROp)0; + + IROp intrinsicOpCode = (IROp)0; + auto toStyle = getTypeStyle(toInfo.tag); + auto fromStyle = getTypeStyle(fromInfo.tag); + if (toStyle == kIROp_BoolType) toStyle = kIROp_IntType; + if (fromStyle == kIROp_BoolType) fromStyle = kIROp_IntType; + if (toStyle == kIROp_IntType && fromStyle == kIROp_IntType) + intrinsicOpCode = kIROp_IntCast; + if (toStyle == kIROp_IntType && fromStyle == kIROp_FloatType) + intrinsicOpCode = kIROp_CastFloatToInt; + if (toStyle == kIROp_FloatType && fromStyle == kIROp_IntType) + intrinsicOpCode = kIROp_CastIntToFloat; + if (toStyle == kIROp_FloatType && fromStyle == kIROp_FloatType) + intrinsicOpCode = kIROp_FloatCast; + return intrinsicOpCode; + } + struct IntrinsicOpInfo { IROp opCode; char const* funcName; char const* opName; char const* interface; unsigned flags; }; static const IntrinsicOpInfo intrinsicUnaryOps[] = { |
