summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/slang/core.meta.slang82
-rw-r--r--source/slang/slang-emit-c-like.cpp8
-rw-r--r--source/slang/slang-emit-spirv.cpp4
-rw-r--r--source/slang/slang-hlsl-intrinsic-set.cpp6
-rw-r--r--source/slang/slang-ir-autodiff-fwd.cpp9
-rw-r--r--source/slang/slang-ir-constexpr.cpp48
-rw-r--r--source/slang/slang-ir-inline.cpp29
-rw-r--r--source/slang/slang-ir-inst-defs.h12
-rw-r--r--source/slang/slang-ir-insts.h13
-rw-r--r--source/slang/slang-ir-link.cpp1
-rw-r--r--source/slang/slang-ir-liveness.cpp14
-rw-r--r--source/slang/slang-ir-peephole.cpp3
-rw-r--r--source/slang/slang-ir-sccp.cpp19
-rw-r--r--source/slang/slang-ir-util.cpp29
-rw-r--r--source/slang/slang-ir-util.h1
-rw-r--r--source/slang/slang-ir.cpp8
-rw-r--r--source/slang/slang-lower-to-ir.cpp32
-rw-r--r--source/slang/slang-stdlib.cpp25
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[] = {