diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2018-09-25 17:59:16 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-09-25 17:59:16 -0400 |
| commit | ee549942335add195df8e69a31f65a691d54aff9 (patch) | |
| tree | 949513e7a8f4abdfe6be2b333d34fa5f9e4c373a | |
| parent | 4f979d74acf2800d7bd2b38155d2bdc47b57d54b (diff) | |
Improve IROp lookup (#650)
* * Change the layout of IROp such that 'main' IROps are 0-x.
* Removed MANUAL_RANGE instuction types, as no longer needed.
* Work in prog on optimizing.
* * Constant time lookup for IROpInfo
* Refactor and document a little more the IROp layout
* Mark ops that use 'other' bits
* Fix typo in definition of kIROpFlag_UseOther
| -rw-r--r-- | source/slang/core.meta.slang | 4 | ||||
| -rw-r--r-- | source/slang/core.meta.slang.h | 4 | ||||
| -rw-r--r-- | source/slang/hlsl.meta.slang | 2 | ||||
| -rw-r--r-- | source/slang/hlsl.meta.slang.h | 2 | ||||
| -rw-r--r-- | source/slang/ir-inst-defs.h | 8 | ||||
| -rw-r--r-- | source/slang/ir.cpp | 53 | ||||
| -rw-r--r-- | source/slang/ir.h | 31 |
7 files changed, 69 insertions, 35 deletions
diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang index aa93863df..89a7f75db 100644 --- a/source/slang/core.meta.slang +++ b/source/slang/core.meta.slang @@ -461,7 +461,7 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt) sb << "__generic<T = float4> "; sb << "__magic_type(TextureSampler," << int(flavor) << ")\n"; - sb << "__intrinsic_type(" << (kIROp_TextureSamplerType + (int(flavor) << kIROp_Mask_Shift)) << ")\n"; + sb << "__intrinsic_type(" << (kIROp_TextureSamplerType + (int(flavor) << kIROpMeta_Shift)) << ")\n"; sb << "struct Sampler"; sb << kBaseTextureAccessLevels[accessLevel].name; sb << name; @@ -519,7 +519,7 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt) sb << "__generic<T = float4> "; sb << "__magic_type(Texture," << int(flavor) << ")\n"; - sb << "__intrinsic_type(" << (kIROp_TextureType + (int(flavor) << kIROp_Mask_Shift)) << ")\n"; + sb << "__intrinsic_type(" << (kIROp_TextureType + (int(flavor) << kIROpMeta_Shift)) << ")\n"; sb << "struct "; sb << kBaseTextureAccessLevels[accessLevel].name; sb << name; diff --git a/source/slang/core.meta.slang.h b/source/slang/core.meta.slang.h index 01bb01137..76a121fe8 100644 --- a/source/slang/core.meta.slang.h +++ b/source/slang/core.meta.slang.h @@ -476,7 +476,7 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt) sb << "__generic<T = float4> "; sb << "__magic_type(TextureSampler," << int(flavor) << ")\n"; - sb << "__intrinsic_type(" << (kIROp_TextureSamplerType + (int(flavor) << kIROp_Mask_Shift)) << ")\n"; + sb << "__intrinsic_type(" << (kIROp_TextureSamplerType + (int(flavor) << kIROpMeta_Shift)) << ")\n"; sb << "struct Sampler"; sb << kBaseTextureAccessLevels[accessLevel].name; sb << name; @@ -534,7 +534,7 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt) sb << "__generic<T = float4> "; sb << "__magic_type(Texture," << int(flavor) << ")\n"; - sb << "__intrinsic_type(" << (kIROp_TextureType + (int(flavor) << kIROp_Mask_Shift)) << ")\n"; + sb << "__intrinsic_type(" << (kIROp_TextureType + (int(flavor) << kIROpMeta_Shift)) << ")\n"; sb << "struct "; sb << kBaseTextureAccessLevels[accessLevel].name; sb << name; diff --git a/source/slang/hlsl.meta.slang b/source/slang/hlsl.meta.slang index ac993179e..a9e2cc6df 100644 --- a/source/slang/hlsl.meta.slang +++ b/source/slang/hlsl.meta.slang @@ -1250,7 +1250,7 @@ for (int aa = 0; aa < kBaseBufferAccessLevelCount; ++aa) auto flavor = TextureFlavor::create(TextureFlavor::Shape::ShapeBuffer, kBaseBufferAccessLevels[aa].access).flavor; sb << "__generic<T>\n"; sb << "__magic_type(Texture," << int(flavor) << ")\n"; - sb << "__intrinsic_type(" << (kIROp_TextureType + (int(flavor) << kIROp_Mask_Shift)) << ")\n"; + sb << "__intrinsic_type(" << (kIROp_TextureType + (int(flavor) << kIROpMeta_Shift)) << ")\n"; sb << "struct "; sb << kBaseBufferAccessLevels[aa].name; sb << "Buffer {\n"; diff --git a/source/slang/hlsl.meta.slang.h b/source/slang/hlsl.meta.slang.h index 967330729..a4ed6ec2c 100644 --- a/source/slang/hlsl.meta.slang.h +++ b/source/slang/hlsl.meta.slang.h @@ -1295,7 +1295,7 @@ for (int aa = 0; aa < kBaseBufferAccessLevelCount; ++aa) auto flavor = TextureFlavor::create(TextureFlavor::Shape::ShapeBuffer, kBaseBufferAccessLevels[aa].access).flavor; sb << "__generic<T>\n"; sb << "__magic_type(Texture," << int(flavor) << ")\n"; - sb << "__intrinsic_type(" << (kIROp_TextureType + (int(flavor) << kIROp_Mask_Shift)) << ")\n"; + sb << "__intrinsic_type(" << (kIROp_TextureType + (int(flavor) << kIROpMeta_Shift)) << ")\n"; sb << "struct "; sb << kBaseBufferAccessLevels[aa].name; sb << "Buffer {\n"; diff --git a/source/slang/ir-inst-defs.h b/source/slang/ir-inst-defs.h index 43437e793..661626dd4 100644 --- a/source/slang/ir-inst-defs.h +++ b/source/slang/ir-inst-defs.h @@ -13,6 +13,7 @@ #endif #define PARENT kIROpFlag_Parent +#define USE_OTHER kIROpFlag_UseOther INST(Nop, nop, 0, 0) @@ -80,11 +81,11 @@ INST(Nop, nop, 0, 0) /* TextureTypeBase */ // NOTE! TextureFlavor::Flavor is stored in 'other' bits for these types. /* TextureType */ - INST(TextureType, TextureType, 0, 0) + INST(TextureType, TextureType, 0, USE_OTHER) /* TextureSamplerType */ - INST(TextureSamplerType, TextureSamplerType, 0, 0) + INST(TextureSamplerType, TextureSamplerType, 0, USE_OTHER) /* GLSLImageType */ - INST(GLSLImageType, GLSLImageType, 0, 0) + INST(GLSLImageType, GLSLImageType, 0, USE_OTHER) INST_RANGE(TextureTypeBase, TextureType, GLSLImageType) INST_RANGE(ResourceType, TextureType, GLSLImageType) INST_RANGE(ResourceTypeBase, TextureType, GLSLImageType) @@ -383,6 +384,7 @@ PSEUDO_INST(Or) #undef PSEUDO_INST #undef PARENT +#undef USE_OTHER #undef INST_RANGE #undef INST diff --git a/source/slang/ir.cpp b/source/slang/ir.cpp index c9131325b..c72a4a705 100644 --- a/source/slang/ir.cpp +++ b/source/slang/ir.cpp @@ -23,42 +23,69 @@ namespace Slang // TODO: We should ideally be speeding up the name->inst // mapping by using a dictionary, or even by pre-computing // a hash table to be stored as a `static const` array. + // + // NOTE! That this array is now constructed in such a way that looking up + // an entry from an op is fast, by keeping blocks of main, and pseudo ops in same order + // as the ops themselves. Care must be taken to keep this constraint. static const IROpMapEntry kIROps[] = { - { kIROp_Invalid, { "invalid", 0, 0 } }, - + + // Main ops in order #define INST(ID, MNEMONIC, ARG_COUNT, FLAGS) \ { kIROp_##ID, { #MNEMONIC, ARG_COUNT, FLAGS, } }, +#include "ir-inst-defs.h" + + // Pseudo ops +#define INST(ID, MNEMONIC, ARG_COUNT, FLAGS) /* empty */ #define PSEUDO_INST(ID) \ { kIRPseudoOp_##ID, { #ID, 0, 0 } }, + + // First is 'invalid' + { kIROp_Invalid,{ "invalid", 0, 0 } }, + // Then all the other psuedo ops #include "ir-inst-defs.h" }; - // - - IROp findIROp(char const* name) + IROpInfo getIROpInfo(IROp opIn) { - for (auto ee : kIROps) + const int op = opIn & kIROpMeta_OpMask; + if ((op & kIROpMeta_IsPseudoOp) && op < kIRPseudoOp_LastPlusOne) { - if (strcmp(name, ee.info.name) == 0) - return ee.op; + // It's a pseudo op + const int index = op - kIRPseudoOp_First; + // Pseudo ops start from kIROpcount + const auto& entry = kIROps[kIROpCount + index]; + SLANG_ASSERT(entry.op == op); + return entry.info; + } + else if (op < kIROpCount) + { + // It's a main op + const auto& entry = kIROps[op]; + SLANG_ASSERT(entry.op == op); + return entry.info; } - return IROp(kIROp_Invalid); + // Don't know what this is + SLANG_ASSERT(!"Invalid op"); + SLANG_ASSERT(kIROps[kIROpCount].op == kIROp_Invalid); + return kIROps[kIROpCount].info; } - IROpInfo getIROpInfo(IROp op) + IROp findIROp(char const* name) { for (auto ee : kIROps) { - if (ee.op == op) - return ee.info; + if (strcmp(name, ee.info.name) == 0) + return ee.op; } - return kIROps[0].info; + return IROp(kIROp_Invalid); } + + // void IRUse::debugValidate() diff --git a/source/slang/ir.h b/source/slang/ir.h index 739a38e84..6627acd5d 100644 --- a/source/slang/ir.h +++ b/source/slang/ir.h @@ -33,9 +33,8 @@ typedef unsigned int IROpFlags; enum : IROpFlags { kIROpFlags_None = 0, - - // This op is a parent op - kIROpFlag_Parent = 1 << 0, + kIROpFlag_Parent = 1 << 0, ///< This op is a parent op + kIROpFlag_UseOther = 1 << 1, ///< If set this op can use 'other bits' to store information }; /* Bit usage of IROp is a follows @@ -45,7 +44,7 @@ Bit range: 0-7 | 8 | Remaining bits If an instruction is 'pseudo' (ie shouldn't appear in output IR), then the Pseudo bit is set - and 'Invalid' falls into this category as well as all pseudo ops. -For doing range checks (for example for doing isa tests), the value is masked by kIROp_Mask_OpMask, such that the Other bits don't interfere. +For doing range checks (for example for doing isa tests), the value is masked by kIROpMeta_OpMask, such that the Other bits don't interfere. The other bits can be used for storage for anything that needs to identify as a different 'op' or 'type'. It is currently used currently for storing the TextureFlavor of a IRResourceTypeBase derived types for example. */ @@ -61,13 +60,14 @@ enum IROp : int32_t // We use the range 0x100 to 0x1ff set for pseudo/non main codes // Instructions that should not appear in valid IR. - kIROp_Invalid = 0x100, ///< If bit set, then in pseudo/not normal space - kIRPseduoOp_FirstPseudo, + kIRPseudoOp_First = kIROp_Invalid, #define INST(ID, MNEMONIC, ARG_COUNT, FLAGS) /* empty */ #define PSEUDO_INST(ID) kIRPseudoOp_##ID, + kIRPseudoOp_LastPlusOne, + #include "ir-inst-defs.h" #define INST(ID, MNEMONIC, ARG_COUNT, FLAGS) /* empty */ @@ -76,14 +76,19 @@ enum IROp : int32_t kIROp_Last##BASE = kIROp_##LAST, #include "ir-inst-defs.h" +}; - kIROp_Mask_Shift = 9, - kIROp_Mask_OpMask = (int32_t(1) << kIROp_Mask_Shift) - 1, ///< Mask for regular ops - kIROp_Mask_OtherMask = ~kIROp_Mask_OpMask, +/* IROpMeta describe values for layout of IROp, as well as values for accessing aspects of IROp bits. */ +enum IROpMeta +{ + kIROpMeta_Shift = 9, ///< Number of bits for op/pseudo ops (shift right by this to get the other bits) + kIROpMeta_OpMask = (int32_t(1) << kIROpMeta_Shift) - 1, ///< Mask for regular ops + kIrOpMeta_OtherMask = ~kIROpMeta_OpMask, ///< Mask for bits that can be used for other purposes than 'op' ('other' bits) + kIROpMeta_IsPseudoOp = kIROp_Invalid, ///< 'And' with op, if set, the op is a pseudo op }; // True if op is pseudo (or invalid which is 'pseudo-like' at least in as so far as current behavior) -SLANG_FORCE_INLINE bool isPseudoOp(IROp op) { return (op & kIROp_Invalid) != 0; } +SLANG_FORCE_INLINE bool isPseudoOp(IROp op) { return (op & kIROpMeta_IsPseudoOp) != 0; } IROp findIROp(char const* name); @@ -418,8 +423,8 @@ struct IRInstList : IRInstListBase // Types -#define IR_LEAF_ISA(NAME) static bool isaImpl(IROp op) { return (kIROp_Mask_OpMask & op) == kIROp_##NAME; } -#define IR_PARENT_ISA(NAME) static bool isaImpl(IROp opIn) { const int op = (kIROp_Mask_OpMask & opIn); return op >= kIROp_First##NAME && op <= kIROp_Last##NAME; } +#define IR_LEAF_ISA(NAME) static bool isaImpl(IROp op) { return (kIROpMeta_OpMask & op) == kIROp_##NAME; } +#define IR_PARENT_ISA(NAME) static bool isaImpl(IROp opIn) { const int op = (kIROpMeta_OpMask & opIn); return op >= kIROp_First##NAME && op <= kIROp_Last##NAME; } #define SIMPLE_IR_TYPE(NAME, BASE) struct IR##NAME : IR##BASE { IR_LEAF_ISA(NAME) }; #define SIMPLE_IR_PARENT_TYPE(NAME, BASE) struct IR##NAME : IR##BASE { IR_PARENT_ISA(NAME) }; @@ -696,7 +701,7 @@ struct IRResourceTypeBase : IRType { TextureFlavor getFlavor() const { - return TextureFlavor((op >> kIROp_Mask_Shift) & 0xFFFF); + return TextureFlavor((op >> kIROpMeta_Shift) & 0xFFFF); } TextureFlavor::Shape GetBaseShape() const |
