From 5de3003af561bad33680940ab1809622c428e94b Mon Sep 17 00:00:00 2001 From: Tim Foley Date: Thu, 17 Aug 2017 09:46:19 -0700 Subject: IR generation cleanup work - Make all instructions store their argument count for now, so we can iterate over them easily. - Longer term we might try to optimize for space because the common case is that the operand count is known, but keeping it simpler seems better for now - Split apart the creation of an instruction from adding it to a parent - Use the above capability to make sure that we add a function to its parent *after* all the parameter/result type emission has occured. - Perform simple value numbering for types during IR creation - This logic also tries to pick a good parent for any type instructions, so that types don't get created local to a function unless they really need to - Create all constants at global scope, and re-use when values are identical --- source/slang/ir.h | 71 +++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 56 insertions(+), 15 deletions(-) (limited to 'source/slang/ir.h') diff --git a/source/slang/ir.h b/source/slang/ir.h index 95dec6007..0a0c8d612 100644 --- a/source/slang/ir.h +++ b/source/slang/ir.h @@ -60,6 +60,8 @@ struct IRUse void init(IRInst* user, IRInst* usedValue); }; +typedef uint32_t IRInstID; + // In the IR, almost *everything* is an instruction, // in order to make the representation as uniform as possible. struct IRInst @@ -70,7 +72,11 @@ struct IRInst // A unique ID to represent the op when printing // (or zero to indicate that the value of this // op isn't special). - UInt id; + IRInstID id; + + // The total number of arguments of this instruction + // (including the type) + uint32_t argCount; // The parent of this instruction. // This will often be a basic block, but we @@ -95,14 +101,16 @@ typedef IRInst IRValue; typedef long long IRIntegerValue; typedef double IRFloatingPointValue; -struct IRIntLit : IRInst -{ - IRIntegerValue value; -}; - -struct IRFloatLit : IRInst +struct IRConstant : IRInst { - IRFloatingPointValue value; + union + { + IRIntegerValue intVal; + IRFloatingPointValue floatVal; + + // HACK: allows us to hash the value easily + void* ptrData[2]; + } u; }; // Representation of a type at the IR level. @@ -188,20 +196,52 @@ struct IRFunc : IRParentInst struct IRModule : IRParentInst { // The designated entry-point function, if any - IRFunc* entryPoint; + IRFunc* entryPoint; // A special counter used to assign logical ids to instructions in this module. - UInt idCounter; + IRInstID idCounter; }; -struct IRBuilder +// Description of an instruction to be used for global value numbering +struct IRInstKey +{ + IRInst* inst; + + int GetHashCode(); +}; + +bool operator==(IRInstKey const& left, IRInstKey const& right); + +struct IRConstantKey +{ + IRConstant* inst; + + int GetHashCode(); +}; +bool operator==(IRConstantKey const& left, IRConstantKey const& right); + +struct SharedIRBuilder { // The module that will own all of the IR IRModule* module; + Dictionary globalValueNumberingMap; + Dictionary constantMap; +}; + +struct IRBuilder +{ + // Shared state for all IR builders working on the same module + SharedIRBuilder* shared; + + IRModule* getModule() { return shared->module; } + // The parent instruction to add children to. IRParentInst* parentInst; + void addInst(IRParentInst* parent, IRInst* inst); + void addInst(IRInst* inst); + IRType* getBaseType(BaseType flavor); IRType* getBoolType(); IRType* getVectorType(IRType* elementType, IRValue* elementCount); @@ -232,19 +272,20 @@ struct IRBuilder IRFunc* createFunc(); IRBlock* createBlock(); + IRBlock* emitBlock(); - IRParam* createParam( + IRParam* emitParam( IRType* type); - IRInst* createFieldExtract( + IRInst* emitFieldExtract( IRType* type, IRValue* base, UInt fieldIndex); - IRInst* createReturn( + IRInst* emitReturn( IRValue* val); - IRInst* createReturn(); + IRInst* emitReturn(); }; void dumpIR(IRModule* module); -- cgit v1.2.3