/*===================== begin_copyright_notice ==================================

Copyright (c) 2017 Intel Corporation

Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


======================= end_copyright_notice ==================================*/

#include <sstream>
#include <fstream>
#include <functional>
#include "visa_igc_common_header.h"
#include "Common_ISA.h"
#include "Common_ISA_util.h"
#include "Common_ISA_framework.h"
#include "JitterDataStruct.h"
#include "VISAKernel.h"
#include "Timer.h"
#include "FlowGraph.h"
#include "BuildIR.h"
#include "Optimizer.h"
#include "BinaryEncoding.h"
#include "BinaryEncodingCNL.h"
#include "Common_BinaryEncoding.h"
#include "DebugInfo.h"
#include "iga/IGALibrary/IR/Instruction.hpp"
#include "BinaryEncodingIGA.h"

#if defined( _DEBUG ) && ( defined( _WIN32 ) || defined( _WIN64 ) )
#include <windows.h>
#endif

using namespace std;
using namespace CisaFramework;
using namespace vISA;
#define SIZE_VALUE m_kernel_data_size
#define SIZE_VALUE_INST m_instruction_size

#define IS_GEN_PATH  (mBuildOption == CM_CISA_BUILDER_GEN)
#define IS_BOTH_PATH (mBuildOption == CM_CISA_BUILDER_BOTH)
#define IS_GEN_BOTH_PATH  (mBuildOption == CM_CISA_BUILDER_GEN || mBuildOption ==  CM_CISA_BUILDER_BOTH)
#ifdef IS_RELEASE_DLL
#define IS_VISA_BOTH_PATH 0
#else
#define IS_VISA_BOTH_PATH (mBuildOption == CM_CISA_BUILDER_CISA || mBuildOption ==  CM_CISA_BUILDER_BOTH)
#endif


static CM_INLINE void PACK_EXEC_SIZE( unsigned int &size, Common_VISA_EMask_Ctrl eMask )
{
    size |= eMask << 4;
}

static CM_INLINE void ADD_OPND( int &num_operands, VISA_opnd **opnd, VISA_opnd * topnd )
{
    if( topnd != NULL )
    {
        opnd[num_operands++] = topnd;
    }

}

#define CM_ERROR_PRINT( error_msg ) std::cerr<< error_msg <<std::endl;
static CM_INLINE int  CHECK_NUM_OPNDS(VISA_INST_Desc *instDesc, int numOperands, int predOpnds)
{
    if((instDesc->opnd_num -predOpnds) != numOperands)
    {
        CM_ERROR_PRINT("Number of parameters does not match");
        std::cerr<<"LINE: "<<__LINE__<<std::endl;
        std::cerr<<"FUNCTION: "<<__FUNCTION__<<std::endl;
        CmAssert( 0 );
        return CM_FAILURE;
    }
    return CM_SUCCESS;
}
static CM_INLINE void GET_NUM_PRED_DESC_OPNDS(int &predOpnd, VISA_INST_Desc *inst_desc_temp )
{
    predOpnd = 0;
    for(int i = 0; i < inst_desc_temp->opnd_num; i++)
    {
        if(inst_desc_temp->opnd_desc[i].opnd_type == OPND_EXECSIZE ||
            inst_desc_temp->opnd_desc[i].opnd_type == OPND_PRED)
            predOpnd++;
    }
}

#if defined(_DEBUG) || defined(_INTERNAL)
    #define START_ASSERT_CHECK 1
#else
   #define START_ASSERT_CHECK 0
#endif

#define GET_G4_OPNG( obj) (obj != NULL) ? obj->g4opnd : NULL

int VISAKernelImpl::calculateTotalInputSize()
{
    for(unsigned int i = 0; i < m_builder->getInputCount(); i++)
    {
        input_info_t * temp = m_builder->getInputArg(i);
        if(m_inputSize < (unsigned int)(temp->offset + temp->size))
        {
            m_inputSize = temp->offset + temp->size;
        }
    }
    return CM_SUCCESS;
}

int VISAKernelImpl::compileFastPath()
{
    int status = CM_SUCCESS;
    if (getIsKernel())
    {
        status = calculateTotalInputSize();
    }

    if (status != CM_SUCCESS)
    {
        return status;
    }

    IR_Builder& builder = *m_builder;
    builder.predefinedVarRegAssignment((uint8_t)m_inputSize);
    builder.expandPredefinedVars();
    builder.resizePredefinedStackVars();
    status = compileTillOptimize();
    return status;
}

void replaceFCOpcodes(IR_Builder& builder)
{
    BB_LIST_ITER bbEnd = builder.kernel.fg.BBs.end();

    for(BB_LIST_ITER bb_it = builder.kernel.fg.BBs.begin();
        bb_it != bbEnd;
        bb_it++)
    {
        G4_BB* bb = (*bb_it);

        if(bb->size() > 0)
        {
            // pseudo_fc_call/ret would always be last
            // instruction in BB so only look at back
            // of instlist.
            G4_INST* lastInstInBB = bb->back();

            if(lastInstInBB->opcode() == G4_pseudo_fc_call)
            {
                lastInstInBB->setOpcode(G4_call);
            }
            else if(lastInstInBB->opcode() == G4_pseudo_fc_ret)
            {
                lastInstInBB->setOpcode(G4_return);
            }
        }
    }
}

static void setDeclAlignment(G4_Declare* dcl, VISA_Align align)
{
    switch (align)
    {
    case ALIGN_BYTE: //no alignment;
    case ALIGN_WORD: dcl->setAlign(Either); dcl->setSubRegAlign(Any); break; //word aligned;
    case ALIGN_DWORD: dcl->setAlign(Either); dcl->setSubRegAlign(Even_Word); break;//dword aligned;
    case ALIGN_QWORD: dcl->setAlign(Either); dcl->setSubRegAlign(Four_Word); break;//8 byte aligned;
    case ALIGN_OWORD: dcl->setAlign(Either); dcl->setSubRegAlign(Eight_Word); break;//oword aligned;
    case ALIGN_GRF: dcl->setAlign(Either); dcl->setSubRegAlign(SUB_ALIGNMENT_GRFALIGN); break;//grf aligned;
    case ALIGN_2_GRF: dcl->setAlign(Even); dcl->setSubRegAlign(SUB_ALIGNMENT_GRFALIGN); break; //2 grf aligned;
    default: assert(false && "Incorrect vISA alignment"); break;
    }
}

int VISAKernelImpl::compileTillOptimize()
{
    // For separate compilation run compilation till RA then return
    startTimer(TIMER_CFG);
    m_kernel->fg.constructFlowGraph(m_builder->instList);
    stopTimer(TIMER_CFG);

    // move the options into the function, like LIR

    Optimizer optimizer(*m_kernelMem, *m_builder, *m_kernel, m_kernel->fg);

    return optimizer.optimization();
}

G4_Declare* VISAKernelImpl::createInstsForCallTargetOffset(InstListType& insts, G4_INST* fcall)
{
    // create instruction sequence:
    //       add  r1.2  -IP   call_target
    //       add  r1.2  r1.2  32

    // calculate the reserved register's num from fcall's dst register
    assert(fcall->getDst()->isGreg());
    uint32_t reg_num = fcall->getDst()->getLinearizedStart() / GENX_GRF_REG_SIZ;
    // hardcoded add's dst subregister to 2
    G4_Declare* add_dst_decl =
        m_builder->createHardwiredDeclare(1, fcall->getDst()->getType(), reg_num, 2);

    // create the first add instruction
    G4_INST* add_inst = m_builder->createInternalInst(
        nullptr, G4_add, nullptr, false, 1,
        m_builder->Create_Dst_Opnd_From_Dcl(add_dst_decl, 1),
        m_builder->createSrcRegRegion(
            Mod_Minus, Direct, m_phyRegPool->getIpReg(), 0, 0,
            m_builder->getRegionScalar(), Type_UD),
        fcall->getSrc(0), InstOpt_WriteEnable | InstOpt_NoCompact);

    // create the second add to add the ip to 32, to get the call's ip
    G4_INST* add_inst2 = m_builder->createInternalInst(
        nullptr, G4_add, nullptr, false, 1,
        m_builder->Create_Dst_Opnd_From_Dcl(add_dst_decl, 1),
        m_builder->Create_Src_Opnd_From_Dcl(
            add_dst_decl, m_builder->getRegionScalar()),
        m_builder->createImm(32, add_inst->getSrc(0)->getType()),
        InstOpt_WriteEnable | InstOpt_NoCompact);

    insts.push_back(add_inst);
    insts.push_back(add_inst2);

    return add_dst_decl;
}

void VISAKernelImpl::createInstsForRetIP(InstListType& insts, G4_INST* fcall)
{
    // SKL workaround for indirect call
    // create instruction sequence:
    //       mov  f0.0   0
    //       mov  r1.1   0
    //       cmp  f0.0   r1.1  0
    //       mov  r1.1   f0.0        // save the exec mask to r1.1
    //       add  r1.0   IP   64     // save the return IP to r1.0
    //
    // This piece of code must be inserted before add instructions
    // created in createInstsForCallTargetOffset and the jmpi:
    //      add  r1.2  -IP   call_target
    //      add  r1.2  r1.2  32
    //      jmpi r1.2
    //
    // so that the return IP in r1.0 will be correct. r1.0 is the
    // IP of the instruction right after jmpi

    // mov  f0.0   0
    insts.push_back(m_builder->createInternalInst(
        nullptr, G4_mov, nullptr, false, 1,
        m_builder->createDstRegRegion(Direct, m_phyRegPool->getF0Reg(), 0, 0, 1, Type_UD),
        m_builder->createImm(0, Type_UD), nullptr, InstOpt_WriteEnable));

    // calculate the reserved register's num from fcall's dst register (shoud be r1)
    assert(fcall->getDst()->isGreg());
    uint32_t reg_num = fcall->getDst()->getLinearizedStart() / GENX_GRF_REG_SIZ;
    G4_Declare* r1_1_decl =
        m_builder->createHardwiredDeclare(1, fcall->getDst()->getType(), reg_num, 1);

    // mov  r1.1   0
    insts.push_back(m_builder->createInternalInst(
        nullptr, G4_mov, nullptr, false, 1,
        m_builder->Create_Dst_Opnd_From_Dcl(r1_1_decl, 1),
        m_builder->createImm(0, Type_UD),
        nullptr, InstOpt_WriteEnable));

    // cmp  f0.0   r1.1  0
    insts.push_back(m_builder->createInternalInst(
        nullptr, G4_cmp, nullptr, false, m_kernel->getSimdSize(),
        m_builder->createDstRegRegion(Direct, m_phyRegPool->getF0Reg(), 0, 0, 1, Type_UD),
        m_builder->Create_Src_Opnd_From_Dcl(r1_1_decl, m_builder->getRegionScalar()),
        m_builder->createImm(0, Type_UD), InstOpt_NoOpt));

    // mov  r1.1   f0.0
    insts.push_back(m_builder->createInternalInst(
        nullptr, G4_mov, nullptr, false, 1,
        m_builder->Create_Dst_Opnd_From_Dcl(r1_1_decl, 1),
        m_builder->createSrcRegRegion(
            Mod_src_undef, Direct, m_phyRegPool->getF0Reg(), 0, 0,
            m_builder->getRegionScalar(), Type_UD),
        nullptr, InstOpt_WriteEnable));

    // add  r1.0   IP   64
    G4_Declare* r1_0_decl =
        m_builder->createHardwiredDeclare(1, fcall->getDst()->getType(), reg_num, 0);
    insts.push_back(m_builder->createInternalInst(
        nullptr, G4_add, nullptr, false, 1,
        m_builder->Create_Dst_Opnd_From_Dcl(r1_0_decl, 1),
        m_builder->createSrcRegRegion(
            Mod_src_undef, Direct, m_phyRegPool->getIpReg(), 0, 0,
            m_builder->getRegionScalar(), Type_UD),
        m_builder->createImm(64, Type_UD),
        InstOpt_WriteEnable | InstOpt_NoCompact));
}

void VISAKernelImpl::expandIndirectCallWithRegTarget()
{
    // check every fcall
    for (BB_LIST_ITER it = m_kernel->fg.BBs.begin();
        it != m_kernel->fg.BBs.end();
        it++)
    {
        G4_BB* bb = (*it);
        // At this point G4_pseudo_fcall may be converted to G4_call,
        // check all call
        if (bb->back()->isFCall() || bb->back()->isCall())
        {
            G4_INST* fcall = bb->back();
            if (fcall->getSrc(0)->isGreg()) {
                // at this point the call function src0 has the target_address
                // and the call dst is the reserved register for ret, we can use
                // the subregister after 2 as add's dst
                // r1.0-r1.7 is reserved in GlobalRA::setABIForStackCallFunctionCalls
                //
                // expand call
                // From:
                //       call r1.0 call_target
                // To:
                //       add  r1.2  -IP   call_target
                //       add  r1.2  r1.2  32
                //       call r1.0  r1.2

                // For SKL workaround, expand call
                // From:
                //       call r1.0 call_target
                // To:
                //       mov  f0.0   0
                //       mov  r1.1   0
                //       cmp  f0.0   r1.1  0
                //       mov  r1.1   f0.0
                //       add  r1.0   IP   64
                //       add  r1.2   -IP    call_target
                //       add  r1.2   r1.2   32
                //       jmpi r1.2

                InstListType expanded_insts;

                // create instructions to store return ip and exec mask, for SKL WA
                if (getGenxPlatform() == GENX_SKL) {
                    createInstsForRetIP(expanded_insts, fcall);
                }

                // create instructions to calculate jump target offset
                G4_Declare* jmp_target_decl = createInstsForCallTargetOffset(expanded_insts, fcall);

                // update jump target (call's src0)
                G4_SrcRegRegion* jump_target = m_builder->Create_Src_Opnd_From_Dcl(
                    jmp_target_decl, m_builder->getRegionScalar());
                fcall->setSrc(jump_target, 0);
                fcall->setNoCompacted();

                if (getGenxPlatform() == GENX_SKL) {
                    // create jmpi
                    G4_INST* jmpi = m_builder->createInternalInst(
                        nullptr, G4_jmpi, nullptr, false, 1, nullptr, fcall->getSrc(0),
                        nullptr, InstOpt_WriteEnable | InstOpt_NoCompact);
                    // jmpi's src must be signed int
                    jmpi->getSrc(0)->asSrcRegRegion()->setType(Type_D);

                    // remove call and insert jmpi to instlist
                    bb->getInstList().erase(--bb->end());
                    bb->getInstList().push_back(jmpi);
                }

                // then insert the expaneded instructions right before the call
                INST_LIST_ITER insert_point = bb->end();
                --insert_point;
                for (auto inst_to_add : expanded_insts) {
                    bb->getInstList().insert(insert_point, inst_to_add);
                    inst_to_add->setCISAOff(fcall->getCISAOff());
                }
            }
        }
    }
}

void* VISAKernelImpl::compilePostOptimize(unsigned int& binarySize)
{
    void* binary = NULL;

    if (getOptions()->getOption(vISA_AddKernelID))
    {
        // gt debugger requires a dummy mov as first
        // executable instruction in compiled kernel.
        // No other instruction must be prepended
        // to the kernel before UUID mov.
        uint64_t kernelID = m_kernel->fg.insertDummyUUIDMov();
        m_kernel->setKernelID(kernelID);
    }

    if (m_kernel->hasIndirectCall())
    {
        // If the indirect call has regiser src0, the register must be a
        // ip-based address of the call target. Insert a add before call to
        // calculate the relative offset from call to the target
        expandIndirectCallWithRegTarget();
    }

    // remove SW fences at this point
    // ToDo: remove all intrinsics?
    for (auto bb : m_kernel->fg.BBs)
    {
        bb->removeIntrinsics(Intrinsic::MemFence);
    }


    m_kernel->evalAddrExp();

    if (getOptions()->getOption(vISA_setStartBreakPoint))
    {
        auto getFirstNonLabelInst = [this]()
        {
            for (auto bb : m_kernel->fg.BBs)
            {
                for (auto inst : *bb)
                {
                    if (inst->isLabel())
                    {
                        continue;
                    }
                    return inst;
                }
            }
            return (G4_INST*) nullptr;
        };

        G4_INST* inst = getFirstNonLabelInst();
        if (inst != nullptr)
        {
            inst->setOptionOn(InstOpt_BreakPoint);
        }
    }

    //
    // Entry point to LIR conversion & transformations
    //

    startTimer(TIMER_ENCODE_AND_EMIT);
    if (m_options->getOption(vISA_IGAEncoder)
        )
    {

        // ToDo: add support for debug info/FastComposite
        BinaryEncodingIGA pBinaryEncoding(*m_kernelMem, *m_kernel, std::string(m_asmName));
        pBinaryEncoding.DoAll();
        binary = pBinaryEncoding.EmitBinary(binarySize);

        if (isFCCallableKernel() || isFCCallerKernel())
        {
            computeFCInfo();

            // After retuning from replaceFCOpcodes, kernel
            // will have all pseudo_fccall and pseudo_fcret
            // opcodes replaced with the usual call
            // and ret opcodes.
            replaceFCOpcodes(*m_builder);
        }
    }
    else
    {
        BinaryEncodingBase* pBinaryEncoding = NULL;

        if (getGenxPlatform() >= GENX_CNL && m_options->getOption(vISA_BXMLEncoder))
        {
            pBinaryEncoding = new BinaryEncodingCNL(*m_kernelMem, *m_kernel, std::string(m_asmName));
        }
        else
        {
            pBinaryEncoding = new BinaryEncoding(*m_kernelMem, *m_kernel, std::string(m_asmName));
        }

        pBinaryEncoding->DoAll();

        if (isFCCallableKernel() || isFCCallerKernel())
        {
            computeFCInfo(pBinaryEncoding);

            // After retuning from replaceFCOpcodes, kernel
            // will have all pseudo_fccall and pseudo_fcret
            // opcodes replaced with the usual call
            // and ret opcodes.
            replaceFCOpcodes(*m_builder);
        }


        /*
            In DLL mode we copy content in to memory buffer
            when vISA_GenerateBinary is specified we dump out .dat file
            */

        binary = pBinaryEncoding->EmitBinary(binarySize);

        pBinaryEncoding->computeBinaryOffsets();

        for (auto bb : m_kernel->fg.BBs)
        {
            for (auto inst : *bb)
            {
                if (inst->getBinInst())
                    inst->setGenOffset(inst->getBinInst()->GetGenOffset());
                else
                    inst->setGenOffset(UNDEFINED_GEN_OFFSET);
            }
        }

        delete pBinaryEncoding;
    }

    // perform any necessary relocation
    m_kernel->doRelocation(binary, binarySize);



    if (m_options->getOption(vISA_PrintASMCount))
    {
        RELEASE_MSG("\tKernel " << m_asmName << " : " << m_kernel->getAsmCount() << " asm_count" << std::endl);
    }
    stopTimer(TIMER_ENCODE_AND_EMIT);

#if defined( _DEBUG ) && ( defined( _WIN32 ) || defined( _WIN64 ) )
    if(m_options->getOption(vISA_DebugConsoleDump)){
        std::basic_ostringstream<char> debugBuff;
        m_kernel->emit_asm(debugBuff, false, nullptr, binarySize);
        debugBuff.flush();
        OutputDebugStringA(debugBuff.str().c_str());
    }
#endif

    if (m_options->getOption(vISA_outputToFile))
    {
        std::ofstream krnlOutput;

        char asmFileName[MAX_OPTION_STR_LENGTH];
        SNPRINTF( asmFileName, MAX_OPTION_STR_LENGTH, "%s.asm", m_asmName.c_str() );
        krnlOutput.open( asmFileName );
        if (!krnlOutput)
        {
            cerr << "Fail to open " << asmFileName << std::endl;
        }

        m_kernel->emit_asm(krnlOutput, false, binary, binarySize);
        krnlOutput.close();
    }


    if( m_builder->getJitInfo() != NULL )
    {
        m_builder->getJitInfo()->numAsmCount = m_kernel->getAsmCount();
    }


    return binary;
}

int VISAKernelImpl::InitializeFastPath()
{

    m_kernelMem = new vISA::Mem_Manager(4096);
    m_globalMem = new vISA::Mem_Manager(4096);

    void *frpPnt = m_mem.alloc(sizeof(PhyRegPool));

    m_kernel = new (m_mem) G4_Kernel(m_instListNodeAllocator, *m_kernelMem, m_options, m_major_version, m_minor_version);
    m_kernel->setName(m_name.c_str());
    m_phyRegPool = new (frpPnt) PhyRegPool(*m_globalMem, m_kernel->getNumRegTotal());

    if (getOptions()->getOption(vISA_GenerateDebugInfo))
    {
        m_kernel->getKernelDebugInfo()->setVISAKernel(this);
    }

    if (getOptions()->getOption(vISA_DumpCompilerStats))
    {
        m_compilerStats.Enable(false);
    }
    m_jitInfo = (FINALIZER_INFO*)m_mem.alloc(sizeof(FINALIZER_INFO));

    int value = 32;
    if (!getIntKernelAttributeValue("FESPSize", value))
    {
        value = 32;
    }

    void* addr = m_kernelMem->alloc(sizeof(class IR_Builder));
    m_builder = new(addr)IR_Builder(m_instListNodeAllocator,
        *m_phyRegPool,
        *m_kernel,
        *m_kernelMem,
        m_options,
        (value == 64),
        m_jitInfo,
        m_pWaTable
        );

    m_builder->setIsKernel(m_isKernel);
    m_builder->setCUnitId(m_kernelID);
    m_builder->num_general_dcl = this->m_num_pred_vars;
    m_builder->getcompilerStats().Link(m_compilerStats);
    initCompilerStats();
    /*
    I don't think this is necessary. Through loader metadata will be maintained on it's side
    through regular vISA builder pass the links will be created explicitly
    m_builder.setVarRelocTable(&commonISAHeader.kernels[kernelId].variable_reloc_symtab);
    m_builder.setFuncRelocTable(&commonISAHeader.kernels[kernelId].function_reloc_symtab);
    */
    return CM_SUCCESS;
}

int VISAKernelImpl::InitializeKernel(const char *kernel_name)
{

    int status = CM_SUCCESS;
    m_num_pred_vars = Get_CISA_PreDefined_Var_Count();
    setName(kernel_name);
    if( IS_GEN_BOTH_PATH && m_isKernel)
    {
        //only doing it for kernel, since function will need Physical register pool created by the kernel
        //so will need to be passed in when kernel is compiled.
        status = InitializeFastPath();
    }
    if(IS_VISA_BOTH_PATH)
    {
        m_branch_targets = new_string_pool();
    }

#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    startTimer(TIMER_VISA_BUILDER_CREATE_VAR);
#endif
    CISABuildPreDefinedDecls();

#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_CREATE_VAR);
#endif

    if(m_isKernel)
    {
        m_kernelID++;
    }

    return status;
}

// This is done for all vISA Compiler Statistics. This is done so that a statistic is
// initialized to false/0 even if the corresponding optimization did not execute.
// This enables the the statistic to be printed out even If the optimization did not happen.
void VISAKernelImpl::initCompilerStats()
{
#if COMPILER_STATS_ENABLE
    m_compilerStats.Init("PreRASchedulerForPressure", CompilerStats::type_bool);
    m_compilerStats.Init("PreRASchedulerForLatency", CompilerStats::type_bool);
    m_compilerStats.Init("IsRAsuccessful", CompilerStats::type_bool);
    m_compilerStats.Init("IsTrivialRA", CompilerStats::type_bool);
    m_compilerStats.Init("IsLocalRA", CompilerStats::type_bool);
    m_compilerStats.Init("IsHybridRA", CompilerStats::type_bool);
    m_compilerStats.Init("IsGlobalRA", CompilerStats::type_bool);
#endif // COMPILER_STATS_ENABLE
}

int VISAKernelImpl::CISABuildPreDefinedDecls()
{
    for( unsigned int i = 0; i < m_num_pred_vars; i++ )
    {

        auto predefId = mapExternalToInternalPreDefVar(i);
        CISA_GEN_VAR* decl = (CISA_GEN_VAR *)m_mem.alloc(sizeof(CISA_GEN_VAR));
        decl->type = GENERAL_VAR;
        decl->index = m_var_info_count++;
        decl->genVar.name_index =-1;
        decl->genVar.attribute_count = 0;
        decl->genVar.attributes = NULL;
        decl->genVar.alias_index = 0;
        decl->genVar.alias_offset = 0;

        if (predefId != PreDefinedVarsInternal::VAR_LAST)
        {
            /*
            Going to create a G4 declaration here, and at compile time set the
            register allocation since this is when number of inputs will be known.
            */
            if (IS_GEN_BOTH_PATH)
            {
                G4_Declare *dcl = m_builder->preDefVars.getPreDefinedVar(predefId);
                decl->genVar.dcl = dcl;
            }
            if (IS_VISA_BOTH_PATH)
            {
                std::string varName(getPredefinedVarString(predefId));
                char* name = (char*)m_mem.alloc(16);
                SNPRINTF(name, 16, "V%u", i);
                decl->genVar.name_index = addStringPool(varName);
                if (m_options->getOption(vISA_isParseMode))
                {
                    setNameIndexMap(std::string(name), decl);
                    setNameIndexMap(varName, decl);
                }
            }
        }
        addVarInfoToList(decl);
    }

    //SLM T0/Global Vars
    for(int i = 0; i < (int) Get_CISA_PreDefined_Surf_Count(); i++)
    {
        //string_pool_lookup_and_insert(name, SURFACE_VAR, ISA_TYPE_ADDR);
        VISA_SurfaceVar* decl = (VISA_SurfaceVar *)m_mem.alloc(sizeof(CISA_GEN_VAR));
        ////memset(decl, 0, sizeof(CISA_GEN_VAR));
        decl->type = SURFACE_VAR;
        decl->index = this->m_surface_count++;
        decl->stateVar.attributes = NULL;
        decl->stateVar.attribute_count = 0;
        decl->stateVar.name_index = -1;
        if(IS_VISA_BOTH_PATH)
        {
			const char* name = vISAPreDefSurf[i].name;
            decl->stateVar.name_index = addStringPool(std::string(name));
            setNameIndexMap(std::string(name), decl);
        }
        if (IS_GEN_BOTH_PATH)
        {
			if (i == PREDEFINED_SURFACE_T252)
			{
				decl->stateVar.dcl = m_builder->getBuiltinT252();
			}
			else
			{
				decl->stateVar.dcl = m_builder->createDeclareNoLookup(
					"",
					G4_GRF,
					1,
					1,
					Type_UD);
			}
        }
        addSurface(decl);
    }

	createBindlessSampler();

    return CM_SUCCESS;
}

void VISAKernelImpl::createBindlessSampler()
{
	m_bindlessSampler = (VISA_SamplerVar *)m_mem.alloc(sizeof(CISA_GEN_VAR));
	m_bindlessSampler->type = SAMPLER_VAR;
	m_bindlessSampler->index = 31;
	m_bindlessSampler->stateVar.attributes = NULL;
	m_bindlessSampler->stateVar.attribute_count = 0;

	if (IS_VISA_BOTH_PATH)
	{
		const char* name = BINDLESS_SAMPLER_NAME;
		m_bindlessSampler->stateVar.name_index = addStringPool(std::string(name));
		setNameIndexMap(std::string(name), m_bindlessSampler);
	}
	if (IS_GEN_BOTH_PATH)
	{
		m_bindlessSampler->stateVar.dcl = m_builder->getBuiltinBindlessSampler();
	}
}

void VISAKernelImpl::setDefaultVariableName(Common_ISA_Var_Class Ty, const char *&varName)
{
    // Do not reassign a name if there is one already.
    if (varName && strlen(varName) > 0)
        return;

#ifndef _DEBUG
    // In a debug build, always set a default name. Otherwise, only set default
    // if emitting visaasm files.
    if (!m_options->getOption(vISA_GenerateISAASM))
        return;
#endif
    char* buf = (char*)m_mem.alloc(256);

    switch (Ty) {
    case Common_ISA_Var_Class::GENERAL_VAR:
        SNPRINTF(buf, 256, "V%d", varNameCount++);
        varName = buf;
        break;
    case Common_ISA_Var_Class::PREDICATE_VAR:
        SNPRINTF(buf, 256, "P%d", predicateNameCount++);
        varName = buf;
        break;
    case Common_ISA_Var_Class::ADDRESS_VAR:
        SNPRINTF(buf, 256, "A%d", addressNameCount++);
        varName = buf;
        break;
    case Common_ISA_Var_Class::SURFACE_VAR:
        SNPRINTF(buf, 256, "T%d", surfaceNameCount++);
        varName = buf;
        break;
    case Common_ISA_Var_Class::SAMPLER_VAR:
        SNPRINTF(buf, 256, "S%d", samplerNameCount++);
        varName = buf;
        break;
    default:
        break;
    }
}

int VISAKernelImpl::CreateVISAGenVar(VISA_GenVar *& decl, const char *varName, int numberElements, VISA_Type dataType,
                                     VISA_Align varAlign, VISA_FileVar *parentDecl, int aliasOffset)
{
    return this->CreateVISAGenVar(decl, varName, numberElements, dataType, varAlign, (VISA_GenVar *)parentDecl, aliasOffset);
}

int VISAKernelImpl::CreateVISAGenVar(VISA_GenVar *& decl, const char *varName, int numberElements, VISA_Type dataType,
                                     VISA_Align varAlign, VISA_GenVar *parentDecl, int aliasOffset)
{
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    startTimer(TIMER_VISA_BUILDER_CREATE_VAR);
#endif
    decl = (VISA_GenVar *)m_mem.alloc(sizeof(VISA_GenVar));
    ////memset(decl, 0, sizeof(VISA_GenVar));
    decl->type = GENERAL_VAR;
    var_info_t *info = &decl->genVar;

    if(m_options->getOption(vISA_isParseMode) && !this->setNameIndexMap(std::string(varName), decl))
    {
        CmAssert( 0 );
        return CM_FAILURE;
    }
    setDefaultVariableName(decl->type, varName);

    info->bit_properties = (uint8_t)dataType;
    info->bit_properties += varAlign << 4;
    info->bit_properties += STORAGE_REG << 7;

    info->num_elements = (uint16_t)numberElements;
    info->alias_offset = 0;
    info->alias_index = 0;
    info->alias_scope_specifier = 0;

    info->alias_scope_specifier = 0;

    if(parentDecl != NULL)
    {
        if(parentDecl->type == FILESCOPE_VAR)
        {
            info->alias_offset = (uint16_t)aliasOffset;
            info->alias_index = parentDecl->index;
            info->alias_scope_specifier = 1;
        }else
        {
            info->alias_offset = (uint16_t)aliasOffset;
            info->alias_index = parentDecl->index;
        }

    }

    info->attribute_count = 0;
    info->attributes = NULL;

    if(IS_GEN_BOTH_PATH)
    {
        G4_Type type = Get_G4_Type_From_Common_ISA_Type(dataType);
        unsigned short dclWidth = 1, dclHeight = 1;
        int totalByteSize = 0;
        getHeightWidth(type, numberElements, dclWidth, dclHeight, totalByteSize);

        info->dcl = m_builder->createDeclareNoLookup(
            createStringCopy(varName, m_mem),
            G4_GRF,
            dclWidth,
            dclHeight,
            type);

        if (parentDecl != NULL)
        {
            var_info_t *aliasDcl = NULL;
            if(parentDecl->type == FILESCOPE_VAR)
            {
                std::map<unsigned int, G4_Declare *>::iterator itFileScope = fileScopeMap.find(parentDecl->index);
                G4_Declare *dcl = NULL;
                if( itFileScope != fileScopeMap.end() )
                {
                    dcl = itFileScope->second;
                }
                else
                {
                    // create a declare for this filescope variable
                    filescope_var_info_t curVar = parentDecl->fileVar;
                    VISA_Type varType = (VISA_Type) (curVar.bit_properties & 0xf);
                    G4_Type typeFS = Get_G4_Type_From_Common_ISA_Type(varType);

                    unsigned short dclWidthFS = 1, dclHeightFS = 1;
                    int totalByteSizeFS = 0;
                    getHeightWidth(typeFS, curVar.num_elements, dclWidthFS, dclHeightFS, totalByteSizeFS);

                    dcl = m_builder->createDeclareNoLookup((const char *)curVar.name, G4_GRF, dclWidthFS, dclHeightFS, typeFS);
                    dcl->setHasFileScope();

                    VISA_Align align_bits= (VISA_Align) ((curVar.bit_properties >> 4) & 0x7);
                    setDeclAlignment(dcl, align_bits);

                    fileScopeMap[parentDecl->index] = dcl;
                }

                info->dcl->setAliasDeclare(dcl, aliasOffset);
            }
            else
            {
                aliasDcl = &parentDecl->genVar;
                info->dcl->setAliasDeclare(aliasDcl->dcl, aliasOffset);

                // check if parent declare is one of the predefined
                if (parentDecl->index < Get_CISA_PreDefined_Var_Count())
                {
                    m_builder->preDefVars.setHasPredefined(mapExternalToInternalPreDefVar(parentDecl->index), true);
                }
            }
        }

        // force subalign to be GRF if total size is larger than or equal to GRF
        if (info->dcl->getSubRegAlign() != SUB_ALIGNMENT_GRFALIGN)
        {
            setDeclAlignment(info->dcl, varAlign);
        }
        info->name_index = -1;
    }
    if (IS_VISA_BOTH_PATH || m_options->getOption(vISA_GenerateDebugInfo))
    {
        info->name_index = addStringPool(std::string(varName));
        addVarInfoToList(decl);
    }

    decl->index = m_var_info_count++;

#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_CREATE_VAR);
#endif
    return CM_SUCCESS;
}

int VISAKernelImpl::CreateVISAAddrVar(VISA_AddrVar *& decl, const char *varName, unsigned int numberElements)
{
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    startTimer(TIMER_VISA_BUILDER_CREATE_VAR);
#endif
    decl = (VISA_AddrVar *)m_mem.alloc(sizeof(VISA_AddrVar));
    ////memset(decl, 0, sizeof(VISA_AddrVar));
    decl->type = ADDRESS_VAR;

    if(m_options->getOption(vISA_isParseMode) && !this->setNameIndexMap(std::string(varName), decl))
    {
        CmAssert( 0 );
        return CM_FAILURE;
    }

    addr_info_t * addr = &decl->addrVar;
    setDefaultVariableName(decl->type, varName);

    decl->index = m_addr_info_count++;
    if(IS_GEN_BOTH_PATH)
    {
        addr->dcl = m_builder->createDeclareNoLookup(
            createStringCopy(varName, m_mem),
            G4_ADDRESS,
            (uint16_t)numberElements,
            1,
            Type_UW );
        addr->name_index = -1;
    }

    addr->num_elements = (uint16_t)numberElements;
    addr->attribute_count = 0;
    addr->attributes = NULL;

    if (IS_VISA_BOTH_PATH || m_options->getOption(vISA_GenerateDebugInfo))
    {
        addr->name_index = this->addStringPool(std::string(varName));
        this->addAddrToList(decl);
    }

#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_CREATE_VAR);
#endif
    return CM_SUCCESS;
}

int VISAKernelImpl::CreateVISAPredVar(VISA_PredVar *& decl, const char* varName, unsigned short numberElements)
{

#define MAX_VISA_PRED_SIZE 32
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    startTimer(TIMER_VISA_BUILDER_CREATE_VAR);
#endif
    decl = (VISA_PredVar *)m_mem.alloc(sizeof(VISA_PredVar));
    ////memset(decl, 0, sizeof(VISA_PredVar));
    decl->type = PREDICATE_VAR;

    MUST_BE_TRUE( numberElements <= MAX_VISA_PRED_SIZE, "number of flags must be <= 32");

    if(m_options->getOption(vISA_isParseMode) && !this->setNameIndexMap(std::string(varName), decl))
    {
        CmAssert( 0 );
        return CM_FAILURE;
    }
    setDefaultVariableName(decl->type, varName);

    pred_info_t * pred = &decl->predVar;

    decl->index = COMMON_ISA_NUM_PREDEFINED_PRED + this->m_pred_info_count++;
    pred->attribute_count = 0;
    if(IS_GEN_BOTH_PATH)
    {
        pred->dcl = m_builder->createFlag(numberElements, createStringCopy(varName, m_mem));
        pred->name_index = -1;
    }
    if(IS_VISA_BOTH_PATH || m_options->getOption(vISA_GenerateDebugInfo))
    {
        pred->name_index = addStringPool(std::string(varName));
        this->addPredToList(decl);
    }
    pred->num_elements = numberElements;
    pred->attribute_count = 0;
    pred->attributes = NULL;

#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_CREATE_VAR);
#endif
    return CM_SUCCESS;
}

int VISAKernelImpl::CreateStateVar(CISA_GEN_VAR *&decl, Common_ISA_Var_Class type, const char* varName, unsigned int numberElements)
{
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    startTimer(TIMER_VISA_BUILDER_CREATE_VAR);
#endif
    decl = (CISA_GEN_VAR *)m_mem.alloc(sizeof(CISA_GEN_VAR));
    ////memset(decl, 0, sizeof(CISA_GEN_VAR));
    decl->type = type;

    if(m_options->getOption(vISA_isParseMode) && !this->setNameIndexMap(std::string(varName), decl))
    {
        CmAssert( 0 );
        return CM_FAILURE;
    }
    setDefaultVariableName(decl->type, varName);

    state_info_t * state = &decl->stateVar;
    state->attribute_count = 0;
    state->attributes = NULL;
    state->num_elements = (uint16_t)numberElements;
    if(IS_GEN_BOTH_PATH)
    {
        state->dcl = m_builder->createDeclareNoLookup(
            createStringCopy(varName, m_mem),
            G4_GRF,
            (uint16_t)numberElements,
            1,
            Type_UD );
        state->name_index = -1;
    }

    switch( type )
    {
    case SAMPLER_VAR:
        decl->index = this->m_sampler_count++;
        break;
    case SURFACE_VAR:
        decl->index = this->m_surface_count++;
        break;
    default:
        CmAssert(0);
        return CM_FAILURE;
    }

    if(IS_VISA_BOTH_PATH || m_options->getOption(vISA_GenerateDebugInfo))
    {
        state->name_index = addStringPool(std::string(varName));
        switch( type )
        {
        case SAMPLER_VAR:
            addSampler(decl);
            break;
        case SURFACE_VAR:
            addSurface(decl);
            break;
        default:
            CmAssert(0);
            return CM_FAILURE;
        }
    }

#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_CREATE_VAR);
#endif
    return CM_SUCCESS;
}

int VISAKernelImpl::CreateVISASamplerVar(VISA_SamplerVar *&decl, const char* name, unsigned int numberElements)
{
    return this->CreateStateVar((CISA_GEN_VAR *&)decl, SAMPLER_VAR, name, numberElements);
}

int VISAKernelImpl::CreateVISASurfaceVar(VISA_SurfaceVar *&decl, const char* name, unsigned int numberElements)
{
    return this->CreateStateVar((CISA_GEN_VAR *&)decl, SURFACE_VAR, name, numberElements);
}

int VISAKernelImpl::CreateDummyLabelOperand(VISA_LabelOpnd *& opnd, char * name, VISA_Label_Kind kind)
{
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    startTimer(TIMER_VISA_BUILDER_CREATE_OPND);
#endif
    VISA_INST_Desc *inst_desc = NULL;
    ISA_Opcode opcode = ISA_LABEL;
    if( kind == LABEL_SUBROUTINE )
    {
        opcode = ISA_SUBROUTINE;
    }
    inst_desc = &CISA_INST_table[opcode];
    opnd = (VISA_LabelOpnd *)m_mem.alloc(sizeof(VISA_LabelOpnd));
    opnd->_opnd.other_opnd = CISA_INVALID_VAR_ID;
    opnd->opnd_type = CISA_OPND_OTHER;
    opnd->size = (uint16_t)Get_Common_ISA_Type_Size((VISA_Type)inst_desc->opnd_desc[0].data_type);
    opnd->tag = opcode;

    m_forward_label_pool[this->m_forward_label_count] = std::string(name);
    opnd->index = this->m_forward_label_count++;
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_CREATE_OPND);
#endif
    return CM_SUCCESS;
}

int VISAKernelImpl::CreateVISALabelVar(VISA_LabelOpnd *& opnd, const char* name, VISA_Label_Kind kind)
{
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    startTimer(TIMER_VISA_BUILDER_CREATE_VAR);
#endif
    opnd = (VISA_LabelOpnd *)m_mem.alloc(sizeof(VISA_LabelOpnd));

    if(IS_GEN_BOTH_PATH)
    {
        //needs to be persistent since label opnd can be used multiple times
        if (m_isKernel == false)
        {
            std::string fname = "L_f" + std::to_string(m_functionId) + "_" + name;
            opnd->g4opnd = m_builder->createLabel(fname, kind);
        }
        else
        {
            std::string kname(name);
            opnd->g4opnd = m_builder->createLabel(kname, kind);
        }
        if(kind == LABEL_SUBROUTINE)
        {
            ((G4_Label*)opnd->g4opnd)->setFuncLabel(true);
		}
		else
        {
            ((G4_Label*)opnd->g4opnd)->setFuncLabel(false);

            if(kind == LABEL_FC)
            {
                // Need to do this here because label kind
                // from VISA is not propagated to G4 IR
                // directly.
                ((G4_Label*)opnd->g4opnd)->setFCLabel(true);
            }
        }
    }
    if(IS_VISA_BOTH_PATH)
    {
        label_info_t *lbl = (label_info_t *)m_mem.alloc(sizeof(label_info_t));
        lbl->name_index = addStringPool(std::string(name));
        lbl->label = NULL;
        lbl->kind = kind; //for now
        m_label_info_list.push_back(lbl);

        opnd->_opnd.other_opnd = m_label_count++;

        VISA_INST_Desc *inst_desc = NULL;

        if( kind == LABEL_BLOCK )
        {
            if(!this->setLabelNameIndexMap(std::string(name), opnd))
            {
                CmAssert( 0 );
                return CM_FAILURE;
            }else
            {
                inst_desc = &CISA_INST_table[ISA_LABEL];
                opnd->tag = ISA_LABEL;
            }
        }else
        {
            if (this->getLabelOperandFromFunctionName(name) == NULL)
            {
                this->m_funcName_to_labelID_map[std::string(name)] = opnd;
                inst_desc = &CISA_INST_table[ISA_SUBROUTINE];
                opnd->tag = ISA_SUBROUTINE;
            }else
            {
                CmAssert( 0 );
                return CM_FAILURE;
            }
        }

        opnd->opnd_type = CISA_OPND_OTHER;
        opnd->size = (uint16_t)Get_Common_ISA_Type_Size((VISA_Type)inst_desc->opnd_desc[0].data_type);
        //opnd->tag = inst_desc->opnd_desc[0].opnd_type;
        lbl->attribute_count = 0;
        lbl->attributes = NULL;

        m_label_info_size += Get_Size_Label_Info(lbl);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_CREATE_VAR);
#endif
    return CM_SUCCESS;
}

int VISAKernelImpl::AddKernelAttribute(const char* attrName, int size, const void *valueBuffer)
{

    attribute_info_t* attr = (attribute_info_t*)m_mem.alloc(sizeof(attribute_info_t));

    /*
    if set through NG path it stores wrong name .isa file
    so in CMRT in simulation mode it fails to look up the name
    */
    if( strcmp( attrName, "AsmName" ) == 0 )
    {
        if (m_options->getOption(VISA_AsmFileNameUser))
        {
            const char *asmName = nullptr;
            m_options->getOption(VISA_AsmFileName, asmName);
            if (asmName != nullptr)
            {
                m_asmName = std::string(asmName);
            }
            else
            {
                m_asmName = std::string("");
            }
        }
        else
        {
            std::string str((char *)valueBuffer);
            if (m_options->getOption(vISA_dumpToCurrentDir))
            {
                auto found = str.find_last_of(DIR_SEPARATOR);
                if (found != string::npos)
                {
                    str = str.substr(found + 1);
                }
            }
            m_asmName = sanitizeString(str);

            size_t found = m_asmName.find(".asm");
            if (found != std::string::npos)
            {
                m_asmName.erase(found, m_asmName.length());
            }
            m_options->setOptionInternally(VISA_AsmFileName, m_asmName.c_str());
        }
    }

    attr->size  = (uint8_t)size;
    attr->isInt = size != 0 && (!strcmp(attrName, "SLMSize") ||
        !strcmp(attrName, "SurfaceUsage") ||
        !strcmp(attrName, "StackSize") ||
        !strcmp(attrName, "Scope") ||
        !strcmp(attrName, "Target") ||
        !strcmp(attrName, "ArgSize") ||
        !strcmp(attrName, "RetValSize") ||
        !strcmp(attrName, "FESPSize") ||
        !strcmp(attrName, "perThreadInputSize"));

    if (attr->isInt)
    {
        switch (attr->size)
        {
        case 1: attr->value.intVal = *((int8_t *) valueBuffer); break;
        case 2: attr->value.intVal = *((int16_t*) valueBuffer); break;
        case 4: attr->value.intVal = *((int32_t*) valueBuffer); break;
        default:
            ASSERT_USER(false, "Unsupported attribute size");
            break;
        }
    }
    else
    {
        if (size > 0)
        {
            attr->value.stringVal = (char*)m_mem.alloc(size + 1);
            memcpy_s(attr->value.stringVal, size + 1, valueBuffer, size + 1);
        }
        else
        {
            attr->value.stringVal = (char*) "";
        }
    }

    if (strcmp(attrName, "Target" ) == 0)
    {
        if (attr->value.intVal == 0)
        {
            m_options->setTarget(VISA_CM);
        }
        else if(attr->value.intVal == 1)
        {
            m_options->setTarget(VISA_3D);
        }
        else if(attr->value.intVal == 2)
        {
            m_options->setTarget(VISA_CS);
        }
        else
        {
            ASSERT_USER( false, "Invalid kernel target attribute." );
        }
        mTargetAttributeSet = true;
    }

    if(strcmp(attrName, "Callable") == 0)
    {
        setFCCallableKernel(true);
    }
    else if(strcmp(attrName, "Caller") == 0)
    {
        setFCCallerKernel(true);
    }
    else if(strcmp(attrName, "Composable") == 0)
    {
        setFCComposableKernel(true);
        if (IS_GEN_BOTH_PATH)
        {
            m_builder->getFCPatchInfo()->setFCComposableKernel(true);
        }
        m_options->setOption(vISA_loadThreadPayload, false);
    }
    else if (strcmp(attrName, "Entry") == 0)
    {
        m_builder->getFCPatchInfo()->setIsEntryKernel(true);
        m_options->setOption(vISA_loadThreadPayload, true);
    }
    else if (strcmp(attrName, "RetValSize") == 0)
    {
        if (IS_GEN_BOTH_PATH)
        {
            if (m_builder->getRetVarSize() < attr->value.intVal)
            {
                m_builder->setRetVarSize((unsigned short)(attr->value.intVal));
            }
        }
    }
    else if (strcmp(attrName, "ArgSize") == 0)
    {
        if (IS_GEN_BOTH_PATH)
        {
            if (m_builder->getArgSize() < attr->value.intVal)
            {
                m_builder->setArgSize((unsigned short)(attr->value.intVal));
            }
        }
    }
    else if (strcmp(attrName, "perThreadInputSize") == 0)
    {
        if (IS_GEN_BOTH_PATH)
        {
            m_builder->setPerThreadInputSize(attr->value.intVal);
        }
    }

    addAttribute(attrName, attr);
    return CM_SUCCESS;
}

int VISAKernelImpl::AddAttributeToVarGeneric(CISA_GEN_VAR *decl, const char* varName, unsigned int size, void *val)
{
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    startTimer(TIMER_VISA_BUILDER_CREATE_VAR);
#endif
    attribute_info_t *attr = (attribute_info_t *) m_mem.alloc(sizeof(attribute_info_t));
    //memset(attr,0,sizeof(attribute_info_t));

    attr->isInt = false;
    attr->nameIndex = addStringPool(std::string(varName));

    void * temp = m_mem.alloc(size);
    memcpy_s(temp, size, val,size);
    attr->value.stringVal = (char *)temp;
    attr->size = (uint8_t)size;

    switch(decl->type)
    {
    case GENERAL_VAR:
        {
            decl->genVar.attribute_count++;
            decl->genVar.attributes = attr;
            //calculated during emission
            //this->m_var_info_size += Get_Size_Attribute_Info(attr);
            if(IS_GEN_BOTH_PATH)
            {
                if (strcmp(varName, "Input") == 0 ||
                    strcmp(varName, "Input_Output") == 0)
                {
                    decl->genVar.dcl->setLiveIn();

                }
                if (strcmp(varName, "Output") == 0 ||
                    strcmp(varName, "Input_Output") == 0)
                {
                    decl->genVar.dcl->setLiveOut();
                }
                if (strcmp(varName, "NoWidening") == 0)
                {
                    decl->genVar.dcl->setDoNotWiden();
                }
            }
            break;
        }
    case ADDRESS_VAR:
        {
            decl->addrVar.attribute_count++;
            decl->addrVar.attributes = attr;
            this->m_adress_info_size += Get_Size_Attribute_Info(attr);
            break;
        }
    case PREDICATE_VAR:
        {
            decl->predVar.attribute_count++;
            decl->predVar.attributes = attr;
            this->m_predicate_info_size += Get_Size_Attribute_Info(attr);
            break;
        }
    case SAMPLER_VAR:
        {
            decl->stateVar.attribute_count++;
            decl->stateVar.attributes = attr;
            this->m_sampler_info_size += Get_Size_Attribute_Info(attr);
            break;
        }
    case SURFACE_VAR:
        {
            if ( !strcmp(varName,"") )
            {
                decl->stateVar.attribute_count++;
                decl->stateVar.attributes = attr;
                //calculated during emission
                //this->m_surface_info_size += Get_Size_Attribute_Info(attr);
            }
            break;
        }
    case LABEL_VAR:
        {
            decl->labelVar.attribute_count++;
            decl->labelVar.attributes = attr;
            this->m_label_info_size += Get_Size_Attribute_Info(attr);
            break;
        }
    case FILESCOPE_VAR:
        {
            decl->fileVar.attribute_count++;
            decl->fileVar.attributes = attr;
            break;
        }
    default:
        CmAssert(0);
        return CM_FAILURE;
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_CREATE_VAR);
#endif
    return CM_SUCCESS;
}

int VISAKernelImpl::AddAttributeToVar(VISA_PredVar *decl, const char* name, unsigned int size, void *val)
{
    return AddAttributeToVarGeneric((CISA_GEN_VAR *)decl, name, size, val);
}

int VISAKernelImpl::AddAttributeToVar(VISA_SurfaceVar *decl, const char* name, unsigned int size, void *val)
{
    return AddAttributeToVarGeneric((CISA_GEN_VAR *)decl, name, size, val);
}

int VISAKernelImpl::AddAttributeToVar(VISA_GenVar *decl, const char* name, unsigned int size, void *val)
{
    return AddAttributeToVarGeneric((CISA_GEN_VAR *)decl, name, size, val);
}

int VISAKernelImpl::AddAttributeToVar(VISA_AddrVar *decl, const char* name, unsigned int size, void *val)
{
    return AddAttributeToVarGeneric((CISA_GEN_VAR *)decl, name, size, val);
}

void VISAKernelImpl::addVarInfoToList(CISA_GEN_VAR * t)
{
    m_var_info_list.push_back(t);
}

void VISAKernelImpl::addSampler(CISA_GEN_VAR * state)
{
    m_sampler_info_list.push_back(state);
    this->m_sampler_info_size += Get_Size_State_Info(&state->stateVar);
}

void VISAKernelImpl::addVme(CISA_GEN_VAR * state)
{
    m_vme_info_list.push_back(state);
    this->m_vme_info_size += Get_Size_State_Info(&state->stateVar);
}

void VISAKernelImpl::addSurface(CISA_GEN_VAR * state)
{
    m_surface_info_list.push_back(state);
}

void VISAKernelImpl::addAddrToList(CISA_GEN_VAR * addr)
{
    m_addr_info_list.push_back(addr);
    this->m_adress_info_size += Get_Size_Addr_Info(&addr->addrVar);
}

void VISAKernelImpl::addPredToList(CISA_GEN_VAR * pred )
{
    m_pred_info_list.push_back(pred);
    this->m_predicate_info_size += Get_Size_Pred_Info(&pred->predVar);
}

void VISAKernelImpl::addAttribute(const char *inputName, attribute_info_t *attrTemp)
{
    attrTemp->nameIndex = addStringPool(std::string(inputName));
    m_attribute_info_list.push_back(attrTemp);
    m_attribute_count++;
    this->m_attribute_info_size += Get_Size_Attribute_Info(attrTemp);
}

Common_ISA_Input_Class VISAKernelImpl::GetInputClass(Common_ISA_Var_Class var_class)
{
    if (var_class == GENERAL_VAR)
        return INPUT_GENERAL;

    if (var_class == SAMPLER_VAR)
        return INPUT_SAMPLER;

    if (var_class == SURFACE_VAR)
        return INPUT_SURFACE;

    return INPUT_UNKNOWN;
}

int VISAKernelImpl::CreateVISAInputVar(CISA_GEN_VAR *decl,
                                        uint16_t offset,
                                        uint16_t size,
                                        uint8_t implicitKind)
{
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    startTimer(TIMER_VISA_BUIDLER_CREATE_VAR);
#endif

    unsigned int status = CM_SUCCESS;
    input_info_t * input = (input_info_t *)m_mem.alloc(sizeof(input_info_t));
    input->kind = GetInputClass(decl->type);
    input->kind |= implicitKind << 3;
    input->setImplicitKind(implicitKind);
    input->index = decl->index;
    input->offset = offset;
    input->size = size;

    if(IS_GEN_BOTH_PATH)
    {
        G4_Declare *dcl = NULL;
        switch(decl->type)
        {
        case GENERAL_VAR:
            {
                dcl = decl->genVar.dcl;
                break;
            }
        case SAMPLER_VAR:
        case SURFACE_VAR:
            {
                dcl = decl->stateVar.dcl;
                break;
            }
        default:
            {
                status = CM_FAILURE;
                break;
            }
        }

        if (status == CM_SUCCESS)
        {
            // decide the physical register number and sub register number
            unsigned int regNum = offset / GENX_GRF_REG_SIZ;
            unsigned int subRegNum = ( offset % GENX_GRF_REG_SIZ ) / dcl->getElemSize();
            dcl->getRegVar()->setPhyReg(m_phyRegPool->getGreg(regNum), subRegNum);
            dcl->setRegFile( G4_INPUT );
            unsigned int reservedGRFNum = m_options->getuInt32Option(vISA_ReservedGRFNum);
            if (regNum + dcl->getNumRows() > m_builder->getOptions()->getuInt32Option(vISA_TotalGRFNum) - reservedGRFNum) {
                MUST_BE_TRUE(false, "INPUT payload execeeds the regsiter number");
            }
        }
        input->dcl = dcl;
        //used in asm generation
        m_builder->addInputArg(input);
    }
    if (IS_VISA_BOTH_PATH)
    {

        if((input->kind & 0x3) == INPUT_UNKNOWN) {
            fprintf(stderr, "Wrong input variable is used");
            status = CM_FAILURE;
        }else
        {
            m_input_info_list.push_back(input);
            m_input_count++;
            this->m_input_info_size += Get_Size_Input_Info(input);
        }
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUIDLER_CREATE_VAR);
#endif
    return status;
}

int VISAKernelImpl::CreateVISAImplicitInputVar(VISA_GenVar *decl, unsigned short offset, unsigned short size, unsigned short kind)
{
    return this->CreateVISAInputVar((CISA_GEN_VAR *)decl, offset, size, (uint8_t)kind);
}

int VISAKernelImpl::CreateVISAInputVar(VISA_GenVar *decl, unsigned short offset, unsigned short size)
{
    return this->CreateVISAInputVar((CISA_GEN_VAR *)decl, offset, size, INPUT_EXPLICIT);
}

int VISAKernelImpl::CreateVISAInputVar(VISA_SamplerVar *decl, unsigned short offset, unsigned short size)
{
    return this->CreateVISAInputVar((CISA_GEN_VAR *)decl, offset, size, INPUT_EXPLICIT);
}

int VISAKernelImpl::CreateVISAInputVar(VISA_SurfaceVar *decl, unsigned short offset, unsigned short size)
{
    return this->CreateVISAInputVar((CISA_GEN_VAR *)decl, offset, size, INPUT_EXPLICIT);
}

int VISAKernelImpl::CreateVISAInputVar(VISA_VMEVar *decl, unsigned short offset, unsigned short size)
{
    return this->CreateVISAInputVar((CISA_GEN_VAR *)decl, offset, size, INPUT_EXPLICIT);
}

/************* OPERANDS CREATION START ******************/
int VISAKernelImpl::CreateVISAAddressSrcOperand(VISA_VectorOpnd *&opnd, VISA_AddrVar *decl, unsigned int offset, unsigned int width)
{
    return CreateVISAAddressOperand(opnd, decl, offset, width, false);
}

int VISAKernelImpl::CreateVISAAddressDstOperand(VISA_VectorOpnd *&opnd, VISA_AddrVar *decl, unsigned int offset)
{
    return CreateVISAAddressOperand(opnd, decl, offset, 1, true);
}
int VISAKernelImpl::CreateVISAAddressOperand(VISA_VectorOpnd *&cisa_opnd, VISA_AddrVar *decl, unsigned int offset, unsigned int width, bool isDst)
{
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    startTimer(TIMER_VISA_BUILDER_CREATE_OPND);
#endif

    cisa_opnd = (VISA_VectorOpnd *)getOpndFromPool();
    if(IS_GEN_BOTH_PATH)
    {
        G4_Declare *dcl = decl->addrVar.dcl;

        if(!isDst)
        {
            // FIXME: This does not adhere to the vISA spec, which allows <0;N,1> regions where
            // N is < exec size
            RegionDesc* rd = width > 1 ? m_builder->getRegionStride1() : m_builder->getRegionScalar();
            cisa_opnd->g4opnd = m_builder->createSrcRegRegion(
                Mod_src_undef,
                Direct,
                dcl->getRegVar(),
                0,
                (uint16_t)offset,
                rd,
                dcl->getElemType());
        }
        else
        {
            cisa_opnd->g4opnd = m_builder->createDstRegRegion(
                Direct,
                dcl->getRegVar(),
                0, //opnd->opnd_val.addr_opnd.index, // should we use 0 here?
                (uint16_t)offset,
                1,
                dcl->getElemType());
        }
    }
    if(IS_VISA_BOTH_PATH)
    {
        cisa_opnd->opnd_type = CISA_OPND_VECTOR;
        cisa_opnd->tag = OPERAND_ADDRESS;
        cisa_opnd->_opnd.v_opnd.tag = OPERAND_ADDRESS;
        cisa_opnd->_opnd.v_opnd.opnd_val.addr_opnd.index= (uint16_t)decl->index;
        cisa_opnd->_opnd.v_opnd.opnd_val.addr_opnd.offset= (uint8_t)offset;
        cisa_opnd->_opnd.v_opnd.opnd_val.addr_opnd.width= Get_Common_ISA_Exec_Size_From_Raw_Size(width & 0x1F);
        cisa_opnd->size = (uint16_t)Get_Size_Vector_Operand(&cisa_opnd->_opnd.v_opnd);

    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_CREATE_OPND);
#endif
    return CM_SUCCESS;
}

int VISAKernelImpl::CreateVISAAddressOfOperandGeneric(VISA_VectorOpnd *&cisa_opnd, CISA_GEN_VAR *decl, unsigned int offset)
{
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    startTimer(TIMER_VISA_BUILDER_CREATE_OPND);
#endif
    int status = CM_SUCCESS;
    cisa_opnd = (VISA_VectorOpnd*)getOpndFromPool();

    if(IS_GEN_BOTH_PATH)
    {
        G4_Declare *src0Dcl = NULL;
        switch(decl->type)
        {
        case GENERAL_VAR:
            {
                src0Dcl = decl->genVar.dcl;
                break;
            }
        case SAMPLER_VAR:
        case SURFACE_VAR:
            {
                src0Dcl = decl->stateVar.dcl;
                break;
            }
        default:
            CmAssert(0);
            return CM_FAILURE;
        }

        // set up to the top level dcl to be addressed
        src0Dcl->setAddressed();
        m_kernel->setHasAddrTaken(true);
        G4_Declare *parentDcl = src0Dcl->getAliasDeclare();
        while( parentDcl ){
            parentDcl->setAddressed();
            parentDcl = parentDcl->getAliasDeclare();
        }
        cisa_opnd->g4opnd = m_builder->createAddrExp(
            src0Dcl->getRegVar(),
            offset,
            Type_UW );
    }
    if(IS_VISA_BOTH_PATH)
    {
        //memset(cisa_opnd,0,sizeof(VISA_opnd));
        switch(decl->type)
        {
            case GENERAL_VAR:
            {
                cisa_opnd->tag = OPERAND_GENERAL;
                cisa_opnd->_opnd.v_opnd.tag = OPERAND_GENERAL;
                cisa_opnd->_opnd.v_opnd.opnd_val.gen_opnd.index = decl->index;
                cisa_opnd->_opnd.v_opnd.opnd_val.gen_opnd.row_offset = offset / G4_GRF_REG_NBYTES;
                VISA_Type type = decl->genVar.getType();
                unsigned int typeSize = G4_Type_Table[Get_G4_Type_From_Common_ISA_Type(type)].byteSize;
                CmAssert((offset % typeSize) == 0);
                cisa_opnd->_opnd.v_opnd.opnd_val.gen_opnd.col_offset = (offset % G4_GRF_REG_NBYTES)/typeSize;


                cisa_opnd->_opnd.v_opnd.opnd_val.gen_opnd.region = (unsigned short)Get_CISA_Region_Val(0);
                cisa_opnd->_opnd.v_opnd.opnd_val.gen_opnd.region |= ((unsigned short)Get_CISA_Region_Val(1)) << 4;
                cisa_opnd->_opnd.v_opnd.opnd_val.gen_opnd.region |= ((unsigned short)Get_CISA_Region_Val(0)) << 8;
                break;
            }
            case SAMPLER_VAR:
            case SURFACE_VAR:
            {
                cisa_opnd->tag = OPERAND_STATE;
                cisa_opnd->_opnd.v_opnd.tag = OPERAND_STATE;
                cisa_opnd->_opnd.v_opnd.opnd_val.state_opnd.index = (uint16_t)decl->index;
                cisa_opnd->_opnd.v_opnd.opnd_val.state_opnd.offset = (uint8_t)offset;
                cisa_opnd->_opnd.v_opnd.opnd_val.state_opnd.opnd_class = decl->type;
                if ( decl->type == SAMPLER_VAR )
                {
                    cisa_opnd->_opnd.v_opnd.opnd_val.state_opnd.opnd_class = STATE_OPND_SAMPLER;
                }
                else if ( decl->type == SURFACE_VAR )
                {
                    cisa_opnd->_opnd.v_opnd.opnd_val.state_opnd.opnd_class = STATE_OPND_SURFACE;
                }
                else
                {
                    cisa_opnd->_opnd.v_opnd.opnd_val.state_opnd.opnd_class = STATE_OPND_VME;
                }
                break;
            }
            default:
                MUST_BE_TRUE(false, "ERROR: unexpected variable class");
                break;
        }

        cisa_opnd->opnd_type = CISA_OPND_VECTOR;
        cisa_opnd->index = decl->index;
        cisa_opnd->size = (uint16_t)Get_Size_Vector_Operand(&cisa_opnd->_opnd.v_opnd);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_CREATE_OPND);
#endif
    return status;
}

int VISAKernelImpl::CreateVISAAddressOfOperand(VISA_VectorOpnd *&cisa_opnd, VISA_GenVar *decl, unsigned int offset)
{
    return this->CreateVISAAddressOfOperandGeneric(cisa_opnd, (CISA_GEN_VAR *)decl, offset);
}
int VISAKernelImpl::CreateVISAAddressOfOperand(VISA_VectorOpnd *&cisa_opnd, VISA_SurfaceVar *decl, unsigned int offset)
{
    return this->CreateVISAAddressOfOperandGeneric(cisa_opnd, (CISA_GEN_VAR *)decl, offset);
}

int VISAKernelImpl::CreateVISAIndirectGeneralOperand(VISA_VectorOpnd *& cisa_opnd, VISA_AddrVar *cisa_decl, VISA_Modifier mod, unsigned int addrOffset, unsigned short immediateOffset,
                                                     unsigned short verticalStride, unsigned short width, unsigned short horizontalStride, VISA_Type type, bool isDst)
{
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    startTimer(TIMER_VISA_BUILDER_CREATE_OPND);
#endif
    cisa_opnd = (VISA_VectorOpnd*)getOpndFromPool();

    if(IS_GEN_BOTH_PATH)
    {
        G4_Declare *dcl = cisa_decl->addrVar.dcl;
        if(!isDst)
        {
            if(verticalStride == MAX_UWORD_VALUE)
                verticalStride = UNDEFINED_SHORT;

            RegionDesc *rd = m_builder->createRegionDesc( verticalStride, width, horizontalStride );
            G4_SrcModifier g4_mod = Get_G4_SrcMod_From_Common_ISA_Mod(mod);
            G4_SrcRegRegion* src = m_builder->createIndirectSrc(
                g4_mod,
                dcl->getRegVar(),
                0,
                (uint16_t)addrOffset,
                rd,
                Get_G4_Type_From_Common_ISA_Type(type),
                immediateOffset);
            cisa_opnd->g4opnd = src;
        }
        else
        {
            G4_DstRegRegion* dst = m_builder->createDstRegRegion(
                IndirGRF,
                dcl->getRegVar(),
                0, //opnd->opnd_val.addr_opnd.index, // should we use 0 here?
                (uint16_t)addrOffset,
                horizontalStride,
                Get_G4_Type_From_Common_ISA_Type(type));
            dst->setImmAddrOff( immediateOffset );
            cisa_opnd->g4opnd = dst;
        }
    }
    if(IS_VISA_BOTH_PATH)
    {
        //memset(cisa_opnd,0,sizeof(VISA_opnd));

        cisa_opnd->opnd_type = CISA_OPND_VECTOR;
        cisa_opnd->tag = OPERAND_INDIRECT;
        cisa_opnd->_opnd.v_opnd.tag = OPERAND_INDIRECT;
        cisa_opnd->_opnd.v_opnd.opnd_val.indirect_opnd.index = (uint16_t)cisa_decl->index;
        cisa_opnd->_opnd.v_opnd.opnd_val.indirect_opnd.addr_offset = (uint8_t)addrOffset;
        cisa_opnd->_opnd.v_opnd.opnd_val.indirect_opnd.indirect_offset = immediateOffset;
        cisa_opnd->_opnd.v_opnd.opnd_val.indirect_opnd.bit_property = type;

        if( !isDst )
        {
            cisa_opnd->_opnd.v_opnd.opnd_val.indirect_opnd.region = Create_CISA_Region(verticalStride,width,horizontalStride);//Get_CISA_Region_Val(horizontal_stride) <<8;

            cisa_opnd->_opnd.v_opnd.tag += mod<<3;
        }else
        {
            cisa_opnd->_opnd.v_opnd.opnd_val.indirect_opnd.region = Get_CISA_Region_Val(horizontalStride) <<8;
        }

        cisa_opnd->size = (uint16_t)Get_Size_Vector_Operand(&cisa_opnd->_opnd.v_opnd);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_CREATE_OPND);
#endif
    return CM_SUCCESS;
}

int VISAKernelImpl::CreateVISAIndirectSrcOperand(VISA_VectorOpnd *& cisa_opnd, VISA_AddrVar *cisa_decl, VISA_Modifier mod, unsigned int addrOffset, short immediateOffset,
                                                 unsigned short verticalStride, unsigned short width, unsigned short horizontalStride, VISA_Type type)
{
    return this->CreateVISAIndirectGeneralOperand(cisa_opnd, cisa_decl, mod, addrOffset, immediateOffset, verticalStride, width, horizontalStride, type, false);
}

int VISAKernelImpl::CreateVISAIndirectDstOperand(VISA_VectorOpnd *& cisa_opnd, VISA_AddrVar *decl, unsigned int addrOffset, short immediateOffset,
                                                 unsigned short horizontalStride, VISA_Type type)
{
    return this->CreateVISAIndirectGeneralOperand(cisa_opnd, decl, MODIFIER_NONE, addrOffset, immediateOffset, -1, -1, horizontalStride, type, true);
}

int VISAKernelImpl::CreateVISAIndirectOperandVxH(VISA_VectorOpnd *& cisa_opnd, VISA_AddrVar *decl, unsigned int addrOffset, short immediateOffset, VISA_Type type)
{
    return this->CreateVISAIndirectGeneralOperand(cisa_opnd, decl, MODIFIER_NONE, addrOffset, immediateOffset, -1, 1, 0, type, false);
}

int VISAKernelImpl::CreateVISAPredicateSrcOperand(VISA_VectorOpnd *& opnd, VISA_PredVar *decl, unsigned int size)
{
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    startTimer(TIMER_VISA_BUILDER_CREATE_OPND);
#endif
    int status = CM_SUCCESS;

    opnd = (VISA_VectorOpnd *)getOpndFromPool();

    if(IS_GEN_BOTH_PATH)
    {
        G4_Declare *dcl = decl->predVar.dcl;
        //ASSERT_USER( (size <= dcl->getNumElems()), " Execsize is larger than predicate variable size." );
        RegionDesc *rd;

        G4_Type type = Type_UW;
            rd = m_builder->getRegionScalar();

        if(size == 32)
            type = Type_UD;

        opnd->g4opnd = m_builder->createSrcRegRegion(
            Mod_src_undef,
            Direct,
            dcl->getRegVar(),
            0,
            0,
            rd,
            type );
    }
    if(IS_VISA_BOTH_PATH)
    {
        status = CreateVISAPredicateOperandvISA((VISA_PredOpnd *&)opnd, decl, PredState_NO_INVERSE, PRED_CTRL_NON);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_CREATE_OPND);
#endif
    return status;
}

int VISAKernelImpl::CreateVISAPredicateDstOperand(VISA_VectorOpnd *& opnd, VISA_PredVar *decl, uint32_t size)
{
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    startTimer(TIMER_VISA_BUILDER_CREATE_OPND);
#endif
    int status = CM_SUCCESS;

    opnd = (VISA_VectorOpnd *)getOpndFromPool();
    if(IS_GEN_BOTH_PATH)
    {
        G4_Declare *dcl = decl->predVar.dcl;

        opnd->g4opnd = m_builder->createDstRegRegion(
            Direct,
            dcl->getRegVar(),
            0,
            0,
            1,
            size == 32 ? Type_UD : Type_UW);
    }
    if(IS_VISA_BOTH_PATH)
    {
        status = CreateVISAPredicateOperandvISA((VISA_PredOpnd *&)opnd, decl, PredState_NO_INVERSE, PRED_CTRL_NON);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_CREATE_OPND);
#endif
    return status;
}

int VISAKernelImpl::CreateVISAPredicateOperandvISA(VISA_PredOpnd *& cisa_opnd, VISA_PredVar *decl, VISA_PREDICATE_STATE state, VISA_PREDICATE_CONTROL cntrl)
{
    int status = CM_SUCCESS;
    cisa_opnd->opnd_type = CISA_OPND_VECTOR;
    cisa_opnd->tag = OPERAND_PREDICATE;
    cisa_opnd->_opnd.v_opnd.tag = OPERAND_PREDICATE;
    cisa_opnd->index = decl->index;
    cisa_opnd->index += cntrl <<13;
    cisa_opnd->index += state << 15;
    cisa_opnd->_opnd.v_opnd.opnd_val.pred_opnd.index = (unsigned short)(cisa_opnd->index);
    cisa_opnd->size = (uint16_t)Get_Size_Vector_Operand(&cisa_opnd->_opnd.v_opnd);
    return status;
}

int VISAKernelImpl::CreateVISAPredicateOperand(VISA_PredOpnd *& cisa_opnd, VISA_PredVar *decl, VISA_PREDICATE_STATE state, VISA_PREDICATE_CONTROL cntrl)
{
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    startTimer(TIMER_VISA_BUILDER_CREATE_OPND);
#endif

    cisa_opnd = (VISA_PredOpnd *)getOpndFromPool();
    if(IS_GEN_BOTH_PATH)
    {
        G4_Declare *dcl = decl->predVar.dcl;
#if START_ASSERT_CHECK
        if(dcl == NULL)
        {
            CmAssert( 0 );
            return CM_FAILURE;
        }
#endif
        //with bool size in bytes was incorrect, now that it's correct it returns "correct"
        //number of elements. Except it thinks each element is a two bytes.
        //we want each element in as a boolean.
        G4_Predicate_Control predCtrl = vISAPredicateToG4Predicate( (VISA_PREDICATE_CONTROL)cntrl, dcl->getNumberFlagElements());

        cisa_opnd->g4opnd = m_builder->createPredicate(
            (state == PredState_INVERSE) ? PredState_Minus : PredState_Plus,
            dcl->getRegVar(),
            0,
            predCtrl );
    }
    if(IS_VISA_BOTH_PATH)
    {
        CreateVISAPredicateOperandvISA(cisa_opnd, decl, state, cntrl);
    }

#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_CREATE_OPND);
#endif
    return CM_SUCCESS;
}

int VISAKernelImpl::CreateVISASrcOperand(VISA_VectorOpnd *& cisa_opnd, VISA_GenVar *cisa_decl, VISA_Modifier mod, unsigned short vStride, unsigned short width, unsigned short hStride,
                                         unsigned char rowOffset, unsigned char colOffset)
{
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    startTimer(TIMER_VISA_BUILDER_CREATE_OPND);
#endif

    cisa_opnd = (VISA_VectorOpnd *)getOpndFromPool();
    if(IS_GEN_BOTH_PATH)
    {
        if( cisa_decl->index < Get_CISA_PreDefined_Var_Count() )
        {
            cisa_opnd->g4opnd = CommonISABuildPreDefinedSrc(cisa_decl->index, vStride, width, hStride, rowOffset, colOffset, mod);
        }
        else
        {

            //create reg region
            G4_Declare *dcl = cisa_decl->genVar.dcl;

            RegionDesc *rd = m_builder->createRegionDesc(vStride, width, hStride);
            G4_SrcModifier g4_mod = Get_G4_SrcMod_From_Common_ISA_Mod(mod);

            cisa_opnd->g4opnd = m_builder->createSrcRegRegion(g4_mod, Direct, dcl->getRegVar(), rowOffset, colOffset, rd, dcl->getElemType());
        }
    }
    if(IS_VISA_BOTH_PATH)
    {
        cisa_opnd->opnd_type = CISA_OPND_VECTOR;
        cisa_opnd->tag = OPERAND_GENERAL; //<--- I think this is redundant at this point.
        cisa_opnd->_opnd.v_opnd.tag = OPERAND_GENERAL;
        cisa_opnd->_opnd.v_opnd.opnd_val.gen_opnd.index = cisa_decl->index;
        cisa_opnd->index = cisa_opnd->_opnd.v_opnd.opnd_val.gen_opnd.index;
        cisa_opnd->_opnd.v_opnd.opnd_val.gen_opnd.row_offset = rowOffset;
        cisa_opnd->_opnd.v_opnd.opnd_val.gen_opnd.col_offset = colOffset;
        cisa_opnd->_opnd.v_opnd.opnd_val.gen_opnd.region = Create_CISA_Region(vStride, width, hStride);

        cisa_opnd->_opnd.v_opnd.tag += mod<<3;

        cisa_opnd->size = (uint16_t)Get_Size_Vector_Operand(&cisa_opnd->_opnd.v_opnd);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_CREATE_OPND);
#endif
    return CM_SUCCESS;
}

int VISAKernelImpl::CreateVISADstOperand(VISA_VectorOpnd *&cisa_opnd, VISA_GenVar *cisa_decl, unsigned short hStride,
                                         unsigned char rowOffset, unsigned char colOffset)
{
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    startTimer(TIMER_VISA_BUILDER_CREATE_OPND);
#endif
    cisa_opnd = (VISA_VectorOpnd *)getOpndFromPool();
    if(IS_GEN_BOTH_PATH)
    {
        //create reg region
        G4_Declare *dcl = cisa_decl->genVar.dcl;

        cisa_opnd->g4opnd = m_builder->createDstRegRegion( Direct, dcl->getRegVar(), rowOffset, colOffset, hStride, dcl->getElemType());
    }

    if(IS_VISA_BOTH_PATH)
    {

        cisa_opnd->opnd_type = CISA_OPND_VECTOR;
        cisa_opnd->tag = OPERAND_GENERAL; //<--- I think this is redundant at this point.
        cisa_opnd->_opnd.v_opnd.tag = OPERAND_GENERAL;
        cisa_opnd->_opnd.v_opnd.opnd_val.gen_opnd.index = cisa_decl->index;
        cisa_opnd->index = cisa_opnd->_opnd.v_opnd.opnd_val.gen_opnd.index;
        cisa_opnd->_opnd.v_opnd.opnd_val.gen_opnd.row_offset = rowOffset;
        cisa_opnd->_opnd.v_opnd.opnd_val.gen_opnd.col_offset = colOffset;
        cisa_opnd->_opnd.v_opnd.opnd_val.gen_opnd.region = Get_CISA_Region_Val(hStride) <<8;

        cisa_opnd->size = (uint16_t)Get_Size_Vector_Operand(&cisa_opnd->_opnd.v_opnd);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_CREATE_OPND);
#endif
    return CM_SUCCESS;
}

int VISAKernelImpl::CreateRelocVISAImmediate(VISA_VectorOpnd *&cisa_opnd, const void *value, VISA_Type isaType, SuperRelocEntry& reloc)
{
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    startTimer(TIMER_VISA_BUILDER_CREATE_OPND);
#endif
    cisa_opnd = (VISA_VectorOpnd *)getOpndFromPool();
    if (IS_GEN_BOTH_PATH)
    {
        if (isaType == ISA_TYPE_Q || isaType == ISA_TYPE_UQ) {
            cisa_opnd->g4opnd = m_builder->createRelocImm(reloc, Type_UQ);
        }
        else if (isaType == ISA_TYPE_D || isaType == ISA_TYPE_UD)
        {
            cisa_opnd->g4opnd = m_builder->createRelocImm(reloc, Type_UD);
        }
        else
        {
            MUST_BE_TRUE(false, "Unable to create relocatable immediate operand with type.");
        }
    }
    if (IS_VISA_BOTH_PATH)
    {
        //memset(cisa_opnd, 0, sizeof(VISA_opnd));

        cisa_opnd->opnd_type = CISA_OPND_VECTOR;
        cisa_opnd->tag = OPERAND_IMMEDIATE;
        cisa_opnd->_opnd.v_opnd.tag = OPERAND_IMMEDIATE;
        cisa_opnd->_opnd.v_opnd.opnd_val.const_opnd.type = isaType;

        int size = CISATypeTable[isaType].typeSize;

        if (size == 0)
        {
            CmAssert(0);
            return CM_FAILURE;
        }
        if (isaType == ISA_TYPE_Q || isaType == ISA_TYPE_UQ)
        {
            cisa_opnd->_opnd.v_opnd.opnd_val.const_opnd._val.lval = *((uint64_t*)value);
        }
        else
        {
            int64_t tmpValue = typecastVals(value, isaType);
            cisa_opnd->_opnd.v_opnd.opnd_val.const_opnd._val.lval = tmpValue;
        }
        cisa_opnd->size = (uint16_t)Get_Size_Vector_Operand(&cisa_opnd->_opnd.v_opnd);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_CREATE_OPND);
#endif
    return CM_SUCCESS;
}

int VISAKernelImpl::CreateVISAImmediate(VISA_VectorOpnd *&cisa_opnd, const void *value, VISA_Type isaType)
{
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    startTimer(TIMER_VISA_BUILDER_CREATE_OPND);
#endif
    cisa_opnd = (VISA_VectorOpnd *)getOpndFromPool();
    if(IS_GEN_BOTH_PATH)
    {
        G4_Type g4type = Get_G4_Type_From_Common_ISA_Type(isaType);

        if( isaType == ISA_TYPE_Q ) {
            cisa_opnd->g4opnd = m_builder->createImmWithLowerType(*(int64_t *)value, Type_Q);
        }
        else if( isaType == ISA_TYPE_UQ) {
            cisa_opnd->g4opnd = m_builder->createImmWithLowerType(*(int64_t *)value, Type_UQ);
        }
        else if( isaType == ISA_TYPE_DF )
        {
            cisa_opnd->g4opnd = m_builder->createDFImm(*(double*)value);
        }
        else if( isaType == ISA_TYPE_F )
        {
            cisa_opnd->g4opnd = m_builder->createImm(*(float*)(value));
        }
        else if( isaType == ISA_TYPE_HF )
        {
            cisa_opnd->g4opnd = m_builder->createImmWithLowerType(*(unsigned*)(value), Type_HF);
        }
        else
        {
            int64_t tmpValue = typecastVals(value, isaType);
            cisa_opnd->g4opnd = m_builder->createImmWithLowerType(
                tmpValue, g4type );
        }
    }
    if(IS_VISA_BOTH_PATH)
    {
        //memset(cisa_opnd, 0, sizeof(VISA_opnd));

        cisa_opnd->opnd_type = CISA_OPND_VECTOR;
        cisa_opnd->tag = OPERAND_IMMEDIATE;
        cisa_opnd->_opnd.v_opnd.tag = OPERAND_IMMEDIATE;
        cisa_opnd->_opnd.v_opnd.opnd_val.const_opnd.type = isaType;

        int size = CISATypeTable[isaType].typeSize;

        if( size == 0 )
        {
            CmAssert( 0 );
            return CM_FAILURE;
        }
        if(isaType == ISA_TYPE_DF)
        {
            cisa_opnd->_opnd.v_opnd.opnd_val.const_opnd._val.dval = *((double*)value);
        }
        else if(isaType == ISA_TYPE_F)
        {
            cisa_opnd->_opnd.v_opnd.opnd_val.const_opnd._val.fval = *((float*)value);
        }
        else if(isaType == ISA_TYPE_Q || isaType == ISA_TYPE_UQ || isaType == ISA_TYPE_HF)
        {
            cisa_opnd->_opnd.v_opnd.opnd_val.const_opnd._val.lval = *((uint64_t*)value);
        }
        else if( isaType == ISA_TYPE_V || isaType == ISA_TYPE_UV )
        {
            int size = Get_Common_ISA_Type_Size(isaType);
            memcpy_s(&cisa_opnd->_opnd.v_opnd.opnd_val.const_opnd._val, size, value, size);
        }
        else
        {
            int64_t tmpValue = typecastVals(value, isaType);
            cisa_opnd->_opnd.v_opnd.opnd_val.const_opnd._val.lval = tmpValue;
        }
        cisa_opnd->size = (uint16_t)Get_Size_Vector_Operand(&cisa_opnd->_opnd.v_opnd);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_CREATE_OPND);
#endif
    return CM_SUCCESS;
}

int VISAKernelImpl::CreateVISAStateOperand(VISA_VectorOpnd *&cisa_opnd, CISA_GEN_VAR *decl, Common_ISA_State_Opnd_Class opndClass, uint8_t size, unsigned char offset, bool useAsDst)
{
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    startTimer(TIMER_VISA_BUILDER_CREATE_OPND);
#endif

    cisa_opnd = (VISA_VectorOpnd *)getOpndFromPool();
    if(IS_GEN_BOTH_PATH)
    {
        G4_Declare *dcl = decl->stateVar.dcl;

        if(!useAsDst)
        {
            // pre-defined surface
            if( opndClass == STATE_OPND_SURFACE &&
                decl->index < Get_CISA_PreDefined_Surf_Count() )
            {
                int64_t immVal = Get_PreDefined_Surf_Index(decl->index);
				if (immVal == PREDEF_SURF_252)
				{
					// we have to keep it as a variable
					cisa_opnd->g4opnd = m_builder->Create_Src_Opnd_From_Dcl(m_builder->getBuiltinT252(), m_builder->getRegionScalar());
				}
				else
				{
					if (m_options->getOption(vISA_noncoherentStateless) && immVal == PREDEF_SURF_255)
					{
						immVal = PREDEF_SURF_253;
					}
					cisa_opnd->g4opnd = m_builder->createImm(immVal, Type_UD);
				}
            }
            else
            {

                cisa_opnd->g4opnd = m_builder->createSrcRegRegion(
                    Mod_src_undef,
                    Direct,
                    dcl->getRegVar(),
                    0,
                    offset,
                    size == 1 ? m_builder->getRegionScalar() : m_builder->getRegionStride1(),
                    dcl->getElemType());
            }
        }
        else
        {
            cisa_opnd->g4opnd = m_builder->createDstRegRegion(
                Direct,
                dcl->getRegVar(),
                0,
                offset,
                1,
                dcl->getElemType());
        }
    }
    if(IS_VISA_BOTH_PATH)
    {

        cisa_opnd->opnd_type = CISA_OPND_VECTOR;
        cisa_opnd->tag = OPERAND_STATE;
        cisa_opnd->_opnd.v_opnd.tag = OPERAND_STATE;

        cisa_opnd->index = decl->index;
        cisa_opnd->_opnd.v_opnd.opnd_val.state_opnd.index = (unsigned short)(cisa_opnd->index);
        cisa_opnd->_opnd.v_opnd.opnd_val.state_opnd.offset = offset;
        cisa_opnd->_opnd.v_opnd.opnd_val.state_opnd.opnd_class = opndClass;
        cisa_opnd->size = (uint16_t)Get_Size_Vector_Operand(&cisa_opnd->_opnd.v_opnd);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_CREATE_OPND);
#endif
    return CM_SUCCESS;
}

int VISAKernelImpl::CreateVISAStateOperand(VISA_VectorOpnd *&opnd, VISA_SurfaceVar *decl, uint8_t size, unsigned char offset, bool useAsDst)
{
    return this->CreateVISAStateOperand(opnd, (CISA_GEN_VAR*)decl, STATE_OPND_SURFACE, size, offset, useAsDst);
}

int VISAKernelImpl::CreateVISAStateOperand(VISA_VectorOpnd *&opnd, VISA_SurfaceVar *decl, unsigned char offset, bool useAsDst)
{
    return this->CreateVISAStateOperand(opnd, (CISA_GEN_VAR*)decl, STATE_OPND_SURFACE, 1, offset, useAsDst);
}

int VISAKernelImpl::CreateVISAStateOperand(VISA_VectorOpnd *&opnd, VISA_SamplerVar *decl, unsigned char offset, bool useAsDst)
{
    return this->CreateVISAStateOperand(opnd, (CISA_GEN_VAR*)decl, STATE_OPND_SAMPLER, 1, offset, useAsDst);
}

int VISAKernelImpl::CreateVISAStateOperand(VISA_VectorOpnd *&opnd, VISA_SamplerVar *decl, uint8_t size, unsigned char offset, bool useAsDst)
{
    return this->CreateVISAStateOperand(opnd, (CISA_GEN_VAR*)decl, STATE_OPND_SAMPLER, size, offset, useAsDst);
}

int VISAKernelImpl::CreateVISAStateOperand(VISA_VectorOpnd *&opnd, VISA_VMEVar *decl, unsigned char offset, bool useAsDst)
{
    return this->CreateVISAStateOperand(opnd, (CISA_GEN_VAR*)decl, STATE_OPND_VME, 1, offset, useAsDst);
}

//size should be 8 since it's a vISA spec.
//size was added because VME doesn't adhere to our spec.
int VISAKernelImpl::CreateVISARawOperand(VISA_RawOpnd *& cisa_opnd, VISA_GenVar *decl, unsigned short offset)
{

#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    startTimer(TIMER_VISA_BUILDER_CREATE_OPND);
#endif
    cisa_opnd = (VISA_RawOpnd *)getOpndFromPool();
    cisa_opnd->opnd_type = CISA_OPND_RAW;
    cisa_opnd->tag = NUM_OPERAND_CLASS;
    cisa_opnd->index = decl->index;
    cisa_opnd->_opnd.r_opnd.index = cisa_opnd->index;
    cisa_opnd->_opnd.r_opnd.offset = offset;
    cisa_opnd->size = sizeof(cisa_opnd->_opnd.r_opnd.index) + sizeof(cisa_opnd->_opnd.r_opnd.offset);
    cisa_opnd->decl = decl;
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_CREATE_OPND);
#endif
    return CM_SUCCESS;
}

// size == 1 means we want scalar region
// FIXME: this is really a bug, rawOpnd should always occupy at least 1 GRF.
// We should fix the vISA spec for this
//  [noTypeChange: keep the original type. This likely needs refactoring]
int VISAKernelImpl::CreateGenRawSrcOperand(VISA_RawOpnd *& cisa_opnd)
{
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    startTimer(TIMER_VISA_BUILDER_CREATE_OPND);
#endif

    if (cisa_opnd->index==0)
    {
        return CreateGenNullRawOperand(cisa_opnd, false);
    }

    unsigned short offset = cisa_opnd->_opnd.r_opnd.offset;

    G4_Declare *dcl = cisa_opnd->decl->genVar.dcl;

    RegionDesc *rd = m_builder->getRegionStride1();
    G4_Type type = dcl->getElemType();
    short row_offset = offset / G4_GRF_REG_NBYTES;
    short col_offset = (offset%G4_GRF_REG_NBYTES) / G4_Type_Table[type].byteSize;

    cisa_opnd->g4opnd = m_builder->createSrcRegRegion(
        Mod_src_undef,
        Direct,
        dcl->getRegVar(),
        row_offset,
        col_offset,
        rd,
        type);

#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_CREATE_OPND);
#endif
    return CM_SUCCESS;
}

int VISAKernelImpl::CreateGenRawDstOperand(VISA_RawOpnd *& cisa_opnd)
{
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    startTimer(TIMER_VISA_BUILDER_CREATE_OPND);
#endif

    if (cisa_opnd->index==0)
    {
        return CreateGenNullRawOperand(cisa_opnd, true);
    }

    unsigned short offset = cisa_opnd->_opnd.r_opnd.offset;

    //if(IS_GEN_BOTH_PATH) //will only be called in GEN or BOTH path
    {
        G4_Declare *dcl = cisa_opnd->decl->genVar.dcl;

        {
            short row_offset = offset/G4_GRF_REG_NBYTES;
            short col_offset = (offset%G4_GRF_REG_NBYTES)/G4_Type_Table[dcl->getElemType()].byteSize;

            cisa_opnd->g4opnd = m_builder->createDstRegRegion(
                Direct,
                dcl->getRegVar(),
                row_offset,
                col_offset,
                1,
                dcl->getElemType());
        }
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_CREATE_OPND);
#endif
    return CM_SUCCESS;
}

int VISAKernelImpl::CreateStateInstUse(VISA_StateOpndHandle *&cisa_opnd, unsigned int index)
{
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    startTimer(TIMER_VISA_BUILDER_CREATE_OPND);
#endif
    cisa_opnd->_opnd.other_opnd = index;
    cisa_opnd->opnd_type = CISA_OPND_OTHER;
    cisa_opnd->size = (uint16_t)Get_Common_ISA_Type_Size(ISA_TYPE_UB);
    cisa_opnd->tag = ISA_TYPE_UB;

#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_CREATE_OPND);
#endif
    return CM_SUCCESS;
}
int VISAKernelImpl::CreateStateInstUseFastPath(VISA_StateOpndHandle *&cisa_opnd, CISA_GEN_VAR *decl)
{
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    startTimer(TIMER_VISA_BUILDER_CREATE_OPND);
#endif
    unsigned int status = CM_SUCCESS;
    G4_Declare *dcl = decl->stateVar.dcl;

    Common_ISA_Var_Class type = decl->type;

    switch( type )
    {
    case SAMPLER_VAR:
    {
        cisa_opnd->g4opnd = m_builder->createSrcRegRegion(Mod_src_undef, Direct, dcl->getRegVar(), 0, 0, m_builder->getRegionScalar(), Type_UD);
        break;
    }
    case SURFACE_VAR:
    {
        uint16_t surf_id = (uint16_t)decl->index;
        if (surf_id >= Get_CISA_PreDefined_Surf_Count())
        {
            cisa_opnd->g4opnd = m_builder->createSrcRegRegion(Mod_src_undef, Direct, dcl->getRegVar(), 0, 0,
                m_builder->getRegionScalar(), Type_UD);
        }
        else // predefined
        {
            if (dcl == m_builder->getBuiltinT252())
            {
                cisa_opnd->g4opnd = m_builder->Create_Src_Opnd_From_Dcl(m_builder->getBuiltinT252(),
                    m_builder->getRegionScalar());
            }
            else
            {
                int64_t immVal = Get_PreDefined_Surf_Index(decl->index);
                if (m_options->getOption(vISA_noncoherentStateless) && immVal == PREDEF_SURF_255)
                {
                    immVal = PREDEF_SURF_253;
                }
                cisa_opnd->g4opnd = m_builder->createImm(immVal, Type_UD);
            }
        }
        break;
    }
    default:
    {
        CmAssert(0);
        status = CM_FAILURE;
        break;
    }
    }


#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_CREATE_OPND);
#endif
    return status;
}
int VISAKernelImpl::CreateVISAStateOperandHandle(VISA_StateOpndHandle *&opnd, VISA_SurfaceVar *decl)
{
    int status = CM_SUCCESS;
    opnd = (VISA_StateOpndHandle *)getOpndFromPool();
    if(IS_GEN_BOTH_PATH )
    {
        status = CreateStateInstUseFastPath(opnd, (CISA_GEN_VAR *)decl);
    }
    if(IS_VISA_BOTH_PATH && status == CM_SUCCESS)
    {
        status = CreateStateInstUse(opnd, decl->index);
    }
    return status;
}

int VISAKernelImpl::CreateVISAStateOperandHandle(VISA_StateOpndHandle *&opnd, VISA_SamplerVar *decl)
{
    int status = CM_SUCCESS;
    opnd = (VISA_StateOpndHandle *)getOpndFromPool();
    if(IS_GEN_BOTH_PATH)
    {
        status =  CreateStateInstUseFastPath(opnd, (CISA_GEN_VAR *)decl);
    }
    if(IS_VISA_BOTH_PATH && status == CM_SUCCESS)
    {
        status =  CreateStateInstUse(opnd, decl->index);
    }
    return status;
}

int VISAKernelImpl::CreateVISAStateOperandHandle(VISA_StateOpndHandle *&opnd, VISA_VMEVar *decl)
{
    int status = CM_SUCCESS;
    opnd = (VISA_StateOpndHandle *)getOpndFromPool();
    if(IS_GEN_BOTH_PATH)
    {
        status = CreateStateInstUseFastPath(opnd, (CISA_GEN_VAR *)decl);
    }
    if(IS_VISA_BOTH_PATH && status == CM_SUCCESS)
    {
        status = CreateStateInstUse(opnd, decl->index);
    }
    return status;
}

int VISAKernelImpl::CreateVISANullRawOperand(VISA_RawOpnd *& cisa_opnd, bool isDst)
{
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    startTimer(TIMER_VISA_BUILDER_CREATE_OPND);
#endif

    cisa_opnd = (VISA_RawOpnd *)getOpndFromPool();
    cisa_opnd->opnd_type = CISA_OPND_RAW;
    cisa_opnd->tag = NUM_OPERAND_CLASS;
    cisa_opnd->index = 0;
    cisa_opnd->_opnd.r_opnd.index = cisa_opnd->index;
    cisa_opnd->_opnd.r_opnd.offset = 0;
    cisa_opnd->size = sizeof(cisa_opnd->_opnd.r_opnd.index) + sizeof(cisa_opnd->_opnd.r_opnd.offset);

    int ret = CreateGenNullRawOperand(cisa_opnd, isDst);

#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_CREATE_OPND);
#endif
    return ret;
}

/**
  * It's expected that the null raw operands had already been pre-allocated.
  */
int VISAKernelImpl::CreateGenNullRawOperand(VISA_RawOpnd *& cisa_opnd, bool isDst)
{
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    startTimer(TIMER_VISA_BUILDER_CREATE_OPND);
#endif
    if(IS_GEN_BOTH_PATH)
    {
        if(isDst)
        {
            cisa_opnd->g4opnd = m_builder->createNullDst(Type_UD);
        }
        else
        {
            cisa_opnd->g4opnd = m_builder->createNullSrc(Type_UD);
        }
    }

#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_CREATE_OPND);
#endif
    return CM_SUCCESS;
}

int VISAKernelImpl::GetPredefinedVar(VISA_GenVar *&predDcl, PreDefined_Vars varName)
{
    int status = CM_SUCCESS;
    predDcl = (VISA_GenVar*)getGenVar(varName);
    return status;
}

int VISAKernelImpl::GetPredefinedSurface(VISA_SurfaceVar *&predDcl, PreDefined_Surface surfaceName)
{
    int status = CM_SUCCESS;
    predDcl = (VISA_SurfaceVar*)(m_surface_info_list[surfaceName]);
    return status;
}

int VISAKernelImpl::GetBindlessSampler(VISA_SamplerVar *&samplerDcl)
{
	int status = CM_SUCCESS;
	samplerDcl = m_bindlessSampler;
	return status;
}
/************* OPERANDS CREATION END   ******************/

/************* START APPEND APIS **********************/
int VISAKernelImpl::AppendVISAArithmeticInst(ISA_Opcode opcode, VISA_PredOpnd *pred, bool satMode, Common_VISA_EMask_Ctrl emask,
                                             Common_ISA_Exec_Size executionSize, VISA_VectorOpnd *tmpDst, VISA_VectorOpnd *src0, VISA_VectorOpnd *src1, VISA_VectorOpnd *src2)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;
    if(IS_GEN_BOTH_PATH)
    {
        G4_Predicate * g4Pred = (pred != NULL)? pred->g4opnd->asPredicate() : NULL;
        if ( ( tmpDst->g4opnd->getType() == Type_DF ) &&
             ( ( opcode == ISA_DIV ) ||  // keeping ISA_DIV at the moment for IGC
               ( opcode == ISA_DIVM ) ) )
        {
            status = m_builder->translateVISAArithmeticDoubleInst(opcode, executionSize, emask, g4Pred,
                satMode, tmpDst->g4opnd->asDstRegRegion(), src0->g4opnd, src1->g4opnd);   // IEEE
        }
        else if ( tmpDst->g4opnd->getType() == Type_DF && opcode == ISA_INV )
        {
            // src0_opnd is divisor
            status = m_builder->translateVISAArithmeticDoubleInst(opcode, executionSize, emask, g4Pred,
                satMode, tmpDst->g4opnd->asDstRegRegion(), NULL, src0->g4opnd); // IEEE
        }
        else if ( tmpDst->g4opnd->getType() == Type_F && opcode == ISA_DIVM )
        {
            status = m_builder->translateVISAArithmeticSingleDivideIEEEInst(opcode, executionSize, emask, g4Pred,
                satMode, NULL, tmpDst->g4opnd->asDstRegRegion(), src0->g4opnd, src1->g4opnd);  // IEEE
        }
        else if ( tmpDst->g4opnd->getType() == Type_F && opcode == ISA_SQRTM )
        {
            status = m_builder->translateVISAArithmeticSingleSQRTIEEEInst(opcode, executionSize, emask, g4Pred,
                satMode, NULL, tmpDst->g4opnd->asDstRegRegion(), src0->g4opnd);  // IEEE
        }
        else if (tmpDst->g4opnd->getType() == Type_DF && (opcode == ISA_SQRT || opcode == ISA_SQRTM))
        {
            status = m_builder->translateVISAArithmeticDoubleSQRTInst(opcode, executionSize, emask, g4Pred,
                satMode, NULL, tmpDst->g4opnd->asDstRegRegion(), src0->g4opnd);
        }
        else
        {
            status =  m_builder->translateVISAArithmeticInst(opcode, executionSize, emask, g4Pred, satMode,
                NULL, tmpDst->g4opnd->asDstRegRegion(), src0->g4opnd, GET_G4_OPNG(src1), GET_G4_OPNG(src2), NULL);
        }
    }
    if(IS_VISA_BOTH_PATH)
    {
        int num_pred_desc_operands = 2; //accounting for exec_size and pred_id in descriptor
        int num_operands = 0;
        VISA_INST_Desc *inst_desc = NULL;
        VISA_opnd *opnd[4];
        VISA_opnd *dst = tmpDst;

        inst_desc = &CISA_INST_table[opcode];
        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, inst_desc );
        VISA_Modifier mod = MODIFIER_NONE;

        if(satMode)
        {
            mod = MODIFIER_SAT;
            dst = (VISA_opnd *)m_mem.alloc(sizeof(VISA_opnd));
            *dst = *tmpDst;
            dst->_opnd.v_opnd.tag += mod<<3;
        }

        ADD_OPND(num_operands, opnd, dst);

        ADD_OPND(num_operands, opnd, src0);

        ADD_OPND(num_operands, opnd, src1);

        ADD_OPND(num_operands, opnd, src2);

        CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        //pred id
        unsigned short pred_id = 0;
        if (pred != NULL)
            pred_id = pred->_opnd.v_opnd.opnd_val.pred_opnd.index;

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        unsigned char size = executionSize;
        size += emask << 4;
        inst->createCisaInstruction(opcode, size, 0 , pred_id,opnd, num_operands, inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISAArithmeticInst(ISA_Opcode opcode, VISA_PredOpnd *pred, bool satMode, Common_VISA_EMask_Ctrl emask,
                                             Common_ISA_Exec_Size executionSize, VISA_VectorOpnd *tmpDst, VISA_VectorOpnd *src0)
{
    return AppendVISAArithmeticInst(opcode, pred, satMode, emask, executionSize, tmpDst, src0, NULL, NULL);
}

int VISAKernelImpl::AppendVISAArithmeticInst(ISA_Opcode opcode, VISA_PredOpnd *pred, bool satMode, Common_VISA_EMask_Ctrl emask,
                                             Common_ISA_Exec_Size executionSize, VISA_VectorOpnd *tmpDst, VISA_VectorOpnd *src0, VISA_VectorOpnd *src1)
{
    return AppendVISAArithmeticInst(opcode, pred, satMode, emask, executionSize, tmpDst, src0, src1, NULL);
}

int VISAKernelImpl::AppendVISAArithmeticInst(ISA_Opcode opcode, VISA_PredOpnd *pred, Common_VISA_EMask_Ctrl emask,
                                             Common_ISA_Exec_Size executionSize, VISA_VectorOpnd *dst1, VISA_VectorOpnd *carry_borrow, VISA_VectorOpnd *src0, VISA_VectorOpnd *src1)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;

    if(IS_GEN_BOTH_PATH)
    {
        G4_Predicate * g4Pred = (pred != NULL)? pred->g4opnd->asPredicate() : NULL;
        status = m_builder->translateVISAArithmeticInst(opcode, executionSize, emask, g4Pred,
            false, NULL, dst1->g4opnd->asDstRegRegion(), src0->g4opnd, src1->g4opnd, NULL,
            carry_borrow->g4opnd->asDstRegRegion());
    }
    if(IS_VISA_BOTH_PATH)
    {
        int num_pred_desc_operands = 2; //accounting for exec_size and pred_id in descriptor
        int num_operands = 0;
        VISA_INST_Desc *inst_desc = NULL;
        VISA_opnd *opnd[4];

        inst_desc = &CISA_INST_table[opcode];
        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, inst_desc );

        if(opcode != ISA_ADDC && opcode != ISA_SUBB)
        {
            CmAssert( 0 );
            std::cerr<<"ONLY ADDC AND SUBB are supported by this API"<<std::endl;
            return CM_FAILURE;
        }

        ADD_OPND(num_operands, opnd, dst1);

        ADD_OPND(num_operands, opnd, carry_borrow);

        ADD_OPND(num_operands, opnd, src0);

        ADD_OPND(num_operands, opnd, src1);

        CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        //pred id
        unsigned short pred_id = 0;
        if (pred != NULL)
            pred_id = pred->_opnd.v_opnd.opnd_val.pred_opnd.index;

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        unsigned char size = executionSize;
        size += emask << 4;
        status = inst->createCisaInstruction(opcode, size, 0 , pred_id,opnd, num_operands, inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISALogicOrShiftInst(ISA_Opcode opcode, Common_VISA_EMask_Ctrl emask,
                                            Common_ISA_Exec_Size executionSize, VISA_PredVar *dst, VISA_PredVar *src0, VISA_PredVar *src1)
{
    VISA_VectorOpnd *dstOpnd = NULL;
    VISA_VectorOpnd *src0Opnd = NULL;
    VISA_VectorOpnd *src1Opnd = NULL;
    uint32_t exSize = Get_Common_ISA_Exec_Size(executionSize);
    CreateVISAPredicateDstOperand(dstOpnd, dst, exSize);
    CreateVISAPredicateSrcOperand(src0Opnd, src0, exSize);
    if(src1 != NULL)
        CreateVISAPredicateSrcOperand(src1Opnd, src1, exSize);

    return AppendVISALogicOrShiftInst(opcode, NULL, false, emask, executionSize, dstOpnd, src0Opnd, src1Opnd, NULL, NULL);
}

int VISAKernelImpl::AppendVISALogicOrShiftInst(ISA_Opcode opcode, VISA_PredOpnd *pred, bool satMode, Common_VISA_EMask_Ctrl emask,
                                               Common_ISA_Exec_Size executionSize, VISA_VectorOpnd *tmpDst, VISA_VectorOpnd *src0, VISA_VectorOpnd *src1, VISA_VectorOpnd *src2, VISA_VectorOpnd *src3)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif

    int status = CM_SUCCESS;

    if(IS_GEN_BOTH_PATH)
    {
        G4_Predicate * g4Pred = (pred != NULL)? pred->g4opnd->asPredicate() : NULL;
        status = m_builder->translateVISALogicInst(opcode, g4Pred,
            satMode, executionSize, emask, tmpDst->g4opnd->asDstRegRegion(), src0->g4opnd, GET_G4_OPNG(src1), GET_G4_OPNG(src2), GET_G4_OPNG(src3));
    }
    if(IS_VISA_BOTH_PATH)
    {
        int num_pred_desc_operands = 2; //accounting for exec_size and pred_id in descriptor
        int num_operands = 0;
        VISA_INST_Desc *inst_desc = NULL;
        VISA_opnd *opnd[5];
        inst_desc = &CISA_INST_table[opcode];
        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, inst_desc );
        VISA_Modifier mod = MODIFIER_NONE;

        VISA_opnd *dst = tmpDst;
        if(satMode)
        {
            if(tmpDst == NULL)
            {
                CM_ERROR_PRINT("Destination for Arithmetic Instruction is NULL");\
                    CmAssert( 0 );
                return CM_FAILURE;
            }
            mod = MODIFIER_SAT;
            dst = (VISA_opnd *)m_mem.alloc(sizeof(VISA_opnd));
            *dst = *tmpDst;
            dst->_opnd.v_opnd.tag += mod<<3;
        }

        ADD_OPND(num_operands, opnd, dst);

        ADD_OPND(num_operands, opnd, src0);

        ADD_OPND(num_operands, opnd, src1);

        ADD_OPND(num_operands, opnd, src2);

        ADD_OPND(num_operands, opnd, src3);

        CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        //pred id
        unsigned short pred_id = 0;
        if (pred != NULL)
            pred_id = pred->_opnd.v_opnd.opnd_val.pred_opnd.index;

        unsigned char size = executionSize;
        size += emask << 4;
        inst->createCisaInstruction(opcode, size, 0 , pred_id ,opnd, num_operands, inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISAAddrAddInst(Common_VISA_EMask_Ctrl emask, Common_ISA_Exec_Size executionSize, VISA_VectorOpnd *dst, VISA_VectorOpnd *src0, VISA_VectorOpnd *src1)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;
    if(IS_GEN_BOTH_PATH)
    {
        status = m_builder->translateVISAAddrInst(ISA_ADDR_ADD, executionSize, emask, dst->g4opnd->asDstRegRegion(), src0->g4opnd, src1->g4opnd);
    }
    if(IS_VISA_BOTH_PATH)
    {
        int num_pred_desc_operands = 0; //accounting for exec_size and pred_id in descriptor
        int num_operands = 0;
        VISA_INST_Desc *inst_desc = NULL;
        VISA_opnd *opnd[4];
        ISA_Opcode opcode = ISA_ADDR_ADD;
        inst_desc = &CISA_INST_table[opcode];
        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, inst_desc );

        ADD_OPND(num_operands, opnd, dst);

        ADD_OPND(num_operands, opnd, src0);

        ADD_OPND(num_operands, opnd, src1);

#if START_ASSERT_CHECK
        if((inst_desc->opnd_num -num_pred_desc_operands) != num_operands)
        {
            CmAssert( 0 );
            CM_ERROR_PRINT("Number of parameters does not match");
            std::cerr<<"LINE: "<<__LINE__<<std::endl;
            std::cerr<<"FUNCTION: "<<__FUNCTION__<<std::endl;
            return CM_FAILURE;
        }
#endif

        CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        unsigned char size = executionSize;
        size += emask << 4;
        status =inst->createCisaInstruction(opcode, size, 0 , 0,opnd, num_operands, inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISAMinMaxInst(CISA_MIN_MAX_SUB_OPCODE subOpcode, bool satMode, Common_VISA_EMask_Ctrl emask,
                                         Common_ISA_Exec_Size executionSize, VISA_VectorOpnd *tmpDst, VISA_VectorOpnd *src0, VISA_VectorOpnd *src1)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;

    if(IS_GEN_BOTH_PATH)
    {
        status = m_builder->translateVISADataMovementInst(ISA_FMINMAX, subOpcode, NULL, executionSize, emask, satMode, tmpDst->g4opnd->asDstRegRegion(), src0->g4opnd, src1->g4opnd);
    }
    if(IS_VISA_BOTH_PATH)
    {
        int num_operands = 0;
        VISA_INST_Desc *inst_desc = NULL;
        VISA_opnd *opnd[4];
        ISA_Opcode opcode = ISA_FMINMAX;
        inst_desc = &CISA_INST_table[opcode];
        int num_pred_desc_operands = 0;
        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, inst_desc ); //accounting for exec_size and pred_id in descriptor
        VISA_Modifier mod = MODIFIER_NONE;

        VISA_opnd *dst = tmpDst;
        if(satMode)
        {
            if(tmpDst == NULL)
            {
                CM_ERROR_PRINT("Destination for Arithmetic Instruction is NULL");
                CmAssert( 0 );
                return CM_FAILURE;
            }
            mod = MODIFIER_SAT;
            dst = (VISA_opnd *)m_mem.alloc(sizeof(VISA_opnd));
            *dst = *tmpDst;
            dst->_opnd.v_opnd.tag += mod<<3;
        }

        ADD_OPND(num_operands, opnd, CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, subOpcode));

        ADD_OPND(num_operands, opnd, dst);

        ADD_OPND(num_operands, opnd, src0);

        ADD_OPND(num_operands, opnd, src1);

        CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        //pred id
        unsigned short pred_id = 0;
        unsigned char size = executionSize;
        size += emask << 4;
        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);
        inst->createCisaInstruction(opcode, size, 0 , pred_id,opnd, num_operands, inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISAPredicateMove( VISA_VectorOpnd *dst, VISA_PredVar *src0)
{
    VISA_VectorOpnd *src0Opnd = NULL;
    CreateVISAPredicateSrcOperand(src0Opnd, src0, 1);
    return AppendVISADataMovementInst(ISA_MOV, NULL, false, vISA_EMASK_M1_NM, EXEC_SIZE_1, dst, src0Opnd, NULL);
}

int VISAKernelImpl::AppendVISASetP(Common_VISA_EMask_Ctrl emask, Common_ISA_Exec_Size executionSize, VISA_PredVar *dst, VISA_VectorOpnd *src0)
{
    uint32_t exSize = Get_Common_ISA_Exec_Size(executionSize);
    VISA_VectorOpnd *dstOpnd = NULL;
    CreateVISAPredicateDstOperand(dstOpnd, dst, exSize);
    return AppendVISADataMovementInst(ISA_SETP, NULL, false, emask, executionSize, dstOpnd, src0);
}

int VISAKernelImpl::AppendVISADataMovementInst(ISA_Opcode opcode, VISA_PredOpnd *pred, bool satMode, Common_VISA_EMask_Ctrl emask,
                                               Common_ISA_Exec_Size executionSize, VISA_VectorOpnd *tmpDst, VISA_VectorOpnd *src0)
{
    return this->AppendVISADataMovementInst(opcode, pred, satMode, emask, executionSize, tmpDst, src0, NULL);
}
int VISAKernelImpl::AppendVISADataMovementInst(ISA_Opcode opcode, VISA_PredOpnd *pred, bool satMode, Common_VISA_EMask_Ctrl emask,
                                               Common_ISA_Exec_Size executionSize, VISA_VectorOpnd *tmpDst, VISA_VectorOpnd *src0, VISA_VectorOpnd *src1)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;

    if(IS_GEN_BOTH_PATH)
    {
        G4_Predicate * g4Pred = (pred != NULL)? pred->g4opnd->asPredicate() : NULL;
        status = m_builder->translateVISADataMovementInst(opcode, CISA_DM_FMIN /*ignored */,
            g4Pred, executionSize, emask, satMode, tmpDst->g4opnd->asDstRegRegion(), src0->g4opnd, GET_G4_OPNG(src1));
    }
    if(IS_VISA_BOTH_PATH)
    {
        int num_operands = 0;
        VISA_INST_Desc *inst_desc = NULL;
        VISA_opnd *opnd[4];
        inst_desc = &CISA_INST_table[opcode];
        int num_pred_desc_operands = 0;
        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, inst_desc ); //accounting for exec_size and pred_id in descriptor
        VISA_Modifier mod = MODIFIER_NONE;

        VISA_opnd *dst = tmpDst;
        if(satMode)
        {
            if(tmpDst == NULL)
            {
                CM_ERROR_PRINT("Destination for Arithmetic Instruction is NULL");\
                    CmAssert( 0 );
                return CM_FAILURE;
            }
            mod = MODIFIER_SAT;
            dst = (VISA_opnd *)m_mem.alloc(sizeof(VISA_opnd));
            *dst = *tmpDst;
            dst->_opnd.v_opnd.tag += mod<<3;
        }

        ADD_OPND(num_operands, opnd, dst);

        ADD_OPND(num_operands, opnd, src0);

        ADD_OPND(num_operands, opnd, src1);

        CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        //pred id
        unsigned short pred_id = 0;
        if (pred != NULL)
            pred_id = pred->_opnd.v_opnd.opnd_val.pred_opnd.index;

        unsigned char size = executionSize;
        size += emask << 4;
        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);
        inst->createCisaInstruction(opcode, size, 0 , pred_id,opnd, num_operands, inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISAComparisonInst(Common_ISA_Cond_Mod sub_op, Common_VISA_EMask_Ctrl emask, Common_ISA_Exec_Size executionSize, VISA_VectorOpnd *dstOpnd, VISA_VectorOpnd *src0, VISA_VectorOpnd *src1)
{
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    AppendVISAInstCommon();
    int status = CM_SUCCESS;

    if(IS_GEN_BOTH_PATH)
    {
        status = m_builder->translateVISACompareInst(ISA_CMP, executionSize, emask, sub_op,
            dstOpnd->g4opnd->asDstRegRegion(), src0->g4opnd, src1->g4opnd);
    }

    if(IS_VISA_BOTH_PATH)
    {
        ISA_Opcode opcode = ISA_CMP;
        VISA_INST_Desc *inst_desc = NULL;
        VISA_opnd *opnd[4];
        int num_pred_desc_operands = 1;
        inst_desc = &CISA_INST_table[opcode];
        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, inst_desc );
        int num_operands = 0;

        //rel op
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, sub_op));

        ADD_OPND(num_operands, opnd, dstOpnd);

        ADD_OPND(num_operands, opnd, src0);

        ADD_OPND(num_operands, opnd, src1);

        CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        unsigned char size = executionSize;
        size += emask << 4;
        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);
        inst->createCisaInstruction(opcode, size, 0, 0,opnd,num_operands,inst_desc);
        addInstructionToEnd(inst);
    }

#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}
int VISAKernelImpl::AppendVISAComparisonInst(Common_ISA_Cond_Mod sub_op, Common_VISA_EMask_Ctrl emask,
    Common_ISA_Exec_Size executionSize, VISA_PredVar *dstDcl, VISA_VectorOpnd *src0, VISA_VectorOpnd *src1)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;
    uint32_t exSize = Get_Common_ISA_Exec_Size(executionSize);
    VISA_VectorOpnd *dst = NULL;
    CreateVISAPredicateDstOperand(dst, dstDcl, exSize);
    if(IS_GEN_BOTH_PATH)
    {
        status = m_builder->translateVISACompareInst(ISA_CMP, executionSize, emask, sub_op, dstDcl->predVar.dcl, src0->g4opnd, src1->g4opnd);
    }
    if(IS_VISA_BOTH_PATH)
    {
        ISA_Opcode opcode = ISA_CMP;
        VISA_INST_Desc *inst_desc = NULL;
        VISA_opnd *opnd[4];
        int num_pred_desc_operands = 1;
        inst_desc = &CISA_INST_table[opcode];
        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, inst_desc );
        int num_operands = 0;

        //rel op
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, sub_op));

        ADD_OPND(num_operands, opnd, dst);

        ADD_OPND(num_operands, opnd, src0);

        ADD_OPND(num_operands, opnd, src1);

        CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        unsigned char size = executionSize;
        size += emask << 4;
        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);
        inst->createCisaInstruction(opcode, size, 0, 0,opnd,num_operands,inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISACFSIMDInst(ISA_Opcode opcode, VISA_PredOpnd *pred, Common_VISA_EMask_Ctrl emask, Common_ISA_Exec_Size executionSize, VISA_LabelOpnd *label)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;

    if(IS_GEN_BOTH_PATH)
    {
        G4_Predicate * g4Pred = (pred != NULL)? pred->g4opnd->asPredicate() : NULL;

        G4_Label * g4Lbl = (opcode != ISA_GOTO)? NULL: (G4_Label *)label->g4opnd;
        status = m_builder->translateVISASimdInst(opcode, g4Pred, executionSize, emask, g4Lbl);
    }
    if(IS_VISA_BOTH_PATH)
    {
        int num_operands = 0;
        VISA_INST_Desc *inst_desc = NULL;
        inst_desc = &CISA_INST_table[opcode];
        VISA_opnd *opnd[1];

        if( (opcode == ISA_GOTO && label == NULL) ||
            (opcode != ISA_GOTO && label != NULL) )
        {
            CmAssert( 0 );
            return CM_FAILURE;
        }

        ADD_OPND(num_operands, opnd, label);

        //pred id
        unsigned short pred_id = 0;
        if (pred != NULL)
            pred_id = pred->_opnd.v_opnd.opnd_val.pred_opnd.index;

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        unsigned char size = executionSize;
        size += emask << 4;
        inst->createCisaInstruction(opcode, size, 0 , pred_id, opnd, num_operands, inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISACFJmpInst(VISA_PredOpnd *pred, VISA_LabelOpnd *label)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;
    if(IS_GEN_BOTH_PATH)
    {
        G4_Predicate * g4Pred = (pred != NULL)? pred->g4opnd->asPredicate() : NULL;
        status = m_builder->translateVISACFJumpInst(g4Pred, (G4_Label*)label->g4opnd);
    }
    if(IS_VISA_BOTH_PATH)
    {
        VISA_INST_Desc *inst_desc = NULL;
        VISA_opnd * opnd[1];
        inst_desc = &CISA_INST_table[ISA_JMP];
        opnd[0] = label;

        if( label == NULL )
        {
            CmAssert( 0 );
            return CM_FAILURE;
        }
        //pred id
        unsigned short pred_id = 0;
        if (pred != NULL)
            pred_id = pred->_opnd.v_opnd.opnd_val.pred_opnd.index;

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        unsigned char size = EXEC_SIZE_1;
        size += vISA_EMASK_M1 << 4;
        inst->createCisaInstruction(ISA_JMP, size, 0 , pred_id, opnd, 1, inst_desc);

        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISACFCallInst(VISA_PredOpnd *pred, Common_VISA_EMask_Ctrl emask, Common_ISA_Exec_Size executionSize, VISA_LabelOpnd *label)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif

    int status = CM_SUCCESS;
    if(IS_GEN_BOTH_PATH)
    {
        if(isFCCallerKernel())
        {
            m_builder->getFCPatchInfo()->setHasFCCalls(true);
        }
        G4_Predicate * g4Pred = (pred != NULL)? pred->g4opnd->asPredicate() : NULL;
        status = m_builder->translateVISACFCallInst(executionSize, emask, g4Pred, (G4_Label*)label->g4opnd);
    }
    if(IS_VISA_BOTH_PATH)
    {
        VISA_INST_Desc *inst_desc = NULL;
        VISA_opnd * opnd[1];
        inst_desc = &CISA_INST_table[ISA_CALL];
        opnd[0] = label;

        if( label == NULL )
        {
            CmAssert( 0 );
            return CM_FAILURE;
        }
        //pred id
        unsigned short pred_id = 0;
        if (pred != NULL)
            pred_id = pred->_opnd.v_opnd.opnd_val.pred_opnd.index;

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        unsigned char size = executionSize;
        size += emask << 4;
        inst->createCisaInstruction(ISA_CALL, size, 0 , pred_id, opnd, 1, inst_desc);

        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISACFRetInst(VISA_PredOpnd *pred, Common_VISA_EMask_Ctrl emask, Common_ISA_Exec_Size executionSize)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;
    if(IS_GEN_BOTH_PATH)
    {
        G4_Predicate * g4Pred = (pred != NULL)? pred->g4opnd->asPredicate() : NULL;
        if(isFCCallableKernel())
        {
            m_builder->getFCPatchInfo()->setIsCallableKernel(true);
        }
        status = m_builder->translateVISACFRetInst(executionSize, emask, g4Pred);
    }
    if(IS_VISA_BOTH_PATH)
    {
        VISA_INST_Desc *inst_desc = NULL;
        ISA_Opcode opcode = ISA_RET;
        inst_desc = &CISA_INST_table[opcode];

        //pred id
        unsigned short pred_id = 0;
        if(pred != NULL)
            pred_id = pred->_opnd.v_opnd.opnd_val.pred_opnd.index;

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);
        unsigned char size = executionSize;
        size += emask << 4;
        inst->createCisaInstruction(opcode,size,0,pred_id,NULL,0,inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISACFLabelInst(VISA_LabelOpnd *label)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;
    if(IS_GEN_BOTH_PATH)
    {
        status = m_builder->translateVISACFLabelInst((G4_Label*)label->g4opnd);
    }
    if(IS_VISA_BOTH_PATH)
    {
        VISA_INST_Desc *inst_desc = NULL;
        VISA_opnd *opnd[1] = {label};
        inst_desc = &CISA_INST_table[(ISA_Opcode)label->tag];

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);
        inst->createCisaInstruction((ISA_Opcode)label->tag,1,0,0,opnd,1, inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISACFFunctionCallInst(VISA_PredOpnd *pred, Common_VISA_EMask_Ctrl emask,
                                                 Common_ISA_Exec_Size executionSize, unsigned short functionID,
                                                 unsigned char argSize, unsigned char returnSize)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;
    if(IS_GEN_BOTH_PATH)
    {
        G4_Predicate * g4Pred = (pred != NULL)? pred->g4opnd->asPredicate() : NULL;
        status = m_builder->translateVISACFFCallInst(executionSize, emask, g4Pred, functionID, argSize, returnSize);
    }
    if(IS_VISA_BOTH_PATH)
    {
        VISA_INST_Desc *inst_desc = NULL;
        VISA_opnd *opnd[3]; //should be more then enough
        int num_pred_desc_operands = 2;
        ISA_Opcode opcode = ISA_FCALL;
        inst_desc = &CISA_INST_table[opcode];
        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, inst_desc );
        int num_operands = 0;

        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, functionID));

        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, argSize));

        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, returnSize));

        CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        //pred id
        unsigned short pred_id = 0;
        if (pred != NULL)
            pred_id = pred->_opnd.v_opnd.opnd_val.pred_opnd.index;
        /*
        Making a copy of descriptor adn setting correct number of operands.
        This is used later to calculate total size of the buffer.
        */
        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(this->m_mem);

        unsigned char size = executionSize;
        size += emask << 4;
        inst->createCisaInstruction(opcode, size, 0 , pred_id, opnd, num_operands, inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISACFIndirectFuncCallInst(VISA_PredOpnd *pred, Common_VISA_EMask_Ctrl emask,
    Common_ISA_Exec_Size executionSize, VISA_VectorOpnd* funcAddr, uint8_t argSize, uint8_t returnSize)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;
    if (IS_GEN_BOTH_PATH)
    {
        G4_Predicate * g4Pred = pred ? pred->g4opnd->asPredicate() : nullptr;
        status = m_builder->translateVISACFIFCallInst(executionSize, emask, g4Pred, funcAddr->g4opnd,
            argSize, returnSize);
    }
    if (IS_VISA_BOTH_PATH)
    {
        VISA_INST_Desc *inst_desc = &CISA_INST_table[ISA_IFCALL];
        VISA_opnd *opnd[3]; //should be more then enough
        int num_pred_desc_operands = 2;
        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, inst_desc);
        int num_operands = 0;

        opnd[num_operands] = funcAddr;
        ++num_operands;

        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, argSize));

        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, returnSize));

        CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        unsigned short pred_id = pred ? pred->_opnd.v_opnd.opnd_val.pred_opnd.index : 0;

        /*
        Making a copy of descriptor adn setting correct number of operands.
        This is used later to calculate total size of the buffer.
        */
        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(this->m_mem);

        unsigned char size = executionSize;
        size += emask << 4;
        inst->createCisaInstruction(ISA_IFCALL, size, 0, pred_id, opnd, num_operands, inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISACFSymbolInst(std::string symbolName, VISA_VectorOpnd* dst)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;
    if (IS_GEN_BOTH_PATH)
    {
        status = m_builder->translateVISACFSymbolInst(symbolName, (G4_DstRegRegion*)dst->g4opnd);
    }
    if (IS_VISA_BOTH_PATH)
    {
        VISA_INST_Desc *inst_desc = &CISA_INST_table[ISA_FADDR];
        VISA_opnd *opnd[3]; //should be more then enough
        int num_operands = 0;

        // create an entry in string pool with the given symbolName
        uint32_t name_idx = addStringPool(symbolName);
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(0, num_operands, inst_desc, name_idx));

        opnd[num_operands] = dst;
        ++num_operands;

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(this->m_mem);

        inst->createCisaInstruction(ISA_FADDR, EXEC_SIZE_1, 0, 0, opnd, num_operands, inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISACFFunctionRetInst(VISA_PredOpnd *pred, Common_VISA_EMask_Ctrl emask, Common_ISA_Exec_Size executionSize)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;
    if(IS_GEN_BOTH_PATH)
    {
        G4_Predicate * g4Pred = (pred != NULL)? pred->g4opnd->asPredicate() : NULL;
        status = m_builder->translateVISACFFretInst(executionSize, emask, g4Pred);
    }
    if(IS_VISA_BOTH_PATH)
    {
        VISA_INST_Desc *inst_desc = NULL;
        ISA_Opcode opcode = ISA_FRET;
        inst_desc = &CISA_INST_table[opcode];

        //pred id
        unsigned short pred_id = 0;
        if(pred != NULL)
            pred_id = pred->_opnd.v_opnd.opnd_val.pred_opnd.index;

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);
        unsigned char size = executionSize;
        size += emask << 4;
        inst->createCisaInstruction(opcode,size,0,pred_id,NULL,0,inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISACFSwitchJMPInst(VISA_VectorOpnd *index, unsigned char labelCount, VISA_LabelOpnd **labels)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;
    if(IS_GEN_BOTH_PATH)
    {
        G4_Label* labelsArray[50];
        if(labelCount >= 50)
        {
            CmAssert( 0 );
            status = CM_FAILURE;
        }else
        {
            for(int i = 0; i< labelCount; i++)
            {
#if START_ASSERT_CHECK
                if(labels[i] == NULL || labels[i]->g4opnd == NULL)
                {
                    CmAssert( 0 );
                    status = CM_FAILURE;
                    break;
                }
#endif
                labelsArray[i] = (G4_Label*)labels[i]->g4opnd;
            }

            status = m_builder->translateVISACFSwitchInst(index->g4opnd, labelCount, labelsArray);
        }
    }
    if(IS_VISA_BOTH_PATH)
    {
        VISA_INST_Desc *inst_desc_temp = NULL;
        VISA_INST_Desc *inst_desc = (VISA_INST_Desc *)m_mem.alloc(sizeof(VISA_INST_Desc));
        int num_pred_desc_operands = 1;
        unsigned int num_operands = 0;
        ISA_Opcode opcode = ISA_SWITCHJMP;
        inst_desc_temp = &CISA_INST_table[opcode];
        *inst_desc = CISA_INST_table[opcode];
        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, inst_desc_temp );

        CISA_opnd *opnd[35];

        if(index == NULL || labelCount == 0 || labels == NULL)
        {
            CmAssert( 0 );
            return CM_FAILURE;
        }

        opnd[num_operands] = CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc_temp, labelCount);
        ++num_operands;
        opnd[num_operands] = index;
        ++num_operands;

        memcpy_s(&opnd[num_operands], sizeof(VISA_LabelOpnd*)* labelCount, labels, sizeof(VISA_LabelOpnd*)* labelCount);
        /*
        Making a copy of descriptor adn setting correct number of operands.
        This is used later to calculate total size of the buffer.
        */
        inst_desc->opnd_num = num_pred_desc_operands + labelCount+ num_operands;

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        unsigned char size = EXEC_SIZE_1;
        size += vISA_EMASK_M1 << 4;
        inst->createCisaInstruction(opcode, size, 0 , 0, opnd, labelCount+num_operands, inst_desc);

        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISASurfAccessDwordAtomicInst(VISA_PredOpnd           *pred,
                                                        VISAAtomicOps      subOpc,
                                                        bool                    is16Bit,
                                                        Common_VISA_EMask_Ctrl  eMask,
                                                        Common_ISA_Exec_Size    execSize,
                                                        VISA_StateOpndHandle    *surface,
                                                        VISA_RawOpnd            *offsets,
                                                        VISA_RawOpnd            *src0,
                                                        VISA_RawOpnd            *src1,
                                                        VISA_RawOpnd            *dst) {
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif

    int status = CM_SUCCESS;

    if (IS_GEN_BOTH_PATH) {
        CreateGenRawSrcOperand(offsets);
        CreateGenRawSrcOperand(src0);
        CreateGenRawSrcOperand(src1);
        CreateGenRawDstOperand(dst);
        status = m_builder
            ->translateVISADwordAtomicInst(subOpc, is16Bit,
                                           pred ? pred->g4opnd->asPredicate() : 0,
                                           execSize, eMask,
                                           surface->g4opnd,
                                           offsets->g4opnd->asSrcRegRegion(),
                                           src0->g4opnd->asSrcRegRegion(),
                                           src1->g4opnd->asSrcRegRegion(),
                                           dst->g4opnd->asDstRegRegion());
    }

    if (IS_VISA_BOTH_PATH) {
        ISA_Opcode opcode = ISA_DWORD_ATOMIC;
        VISA_INST_Desc *instDesc = &CISA_INST_table[opcode];

        VISA_opnd *ops[6];
        int numOps = 0;

        uint8_t OpAnd16BitTag = uint8_t(subOpc) | uint8_t((is16Bit ? 1 : 0) << 5);
        ADD_OPND(numOps, ops, CreateOtherOpnd(OpAnd16BitTag, ISA_TYPE_UB));
        ADD_OPND(numOps, ops, surface);
        ADD_OPND(numOps, ops, offsets);
        ADD_OPND(numOps, ops, src0);
        ADD_OPND(numOps, ops, src1);
        ADD_OPND(numOps, ops, dst);

        CisaFramework::CisaInst * inst
            = new(m_mem) CisaFramework::CisaInst(m_mem);

        // Predicate
        unsigned short predId
            = pred ?  pred->_opnd.v_opnd.opnd_val.pred_opnd.index : 0;
        // Pack execution size & mask
        unsigned size = execSize;
        PACK_EXEC_SIZE(size, eMask);

        inst->createCisaInstruction(opcode, (uint8_t)size, 0, predId, ops, numOps, instDesc);
        addInstructionToEnd(inst);
    }

#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISASurfAccessGatherScatterInst(ISA_Opcode opcode, Common_VISA_EMask_Ctrl emask, GATHER_SCATTER_ELEMENT_SIZE elementSize,
                                                          Common_ISA_Exec_Size executionSize, VISA_StateOpndHandle *surface, VISA_VectorOpnd *globalOffset, VISA_RawOpnd *elementOffset, VISA_RawOpnd *srcDst)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;

    if(IS_GEN_BOTH_PATH)
    {
        CreateGenRawSrcOperand(elementOffset);
        auto offset = elementOffset->g4opnd->asSrcRegRegion();
        if(opcode == ISA_GATHER)
        {
            CreateGenRawDstOperand(srcDst); //gather: srcDst is dst
            status = m_builder->translateVISAGatherInst(emask, false, elementSize, executionSize,
                surface->g4opnd, globalOffset->g4opnd, offset, srcDst->g4opnd->asDstRegRegion());
        }
        else
        {
            CreateGenRawSrcOperand(srcDst); //scatter: srcDst is src
            status = m_builder->translateVISAScatterInst(emask, elementSize, executionSize,
                surface->g4opnd, globalOffset->g4opnd, offset, srcDst->g4opnd->asSrcRegRegion());
        }
    }
    if(IS_VISA_BOTH_PATH)
    {
        VISA_INST_Desc *inst_desc = NULL;
        VISA_opnd *opnd[8];
        int num_pred_desc_operands = 0;
        inst_desc = &CISA_INST_table[opcode];
        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, inst_desc );
        int num_operands = 0;

        unsigned int numberOfElements = 0;

        //elt_size
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, elementSize));

        if(opcode == ISA_GATHER)
        {
            //ignored
            ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, 0));
        }

        //elt_size
        switch( executionSize )
        {
        case EXEC_SIZE_8:
            numberOfElements = 0;
            break;
        case EXEC_SIZE_16:
            numberOfElements = 1;
            break;
        case EXEC_SIZE_1:
            numberOfElements= 2;
            break;
        default:
            MUST_BE_TRUE(false, "Invalid Number of Elements for Gather/Scatter." );
            return false;
        }

        numberOfElements += emask<<4;
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, numberOfElements));

        //surface
        ADD_OPND(num_operands, opnd, surface);

        //global offset
        ADD_OPND(num_operands, opnd, globalOffset);

        //element offset
        ADD_OPND(num_operands, opnd, elementOffset);

        //dst/src
        ADD_OPND(num_operands, opnd, srcDst);

        CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        inst->createCisaInstruction(opcode, EXEC_SIZE_1, 0 , 0 ,opnd, num_operands, inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISASurfAccessGather4Scatter4TypedInst(ISA_Opcode opcode,
                                                                 VISA_PredOpnd *pred,
                                                                 VISAChannelMask _chMask,
                                                                 Common_VISA_EMask_Ctrl emask,
                                                                 Common_ISA_Exec_Size executionSize,
                                                                 VISA_StateOpndHandle *surface,
                                                                 VISA_RawOpnd *uOffset,
                                                                 VISA_RawOpnd *vOffset,
                                                                 VISA_RawOpnd *rOffset,
                                                                 VISA_RawOpnd *lod,
                                                                 VISA_RawOpnd *dst)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;
    ChannelMask chMask = ChannelMask::createFromAPI(_chMask);

    if(IS_GEN_BOTH_PATH)
    {
        G4_Predicate * g4Pred = (pred != NULL) ? pred->g4opnd->asPredicate() : NULL;
        CreateGenRawSrcOperand(uOffset);
        CreateGenRawSrcOperand(vOffset);
        CreateGenRawSrcOperand(rOffset);
        CreateGenRawSrcOperand(lod);
        if (opcode == ISA_GATHER4_TYPED) {
            CreateGenRawDstOperand(dst);
            status = m_builder->translateVISAGather4TypedInst(g4Pred, emask, chMask, surface->g4opnd, executionSize, uOffset->g4opnd->asSrcRegRegion(), vOffset->g4opnd->asSrcRegRegion(), rOffset->g4opnd->asSrcRegRegion(), lod->g4opnd->asSrcRegRegion(), dst->g4opnd->asDstRegRegion());
        } else {
            ASSERT_USER(opcode == ISA_SCATTER4_TYPED, "Invalid opcode for typed gather4/scatter4!");
            CreateGenRawSrcOperand(dst);
            status = m_builder->translateVISAScatter4TypedInst(g4Pred, emask, chMask, surface->g4opnd, executionSize, uOffset->g4opnd->asSrcRegRegion(), vOffset->g4opnd->asSrcRegRegion(), rOffset->g4opnd->asSrcRegRegion(), lod->g4opnd->asSrcRegRegion(), dst->g4opnd->asSrcRegRegion());
        }
    }
    if(IS_VISA_BOTH_PATH)
    {
        VISA_INST_Desc *inst_desc = NULL;
        VISA_opnd *opnd[8];
        int num_operands = 0;
        inst_desc = &CISA_INST_table[opcode];

        ADD_OPND(num_operands, opnd, CreateOtherOpnd(chMask.getBinary(opcode),
                                              ISA_TYPE_UB));
        ADD_OPND(num_operands, opnd, surface);
        ADD_OPND(num_operands, opnd, uOffset);
        ADD_OPND(num_operands, opnd, vOffset);
        ADD_OPND(num_operands, opnd, rOffset);
        ADD_OPND(num_operands, opnd, lod);
        ADD_OPND(num_operands, opnd, dst);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        unsigned short predId
            = pred ?  pred->_opnd.v_opnd.opnd_val.pred_opnd.index : 0;
        unsigned size = executionSize;
        PACK_EXEC_SIZE(size, emask);

        int status = inst->createCisaInstruction(opcode, (uint8_t)size, 0, predId, opnd, num_operands, inst_desc);
        if( status != CM_SUCCESS )
        {
            CmAssert( 0 );
            return status;
        }
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISASurfAccessGather4Scatter4ScaledInst(ISA_Opcode                opcode,
                                                                  VISA_PredOpnd             *pred,
                                                                  Common_VISA_EMask_Ctrl    eMask,
                                                                  Common_ISA_Exec_Size      execSize,
                                                                  VISAChannelMask           channelMask,
                                                                  VISA_StateOpndHandle      *surface,
                                                                  VISA_VectorOpnd           *globalOffset,
                                                                  VISA_RawOpnd              *offsets,
                                                                  VISA_RawOpnd              *dstSrc) {
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;
    ChannelMask chMask = ChannelMask::createFromAPI(channelMask);

    if (IS_GEN_BOTH_PATH) {
        ASSERT_USER(opcode == ISA_GATHER4_SCALED ||
                    opcode == ISA_SCATTER4_SCALED,
                    "Unknown opcode for scaled message!");

        CreateGenRawSrcOperand(offsets);
        if ( opcode == ISA_GATHER4_SCALED )
        {
            CreateGenRawDstOperand(dstSrc);
        }
        else
        {
            CreateGenRawSrcOperand(dstSrc);
        }
        if (opcode == ISA_GATHER4_SCALED) {
            status = m_builder
                ->translateVISAGather4ScaledInst(pred ? pred->g4opnd->asPredicate() : 0,
                                                 execSize, eMask,
                                                 chMask,
                                                 surface->g4opnd,
                                                 globalOffset->g4opnd,
                                                 offsets->g4opnd->asSrcRegRegion(),
                                                 dstSrc->g4opnd->asDstRegRegion());
        } else {
            status = m_builder
                ->translateVISAScatter4ScaledInst(pred ? pred->g4opnd->asPredicate() : 0,
                                                  execSize, eMask,
                                                  chMask,
                                                  surface->g4opnd,
                                                  globalOffset->g4opnd,
                                                  offsets->g4opnd->asSrcRegRegion(),
                                                  dstSrc->g4opnd->asSrcRegRegion());
        }
    }

    if (IS_VISA_BOTH_PATH) {
        VISA_INST_Desc *instDesc = &CISA_INST_table[opcode];
        VISA_opnd *ops[6];
        int numOps = 0;

        ADD_OPND(numOps, ops, CreateOtherOpnd(chMask.getBinary(opcode),
                                              ISA_TYPE_UB));
        ADD_OPND(numOps, ops, CreateOtherOpnd(0, ISA_TYPE_UW));
        ADD_OPND(numOps, ops, surface);
        ADD_OPND(numOps, ops, globalOffset);
        ADD_OPND(numOps, ops, offsets);
        ADD_OPND(numOps, ops, dstSrc);

        CisaFramework::CisaInst * inst
            = new (m_mem) CisaFramework::CisaInst(m_mem);

        // Predicate
        unsigned short predId
            = pred ?  pred->_opnd.v_opnd.opnd_val.pred_opnd.index : 0;
        // Pack execution size & mask
        unsigned size = execSize;
        PACK_EXEC_SIZE(size, eMask);

        inst->createCisaInstruction(opcode, (uint8_t)size, 0, predId, ops, numOps, instDesc);
        addInstructionToEnd(inst);
    }

#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISASurfAccessScatterScaledInst(ISA_Opcode                opcode,
                                                          VISA_PredOpnd             *pred,
                                                          Common_VISA_EMask_Ctrl    eMask,
                                                          Common_ISA_Exec_Size      execSize,
                                                          Common_ISA_SVM_Block_Num  numBlocks,
                                                          VISA_StateOpndHandle      *surface,
                                                          VISA_VectorOpnd           *globalOffset,
                                                          VISA_RawOpnd              *offsets,
                                                          VISA_RawOpnd              *dstSrc) {
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;

    if (IS_GEN_BOTH_PATH) {
        ASSERT_USER(opcode == ISA_GATHER_SCALED ||
                    opcode == ISA_SCATTER_SCALED,
                    "Unknown opcode for scaled message!");

        CreateGenRawSrcOperand(offsets);
        if ( opcode == ISA_GATHER_SCALED )
        {
            CreateGenRawDstOperand(dstSrc);
        }
        else
        {
            CreateGenRawSrcOperand(dstSrc);
        }
        if (opcode == ISA_GATHER_SCALED) {
            status = m_builder
                ->translateVISAGatherScaledInst(pred ? pred->g4opnd->asPredicate() : 0,
                                                execSize, eMask,
                                                numBlocks,
                                                surface->g4opnd,
                                                globalOffset->g4opnd,
                                                offsets->g4opnd->asSrcRegRegion(),
                                                dstSrc->g4opnd->asDstRegRegion());
        } else {
            status = m_builder
                ->translateVISAScatterScaledInst(pred ? pred->g4opnd->asPredicate() : 0,
                                                  execSize, eMask,
                                                  numBlocks,
                                                  surface->g4opnd,
                                                  globalOffset->g4opnd,
                                                  offsets->g4opnd->asSrcRegRegion(),
                                                  dstSrc->g4opnd->asSrcRegRegion());
        }
    }

    if (IS_VISA_BOTH_PATH) {
        VISA_INST_Desc *instDesc = &CISA_INST_table[opcode];
        VISA_opnd *ops[7];
        int numOps = 0;

        ADD_OPND(numOps, ops, CreateOtherOpnd(0, ISA_TYPE_UB));
        ADD_OPND(numOps, ops, CreateOtherOpnd(numBlocks, ISA_TYPE_UB));
        ADD_OPND(numOps, ops, CreateOtherOpnd(0, ISA_TYPE_UW));
        ADD_OPND(numOps, ops, surface);
        ADD_OPND(numOps, ops, globalOffset);
        ADD_OPND(numOps, ops, offsets);
        ADD_OPND(numOps, ops, dstSrc);

        CisaFramework::CisaInst * inst
            = new (m_mem) CisaFramework::CisaInst(m_mem);

        // Predicate
        unsigned short predId
            = pred ?  pred->_opnd.v_opnd.opnd_val.pred_opnd.index : 0;
        // Pack execution size & mask
        unsigned size = execSize;
        PACK_EXEC_SIZE(size, eMask);

        inst->createCisaInstruction(opcode, (uint8_t)size, 0, predId, ops, numOps, instDesc);
        addInstructionToEnd(inst);
    }

#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISASurfAccessMediaLoadStoreInst(ISA_Opcode opcode, MEDIA_LD_mod modifier, VISA_StateOpndHandle *surface, unsigned char blockWidth,
                                                           unsigned char blockHeight, VISA_VectorOpnd *xOffset, VISA_VectorOpnd *yOffset, VISA_RawOpnd *srcDst,
                                                           CISA_PLANE_ID plane)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;

    if(IS_GEN_BOTH_PATH)
    {
        if(opcode == ISA_MEDIA_LD)
        {
            CreateGenRawDstOperand(srcDst); //srcDst: dst
            status = m_builder->translateVISAMediaLoadInst(modifier, surface->g4opnd, plane, blockWidth, blockHeight,
                xOffset->g4opnd, yOffset->g4opnd, srcDst->g4opnd->asDstRegRegion());
        }
        else
        {
            if ( opcode!=ISA_MEDIA_ST )
            {
                CreateGenRawDstOperand(srcDst); //srcDst: dst
            }
            else
            {
                CreateGenRawSrcOperand(srcDst); //srcDst: src
            }
            status = m_builder->translateVISAMediaStoreInst((MEDIA_ST_mod)modifier, surface->g4opnd, plane, blockWidth,
                blockHeight, xOffset->g4opnd, yOffset->g4opnd, srcDst->g4opnd->asSrcRegRegion());
        }
    }
    if(IS_VISA_BOTH_PATH)
    {
        VISA_INST_Desc *inst_desc = NULL;
        VISA_opnd *opnd[8];
        int num_pred_desc_operands = 0;
        inst_desc = &CISA_INST_table[opcode];
        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, inst_desc );
        int num_operands = 0;

        //modifiers
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, modifier));
        //surface
        ADD_OPND(num_operands, opnd, surface);

        //plane
        //right now there is VISA and implementation missmatch
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, plane));

        //block width
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, blockWidth));

        //block height
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, blockHeight));

        //x_offset_opnd
        ADD_OPND(num_operands, opnd, xOffset);

        //y_offset_opnd
        ADD_OPND(num_operands, opnd, yOffset);

        //raw_opnd
        ADD_OPND(num_operands, opnd, srcDst);

        CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);
        inst->createCisaInstruction(opcode,EXEC_SIZE_1,0,0,opnd,num_operands,inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

CisaFramework::CisaInst* AppendVISASvmGeneralBlockInst(Common_ISA_Oword_Num size, bool unaligned, VISA_VectorOpnd* address, VISA_RawOpnd *srcDst, vISA::Mem_Manager& mem, bool isReadOnly)
{
    VISA_opnd*    opnd[4] = { NULL, NULL, address, srcDst};
    unsigned char pack[2] = {static_cast<unsigned char>(isReadOnly ? SVM_BLOCK_LD : SVM_BLOCK_ST), static_cast<unsigned char>(size | (unaligned ? 0x80 : 0))};
    for (unsigned i = 0; i < lengthOf(pack); i++)
    {
        opnd[i]                   = (VISA_opnd*)mem.alloc(sizeof(VISA_opnd));
        opnd[i]->_opnd.other_opnd = pack[i];
        opnd[i]->opnd_type        = CISA_OPND_OTHER;
        opnd[i]->size             = sizeof(pack[i]);
        /// opnd[i]->tag              = TYPE_UB;
    }

    CisaFramework::CisaInst* inst = new(mem)CisaFramework::CisaInst(mem);
    inst->createCisaInstruction(ISA_SVM, EXEC_SIZE_1, 0, 0, opnd, lengthOf(opnd), &CISA_INST_table[ISA_SVM]);
    return inst;
}

CisaFramework::CisaInst* VISAKernelImpl::AppendVISASvmGeneralScatterInst(VISA_PredOpnd* pred,
                                                                         Common_VISA_EMask_Ctrl emask,
                                                                         Common_ISA_Exec_Size execSize,
                                                                         unsigned char blockSize,
                                                                         unsigned char numBlocks,
                                                                         VISA_RawOpnd* address,
                                                                         VISA_RawOpnd *srcDst,
                                                                         bool isRead)
{

    VISA_INST_Desc *inst_desc = NULL;
    VISA_opnd *opnd[10];
    SVMSubOpcode subOp = isRead ? SVM_GATHER : SVM_SCATTER;
    inst_desc = &CISA_INST_table[ISA_SVM];
    int num_operands = 0;
    unsigned char size = execSize;
    size += emask << 4;

    unsigned short pred_id = 0;
    if (pred != NULL)
    {
        pred_id = pred->_opnd.v_opnd.opnd_val.pred_opnd.index;
    }

    // execSize and pred are not handled uniformly for some reason
    ADD_OPND(num_operands, opnd, CreateOtherOpnd(subOp, ISA_TYPE_UB));
    ADD_OPND(num_operands, opnd, CreateOtherOpnd(blockSize, ISA_TYPE_UB));
    ADD_OPND(num_operands, opnd, CreateOtherOpnd(numBlocks, ISA_TYPE_UB));

    ADD_OPND(num_operands, opnd, address);
    ADD_OPND(num_operands, opnd, srcDst);

    CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

    inst->createCisaInstruction(ISA_SVM, size, 0, pred_id, opnd, num_operands, inst_desc);
    return inst;
}

int VISAKernelImpl::AppendVISASvmBlockLoadInst(Common_ISA_Oword_Num size, bool unaligned, VISA_VectorOpnd* address, VISA_RawOpnd *srcDst)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;

    if (IS_GEN_BOTH_PATH)
    {
        CreateGenRawDstOperand(srcDst); //dst for load
        status = m_builder->translateVISASVMBlockReadInst(size, unaligned, address->g4opnd->asSrcRegRegion(),
            srcDst->g4opnd->asDstRegRegion());
    }
    if (IS_VISA_BOTH_PATH)
    {
        addInstructionToEnd(AppendVISASvmGeneralBlockInst(size, unaligned, address, srcDst, m_mem, true /* read */));
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISASvmBlockStoreInst(Common_ISA_Oword_Num size, bool unaligned, VISA_VectorOpnd* address, VISA_RawOpnd *srcDst)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;

    if(IS_GEN_BOTH_PATH)
    {
        CreateGenRawSrcOperand(srcDst); //src for store
        status = m_builder->translateVISASVMBlockWriteInst(size, address->g4opnd->asSrcRegRegion(),
            srcDst->g4opnd->asSrcRegRegion());
    }

    if (IS_VISA_BOTH_PATH)
    {
        addInstructionToEnd(AppendVISASvmGeneralBlockInst(size, unaligned, address, srcDst, m_mem, false /* write */));
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISASvmGatherInst(VISA_PredOpnd *pred,
                                            Common_VISA_EMask_Ctrl emask,
                                            Common_ISA_Exec_Size executionSize,
                                            Common_ISA_SVM_Block_Type blockType,
                                            Common_ISA_SVM_Block_Num numBlocks,
                                            VISA_RawOpnd* address,
                                            VISA_RawOpnd* srcDst)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;
    if(IS_GEN_BOTH_PATH)
    {
        CreateGenRawSrcOperand(address);
        CreateGenRawDstOperand(srcDst); // dst for gather
        G4_Predicate * g4Pred = (pred != NULL) ? pred->g4opnd->asPredicate() : NULL;
        status = m_builder->translateVISASVMScatterReadInst(executionSize, emask, g4Pred, blockType, numBlocks,
            address->g4opnd->asSrcRegRegion(), srcDst->g4opnd->asDstRegRegion());
    }

    if (IS_VISA_BOTH_PATH)
    {
        addInstructionToEnd(AppendVISASvmGeneralScatterInst(pred, emask, executionSize, blockType, numBlocks, address, srcDst, true /* read */));
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISASvmScatterInst(VISA_PredOpnd *pred,
                                            Common_VISA_EMask_Ctrl emask,
                                            Common_ISA_Exec_Size executionSize,
                                            Common_ISA_SVM_Block_Type blockType,
                                            Common_ISA_SVM_Block_Num numBlocks,
                                            VISA_RawOpnd* address,
                                            VISA_RawOpnd* srcDst)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;
    if(IS_GEN_BOTH_PATH)
    {
        CreateGenRawSrcOperand(address);
        CreateGenRawSrcOperand(srcDst); // src for scatter
        G4_Predicate * g4Pred = (pred != NULL) ? pred->g4opnd->asPredicate() : NULL;
        status = m_builder->translateVISASVMScatterWriteInst(executionSize, emask, g4Pred, blockType, numBlocks,
            address->g4opnd->asSrcRegRegion(), srcDst->g4opnd->asSrcRegRegion());
    }

    if (IS_VISA_BOTH_PATH)
    {
        addInstructionToEnd(AppendVISASvmGeneralScatterInst(pred, emask, executionSize, blockType, numBlocks, address, srcDst, false /* write */));
    }

#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return CM_SUCCESS;
}

int VISAKernelImpl::AppendVISASvmAtomicInst(VISA_PredOpnd *pred,
                                            Common_VISA_EMask_Ctrl emask,
                                            Common_ISA_Exec_Size executionSize,
                                            VISAAtomicOps op,
                                            unsigned short bitwidth,
                                            VISA_RawOpnd* address,
                                            VISA_RawOpnd* src0,
                                            VISA_RawOpnd* src1,
                                            VISA_RawOpnd* dst)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;
    if (IS_GEN_BOTH_PATH)
    {
        CreateGenRawSrcOperand(address);
        CreateGenRawSrcOperand(src0);
        CreateGenRawSrcOperand(src1);
        CreateGenRawDstOperand(dst);
        G4_Predicate * g4Pred = (pred != NULL) ? pred->g4opnd->asPredicate() : NULL;
        status = m_builder->translateVISASVMAtomicInst(
            static_cast<VISAAtomicOps>(op), bitwidth, executionSize, emask,
            g4Pred, address->g4opnd->asSrcRegRegion(),
            src0->g4opnd->asSrcRegRegion(), src1->g4opnd->asSrcRegRegion(),
            dst->g4opnd->asDstRegRegion());
    }

    if (IS_VISA_BOTH_PATH)
    {
        VISA_INST_Desc *inst_desc = NULL;
        VISA_opnd *opnd[10];
        inst_desc = &CISA_INST_table[ISA_SVM];
        int num_operands = 0;
        ADD_OPND(num_operands, opnd, this->CreateOtherOpnd(SVM_ATOMIC, ISA_TYPE_UB));
        uint8_t BitwidthTag = uint8_t(op);
        switch (bitwidth)
        {
            case 16: BitwidthTag |= 0x20; break;
            case 64: BitwidthTag |= 0x40; break;
        };
        ADD_OPND(num_operands, opnd, this->CreateOtherOpnd(BitwidthTag, ISA_TYPE_UB));
        ADD_OPND(num_operands, opnd, address);
        ADD_OPND(num_operands, opnd, src0);
        ADD_OPND(num_operands, opnd, src1);
        ADD_OPND(num_operands, opnd, dst);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        unsigned char size = executionSize;
        size += emask << 4;

        //pred id
        unsigned short pred_id = 0;
        if (pred != NULL)
        {
            pred_id = pred->_opnd.v_opnd.opnd_val.pred_opnd.index;
        }

        inst->createCisaInstruction(ISA_SVM, size, 0, pred_id, opnd, num_operands, inst_desc);
        addInstructionToEnd(inst);
    }

#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return CM_SUCCESS;
}

CisaFramework::CisaInst *
VISAKernelImpl::PackCisaInsnForSVMGather4Scatter4Scaled(unsigned subOpc,
                                                        VISA_PredOpnd *pred,
                                                        Common_VISA_EMask_Ctrl eMask,
                                                        Common_ISA_Exec_Size executionSize,
                                                        ChannelMask chMask,
                                                        VISA_VectorOpnd *address,
                                                        VISA_RawOpnd *offsets,
                                                        VISA_RawOpnd *srcOrDst)
{
    VISA_INST_Desc *instDesc = &CISA_INST_table[ISA_SVM];
    VISA_opnd *ops[6];
    int numOps = 0;

    ADD_OPND(numOps, ops, CreateOtherOpnd(subOpc, ISA_TYPE_UB));
    ADD_OPND(numOps, ops, CreateOtherOpnd(chMask.getBinary(ISA_SVM),
                                          ISA_TYPE_UB));
    ADD_OPND(numOps, ops, CreateOtherOpnd(0, ISA_TYPE_UW));

    ADD_OPND(numOps, ops, address);
    ADD_OPND(numOps, ops, offsets);
    ADD_OPND(numOps, ops, srcOrDst);

    CisaFramework::CisaInst *insn
        = new (m_mem) CisaFramework::CisaInst(m_mem);

    // Predicate
    unsigned short predId
        = pred ? pred->_opnd.v_opnd.opnd_val.pred_opnd.index : 0;
    // Pack executionSize & eMask
    unsigned size = executionSize;
    PACK_EXEC_SIZE(size, eMask);

    insn->createCisaInstruction(ISA_SVM, (uint8_t)size, 0, predId, ops, numOps,
                                instDesc);

    return insn;
}

int VISAKernelImpl::AppendVISASvmGather4ScaledInst(VISA_PredOpnd            *pred,
                                                   Common_VISA_EMask_Ctrl   eMask,
                                                   Common_ISA_Exec_Size     executionSize,
                                                   VISAChannelMask          channelMask,
                                                   VISA_VectorOpnd          *address,
                                                   VISA_RawOpnd             *offsets,
                                                   VISA_RawOpnd             *dst)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;

    ChannelMask chMask = ChannelMask::createFromAPI(channelMask);

    if (IS_GEN_BOTH_PATH) {
        CreateGenRawSrcOperand(offsets);
        CreateGenRawDstOperand(dst);
        status = m_builder
            ->translateVISASVMGather4ScaledInst(executionSize, eMask,
                                                chMask,
                                                pred ? pred->g4opnd->asPredicate() : 0,
                                                address->g4opnd,
                                                offsets->g4opnd->asSrcRegRegion(),
                                                dst->g4opnd->asDstRegRegion());
    }

    if (IS_VISA_BOTH_PATH) {
        addInstructionToEnd(
            PackCisaInsnForSVMGather4Scatter4Scaled(SVM_GATHER4SCALED,
                                                    pred, eMask, executionSize,
                                                    chMask,
                                                    address, offsets, dst));
    }

#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISASvmScatter4ScaledInst(VISA_PredOpnd           *pred,
                                                    Common_VISA_EMask_Ctrl  eMask,
                                                    Common_ISA_Exec_Size    executionSize,
                                                    VISAChannelMask         channelMask,
                                                    VISA_VectorOpnd         *address,
                                                    VISA_RawOpnd            *offsets,
                                                    VISA_RawOpnd            *src)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;

    ChannelMask chMask = ChannelMask::createFromAPI(channelMask);

    if (IS_GEN_BOTH_PATH) {
        CreateGenRawSrcOperand(offsets);
        CreateGenRawSrcOperand(src);
        status = m_builder
            ->translateVISASVMScatter4ScaledInst(executionSize, eMask,
                                                 chMask,
                                                 pred ? pred->g4opnd->asPredicate() : 0,
                                                 address->g4opnd,
                                                 offsets->g4opnd->asSrcRegRegion(),
                                                 src->g4opnd->asSrcRegRegion());
    }

    if (IS_VISA_BOTH_PATH) {
        addInstructionToEnd(
            PackCisaInsnForSVMGather4Scatter4Scaled(SVM_SCATTER4SCALED,
                                                    pred, eMask, executionSize,
                                                    chMask,
                                                    address, offsets, src));
    }

#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISASurfAccessOwordLoadStoreInst(ISA_Opcode opcode, Common_VISA_EMask_Ctrl emask, VISA_StateOpndHandle *surface, Common_ISA_Oword_Num size, VISA_VectorOpnd *offset, VISA_RawOpnd *srcDst)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;

    if(IS_GEN_BOTH_PATH)
    {
        if(opcode == ISA_OWORD_ST)
        {
            CreateGenRawSrcOperand(srcDst);
            status = m_builder->translateVISAOwordStoreInst(surface->g4opnd, size, offset->g4opnd,
                srcDst->g4opnd->asSrcRegRegion());
        }else
        {
            CreateGenRawDstOperand(srcDst); //srcDst: dst
            status = m_builder->translateVISAOwordLoadInst(opcode, false, surface->g4opnd, size, offset->g4opnd,
                srcDst->g4opnd->asDstRegRegion());
        }
    }
    if(IS_VISA_BOTH_PATH)
    {
        VISA_INST_Desc *inst_desc = NULL;
        VISA_opnd *opnd[5];
        inst_desc = &CISA_INST_table[opcode];
        int num_operands = 0;
        int num_pred_desc_operands = 0;
        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, inst_desc );

        //size
        opnd[num_operands] = (VISA_opnd * )m_mem.alloc(sizeof(VISA_opnd));
        opnd[num_operands]->_opnd.other_opnd = size;
        opnd[num_operands]->opnd_type = CISA_OPND_OTHER;
        opnd[num_operands]->size = (uint16_t)Get_Common_ISA_Type_Size((VISA_Type)inst_desc->opnd_desc[num_operands].data_type);
        opnd[num_operands]->tag = (uint8_t)inst_desc->opnd_desc[num_operands].opnd_type;
        num_operands++;

        //ignored
        if(opcode == ISA_OWORD_LD || opcode == ISA_OWORD_LD_UNALIGNED)
        {
            ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, 0));
        }

        ADD_OPND(num_operands, opnd, surface);
        ADD_OPND(num_operands, opnd, offset);
        ADD_OPND(num_operands, opnd, srcDst);

        CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);
        inst->createCisaInstruction(opcode,EXEC_SIZE_1,0,0,opnd,num_operands,inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISASILoad(VISA_StateOpndHandle *surface, VISAChannelMask _channel, bool isSIMD16,
                                     VISA_RawOpnd *uOffset, VISA_RawOpnd *vOffset, VISA_RawOpnd *rOffset, VISA_RawOpnd *dst)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;
    ChannelMask channel = ChannelMask::createFromAPI(_channel);

    if(IS_GEN_BOTH_PATH)
    {
        uint8_t simdMode = isSIMD16 ? 16: 8;
        CreateGenRawSrcOperand(uOffset);
        CreateGenRawSrcOperand(vOffset);
        CreateGenRawSrcOperand(rOffset);
        CreateGenRawDstOperand(dst);
        status = m_builder->translateVISASamplerInst(simdMode, surface->g4opnd, NULL, channel, channel.getNumEnabledChannels(), uOffset->g4opnd, vOffset->g4opnd, rOffset->g4opnd, dst->g4opnd->asDstRegRegion());
    }
    if(IS_VISA_BOTH_PATH)
    {
        VISA_INST_Desc *inst_desc = NULL;
        VISA_opnd *opnd[8];
        int num_pred_desc_operands = 0;
        ISA_Opcode opcode = ISA_LOAD;
        inst_desc = &CISA_INST_table[opcode];
        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, inst_desc );
        int num_operands = 0;

        unsigned mode = channel.getBinary(opcode);

        if(isSIMD16)
            mode += 0x1<<4;

        //mode
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(0, num_operands, inst_desc, mode));

        ADD_OPND(num_operands, opnd, surface);
        ADD_OPND(num_operands, opnd, uOffset);
        ADD_OPND(num_operands, opnd, vOffset);
        ADD_OPND(num_operands, opnd, rOffset);
        ADD_OPND(num_operands, opnd, dst);

        CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        inst->createCisaInstruction(opcode, EXEC_SIZE_1, 0 , 0,opnd, num_operands, inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISASISample(Common_VISA_EMask_Ctrl emask, VISA_StateOpndHandle *surface, VISA_StateOpndHandle *sampler, VISAChannelMask _channel, bool isSIMD16,
                                       VISA_RawOpnd *uOffset, VISA_RawOpnd *vOffset, VISA_RawOpnd *rOffset, VISA_RawOpnd *dst)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;
    ChannelMask channel = ChannelMask::createFromAPI(_channel);

    if(IS_GEN_BOTH_PATH)
    {
        uint8_t simdMode = (isSIMD16)?16:8;
        CreateGenRawSrcOperand(uOffset);
        CreateGenRawSrcOperand(vOffset);
        CreateGenRawSrcOperand(rOffset);
        CreateGenRawDstOperand(dst); //srcDst: src
        status = m_builder->translateVISASamplerInst(simdMode, surface->g4opnd, sampler->g4opnd, channel, channel.getNumEnabledChannels(), uOffset->g4opnd, vOffset->g4opnd, rOffset->g4opnd, dst->g4opnd->asDstRegRegion());
    }
    if(IS_VISA_BOTH_PATH)
    {
        VISA_INST_Desc *inst_desc = NULL;
        VISA_opnd *opnd[8];
        int num_pred_desc_operands = 0;
        ISA_Opcode opcode = ISA_SAMPLE;
        inst_desc = &CISA_INST_table[opcode];
        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, inst_desc );
        int num_operands = 0;

        unsigned mode = channel.getBinary(opcode);

        if(isSIMD16)
            mode += 0x1<<4;

        //mode
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(0, num_operands, inst_desc, mode));
        ADD_OPND(num_operands, opnd, sampler);
        ADD_OPND(num_operands, opnd, surface);
        ADD_OPND(num_operands, opnd, uOffset);
        ADD_OPND(num_operands, opnd, vOffset);
        ADD_OPND(num_operands, opnd, rOffset);
        ADD_OPND(num_operands, opnd, dst);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        inst->createCisaInstruction(opcode, EXEC_SIZE_1, 0 , 0,opnd, num_operands, inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISASISampleUnorm(VISA_StateOpndHandle *surface, VISA_StateOpndHandle *sampler, VISAChannelMask _channel,
                                            VISA_VectorOpnd *uOffset, VISA_VectorOpnd *vOffset, VISA_VectorOpnd *deltaU, VISA_VectorOpnd *deltaV, VISA_RawOpnd *dst, CHANNEL_OUTPUT_FORMAT _output)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;
    ChannelMask channel = ChannelMask::createFromAPI(_channel);

    if(IS_GEN_BOTH_PATH)
    {
        CreateGenRawDstOperand(dst); //srcDst: src
        status = m_builder->translateVISASamplerNormInst(surface->g4opnd, sampler->g4opnd, channel, channel.getNumEnabledChannels(), deltaU->g4opnd, uOffset->g4opnd, deltaV->g4opnd, vOffset->g4opnd, dst->g4opnd->asDstRegRegion());
    }
    if(IS_VISA_BOTH_PATH)
    {
        VISA_INST_Desc *inst_desc = NULL;
        VISA_opnd *opnd[8];
        int num_pred_desc_operands = 0;
        ISA_Opcode opcode = ISA_SAMPLE_UNORM;
        inst_desc = &CISA_INST_table[opcode];
        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, inst_desc );
        int num_operands = 0;

        //mode
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(0, num_operands, inst_desc, channel.getBinary(opcode, _output)));

        ADD_OPND(num_operands, opnd, sampler);
        ADD_OPND(num_operands, opnd, surface);
        ADD_OPND(num_operands, opnd, uOffset);
        ADD_OPND(num_operands, opnd, vOffset);
        ADD_OPND(num_operands, opnd, deltaU);
        ADD_OPND(num_operands, opnd, deltaV);
        ADD_OPND(num_operands, opnd, dst);

        CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        inst->createCisaInstruction(opcode, EXEC_SIZE_1, 0 , 0,opnd, num_operands, inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISAWaitInst(VISA_VectorOpnd* mask)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;

    if (IS_GEN_BOTH_PATH)
    {
        status = m_builder->translateVISAWaitInst(mask != NULL ? mask->g4opnd : NULL);
    }
    if(IS_VISA_BOTH_PATH)
    {
        VISA_INST_Desc *inst_desc = NULL;
        VISA_opnd* opnd[1];
        int num_pred_desc_operands = 0;
        inst_desc = &CISA_INST_table[ISA_WAIT];
        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, inst_desc );
        int num_operands = 0;

        if (mask == nullptr)
        {
            int val = 0;
            CreateVISAImmediate(mask, &val, ISA_TYPE_UD);
        }

        ADD_OPND(num_operands, opnd, mask);

        CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        inst->createCisaInstruction(ISA_WAIT, EXEC_SIZE_1, 0 , 0, opnd, num_operands, inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}


int VISAKernelImpl::AppendVISASyncInst(ISA_Opcode opcode, unsigned char mask)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;

    if(IS_GEN_BOTH_PATH)
    {
        status = m_builder->translateVISASyncInst(opcode, mask);
    }
    if(IS_VISA_BOTH_PATH)
    {
        VISA_INST_Desc *inst_desc = NULL;
        VISA_opnd* opnd[1];
        int num_pred_desc_operands = 0;
        inst_desc = &CISA_INST_table[opcode];
        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, inst_desc );
        int num_operands = 0;

        if( opcode == ISA_FENCE )
        {
            //number of registers to send
            ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, mask));
        }

        CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        inst->createCisaInstruction(opcode, EXEC_SIZE_1, 0 , 0,opnd, num_operands, inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISASplitBarrierInst(bool isSignal)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;

    if (IS_GEN_BOTH_PATH)
    {
        status = m_builder->translateVISASplitBarrierInst(isSignal);
    }

    if (IS_VISA_BOTH_PATH)
    {
        VISA_INST_Desc *inst_desc = NULL;
        VISA_opnd* opnd[1];
        int num_pred_desc_operands = 0;
        inst_desc = &CISA_INST_table[ISA_SBARRIER];
        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, inst_desc);
        int num_operands = 0;

        uint8_t mode = isSignal ? 1 : 0;
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, mode));

        CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        inst->createCisaInstruction(ISA_SBARRIER, EXEC_SIZE_1, 0, 0, opnd, num_operands, inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISAMiscFileInst(const char *fileName)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;

    if(IS_GEN_BOTH_PATH)
    {
        size_t fileLen = strlen(fileName) + 1;
        m_builder->curFile = (char*)m_mem.alloc(fileLen);
        strcpy_s(m_builder->curFile, fileLen, fileName);
    }
    if(IS_VISA_BOTH_PATH)
    {
        VISA_INST_Desc *inst_desc = NULL;
        VISA_opnd* opnd[1];
        ISA_Opcode opcode = ISA_FILE;
        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        inst_desc = &CISA_INST_table[opcode];

        opnd[0] = (VISA_opnd*)m_mem.alloc(sizeof(VISA_opnd));
        opnd[0]->_opnd.other_opnd = addStringPool(std::string(fileName));
        opnd[0]->opnd_type = CISA_OPND_OTHER;

        opnd[0]->size = Get_Common_ISA_Type_Size((VISA_Type)inst_desc->opnd_desc[0].data_type);
        opnd[0]->tag = (uint8_t)inst_desc->opnd_desc[0].opnd_type;
        inst->createCisaInstruction(opcode,1,0,0,opnd,1,inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISAMiscLOC(unsigned int lineNumber)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;

    if(IS_GEN_BOTH_PATH)
    {
        m_builder->curLine = lineNumber;
    }
    if(IS_VISA_BOTH_PATH)
    {
        VISA_INST_Desc *inst_desc = NULL;
        VISA_opnd* opnd[1];
        ISA_Opcode opcode = ISA_LOC;
        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        inst_desc = &CISA_INST_table[opcode];

        opnd[0] = (VISA_opnd*)m_mem.alloc(sizeof(VISA_opnd));
        opnd[0]->_opnd.other_opnd = lineNumber;
        opnd[0]->opnd_type = CISA_OPND_OTHER;

        opnd[0]->size = Get_Common_ISA_Type_Size((VISA_Type)inst_desc->opnd_desc[0].data_type);
        opnd[0]->tag = (uint8_t)inst_desc->opnd_desc[0].opnd_type;
        inst->createCisaInstruction(opcode,1,0,0,opnd,1,inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISAMiscRawSend(VISA_PredOpnd *pred, Common_VISA_EMask_Ctrl emask, Common_ISA_Exec_Size executionSize, unsigned char modifiers,
                                          unsigned int exMsgDesc, unsigned char srcSize, unsigned char dstSize, VISA_VectorOpnd *desc,
                                          VISA_RawOpnd *src, VISA_RawOpnd *dst)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;

    if(IS_GEN_BOTH_PATH)
    {
        CreateGenRawSrcOperand(src);
        CreateGenRawDstOperand(dst);
        G4_Predicate * g4Pred = (pred != NULL)? pred->g4opnd->asPredicate() : NULL;
        dst->g4opnd->asDstRegRegion()->setType( executionSize == EXEC_SIZE_16 ? Type_UW : Type_UD );

        status = m_builder->translateVISARawSendInst(g4Pred, executionSize,
            emask, modifiers, exMsgDesc, srcSize, dstSize, desc->g4opnd,
            src->g4opnd->asSrcRegRegion(), dst->g4opnd->asDstRegRegion());
    }
    if(IS_VISA_BOTH_PATH)
    {
        VISA_INST_Desc *inst_desc = NULL;
        VISA_opnd *opnd[7];
        ISA_Opcode opcode = ISA_RAW_SEND;
        int num_pred_desc_operands = 0;
        inst_desc = &CISA_INST_table[opcode];
        int num_operands = 0;

        //modifier
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, modifiers));

        num_pred_desc_operands = 2;
        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, inst_desc );

        //exMsgDesc
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, exMsgDesc));
        //number of registers to send
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, srcSize));
        //Number of registers expected returned
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, dstSize));
        //Message Descriptor
        ADD_OPND(num_operands, opnd, desc);
        //Source
        ADD_OPND(num_operands, opnd, src);
        //Destination
        ADD_OPND(num_operands, opnd, dst);

        CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        unsigned char size = executionSize;
        size += emask << 4;

        //pred id
        unsigned short pred_id = 0;
        if (pred != NULL)
            pred_id = pred->_opnd.v_opnd.opnd_val.pred_opnd.index;

        inst->createCisaInstruction(opcode, size, modifiers , pred_id, opnd, num_operands, inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISAMiscRawSends(VISA_PredOpnd *pred, Common_VISA_EMask_Ctrl emask, Common_ISA_Exec_Size executionSize, unsigned char modifiers,
                                           unsigned ffid, VISA_VectorOpnd *exMsgDesc, unsigned char src0Size, unsigned char src1Size, unsigned char dstSize, VISA_VectorOpnd *desc,
                                          VISA_RawOpnd *src0, VISA_RawOpnd *src1, VISA_RawOpnd *dst)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;

    if(IS_GEN_BOTH_PATH)
    {
        CreateGenRawSrcOperand(src0);
        CreateGenRawSrcOperand(src1);
        CreateGenRawDstOperand(dst);
        G4_Predicate * g4Pred = (pred != NULL)? pred->g4opnd->asPredicate() : NULL;
        dst->g4opnd->asDstRegRegion()->setType(Type_UD);

        status = m_builder->translateVISARawSendsInst(g4Pred, executionSize,
            emask, modifiers, exMsgDesc->g4opnd, src0Size, src1Size, dstSize, desc->g4opnd, src0->g4opnd, src1->g4opnd, dst->g4opnd->asDstRegRegion(), ffid);
    }
    if(IS_VISA_BOTH_PATH)
    {
        VISA_INST_Desc *inst_desc = NULL;
        VISA_opnd *opnd[12]; // TODO: avoid hard-coding
        ISA_Opcode opcode = ISA_RAW_SENDS;
        int num_pred_desc_operands = 0;
        inst_desc = &CISA_INST_table[opcode];
        int num_operands = 0;

        //modifier
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, modifiers));

        num_pred_desc_operands = 2;
        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, inst_desc );

        //number of source register 0 to send
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, src0Size));
        //number of source register 1 to send
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, src1Size));
        //Number of destination registers expected returned
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, dstSize));
        //SFID
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, ffid));
        //exMsgDesc
        ADD_OPND(num_operands, opnd, exMsgDesc);
        //Message Descriptor
        ADD_OPND(num_operands, opnd, desc);
        //Source 0
        ADD_OPND(num_operands, opnd, src0);
        //Source 1
        ADD_OPND(num_operands, opnd, src1);
        //Destination
        ADD_OPND(num_operands, opnd, dst);

        CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        unsigned char size = executionSize;
        size += emask << 4;

        //pred id
        unsigned short pred_id = 0;
        if (pred != NULL)
            pred_id = pred->_opnd.v_opnd.opnd_val.pred_opnd.index;

        inst->createCisaInstruction(opcode, size, modifiers , pred_id, opnd, num_operands, inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISAMiscVME_FBR(VISA_StateOpndHandle *surface, VISA_RawOpnd *UNIInput, VISA_RawOpnd *FBRInput, VISA_VectorOpnd* FBRMbMode, VISA_VectorOpnd *FBRSubMbShape,
                                          VISA_VectorOpnd *FBRSubPredMode, VISA_RawOpnd *output)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;

    if(IS_GEN_BOTH_PATH)
    {
        CreateGenRawSrcOperand(UNIInput);
        CreateGenRawSrcOperand(FBRInput);
        CreateGenRawDstOperand(output);
        status = m_builder->translateVISAVmeFbrInst(surface->g4opnd, UNIInput->g4opnd, FBRInput->g4opnd,
            FBRMbMode->g4opnd, FBRSubMbShape->g4opnd, FBRSubPredMode->g4opnd, output->g4opnd->asDstRegRegion());
    }
    if(IS_VISA_BOTH_PATH)
    {
        VISA_INST_Desc *inst_desc = NULL;
        VISA_opnd *opnd[7];
        int num_pred_desc_operands = 0;
        ISA_Opcode opcode = ISA_VME_FBR;
        inst_desc = &CISA_INST_table[opcode];
        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, inst_desc );
        int num_operands = 0;

        //UNIinput
        ADD_OPND(num_operands, opnd, UNIInput);
        //fbr_input
        ADD_OPND(num_operands, opnd, FBRInput);
        //surface
        ADD_OPND(num_operands, opnd, surface);
        //FBRMbMode
        ADD_OPND(num_operands, opnd, FBRMbMode);
        //FBRSubMbShape
        ADD_OPND(num_operands, opnd, FBRSubMbShape);
        //FBRSubPredMode
        ADD_OPND(num_operands, opnd, FBRSubPredMode);
        //output
        ADD_OPND(num_operands, opnd, output);

        CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        inst->createCisaInstruction(opcode, EXEC_SIZE_1, 0 , 0,opnd, num_operands, inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISAMiscVME_IME(VISA_StateOpndHandle *surface, unsigned char streamMode, unsigned char searchControlMode, VISA_RawOpnd *UNIInput,
                                          VISA_RawOpnd *IMEInput, VISA_RawOpnd *ref0, VISA_RawOpnd *ref1, VISA_RawOpnd *costCenter, VISA_RawOpnd *output)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;

    if(IS_GEN_BOTH_PATH)
    {
        CreateGenRawSrcOperand(UNIInput);
        CreateGenRawSrcOperand(IMEInput);
        CreateGenRawSrcOperand(ref0);
        CreateGenRawSrcOperand(ref1);
        CreateGenRawSrcOperand(costCenter);
        CreateGenRawDstOperand(output);
        status = m_builder->translateVISAVmeImeInst(streamMode, searchControlMode, surface->g4opnd,
            UNIInput->g4opnd, IMEInput->g4opnd, ref0->g4opnd, ref1->g4opnd, costCenter->g4opnd, output->g4opnd->asDstRegRegion());
    }
    if(IS_VISA_BOTH_PATH)
    {
        VISA_INST_Desc *inst_desc = NULL;
        VISA_opnd *opnd[9];
        int num_pred_desc_operands = 0;
        ISA_Opcode opcode = ISA_VME_IME;
        inst_desc = &CISA_INST_table[opcode];
        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, inst_desc );
        int num_operands = 0;

        //streamMode
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, streamMode));
        //searchCtrl
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, searchControlMode));
        //input
        ADD_OPND(num_operands, opnd, UNIInput);
        //ime_input
        ADD_OPND(num_operands, opnd, IMEInput);
        //surface
        ADD_OPND(num_operands, opnd, surface);
        //ref0
        ADD_OPND(num_operands, opnd, ref0);
        //ref1
        ADD_OPND(num_operands, opnd, ref1);
        //CostCenter
        ADD_OPND(num_operands, opnd, costCenter);
        //output
        ADD_OPND(num_operands, opnd, output);

        CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        inst->createCisaInstruction(opcode, EXEC_SIZE_1, 0 , 0,opnd, num_operands, inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISAMiscVME_SIC(VISA_StateOpndHandle *surface, VISA_RawOpnd *UNIInput, VISA_RawOpnd *SICInput, VISA_RawOpnd *output)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;

    if(IS_GEN_BOTH_PATH)
    {
        CreateGenRawSrcOperand(UNIInput);
        CreateGenRawSrcOperand(SICInput);
        CreateGenRawDstOperand(output);
        status = m_builder->translateVISAVmeSicInst(surface->g4opnd, UNIInput->g4opnd, SICInput->g4opnd, output->g4opnd->asDstRegRegion());
    }
    if(IS_VISA_BOTH_PATH)
    {
        VISA_INST_Desc *inst_desc = NULL;
        VISA_opnd *opnd[4];
        int num_pred_desc_operands = 0;
        ISA_Opcode opcode = ISA_VME_SIC;
        inst_desc = &CISA_INST_table[opcode];
        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, inst_desc );
        int num_operands = 0;

        ADD_OPND(num_operands, opnd, UNIInput);
        ADD_OPND(num_operands, opnd, SICInput);
        ADD_OPND(num_operands, opnd, surface);
        ADD_OPND(num_operands, opnd, output);

        CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        inst->createCisaInstruction(opcode, EXEC_SIZE_1, 0 , 0,opnd, num_operands, inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}


int VISAKernelImpl::AppendVISAMiscVME_IDM(VISA_StateOpndHandle *surface, VISA_RawOpnd *UNIInput, VISA_RawOpnd *IDMInput, VISA_RawOpnd *output)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;

    if(IS_GEN_BOTH_PATH)
    {
        CreateGenRawSrcOperand(UNIInput);
        CreateGenRawSrcOperand(IDMInput);
        CreateGenRawDstOperand(output);
        status = m_builder->translateVISAVmeIdmInst(surface->g4opnd, UNIInput->g4opnd, IDMInput->g4opnd, output->g4opnd->asDstRegRegion());
    }
    if(IS_VISA_BOTH_PATH)
    {
        VISA_INST_Desc *inst_desc = NULL;
        VISA_opnd *opnd[4];
        int num_pred_desc_operands = 0;
        ISA_Opcode opcode = ISA_VME_SIC;
        inst_desc = &CISA_INST_table[opcode];
        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, inst_desc );
        int num_operands = 0;

        ADD_OPND(num_operands, opnd, UNIInput);
        ADD_OPND(num_operands, opnd, IDMInput);
        ADD_OPND(num_operands, opnd, surface);
        ADD_OPND(num_operands, opnd, output);

        CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        inst->createCisaInstruction(opcode, EXEC_SIZE_1, 0 , 0,opnd, num_operands, inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISAMEAVS(VISA_StateOpndHandle *surface,  VISA_StateOpndHandle *sampler,          VISAChannelMask _chMask,                VISA_VectorOpnd *uOffset,
                                    VISA_VectorOpnd *vOffset,       VISA_VectorOpnd *deltaU,                VISA_VectorOpnd *deltaV,                VISA_VectorOpnd *u2d,
                                    VISA_VectorOpnd *v2d,           VISA_VectorOpnd *groupID,               VISA_VectorOpnd *verticalBlockNumber,   OutputFormatControl cntrl,
                                    AVSExecMode execMode,           VISA_VectorOpnd *iefBypass,             VISA_RawOpnd *dst)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;
    ChannelMask chMask = ChannelMask::createFromAPI(_chMask);
    if(IS_GEN_BOTH_PATH)
    {
        CreateGenRawDstOperand(dst);
        unsigned numChannelsEnabled = 0;
        numChannelsEnabled = chMask.getNumEnabledChannels();

        status = m_builder->translateVISAAvsInst(surface->g4opnd, sampler->g4opnd, chMask, numChannelsEnabled,
            GET_G4_OPNG(deltaU), uOffset->g4opnd, GET_G4_OPNG(deltaV), GET_G4_OPNG(vOffset),
            GET_G4_OPNG(u2d), GET_G4_OPNG(groupID), GET_G4_OPNG(verticalBlockNumber), cntrl, GET_G4_OPNG(v2d),
            execMode, GET_G4_OPNG(iefBypass), dst->g4opnd->asDstRegRegion());
    }
    if(IS_VISA_BOTH_PATH)
    {
        VISA_INST_Desc *inst_desc = NULL;
        VISA_opnd *opnd[32];
        int num_pred_desc_operands = 0;
        ISA_Opcode opcode = ISA_AVS;
        inst_desc = &CISA_INST_table[opcode];
        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, inst_desc );
        int num_operands = 0;

        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, chMask.getBinary(ISA_AVS)));
        ADD_OPND(num_operands, opnd, sampler);
        ADD_OPND(num_operands, opnd, surface);
        ADD_OPND(num_operands, opnd, uOffset);
        ADD_OPND(num_operands, opnd, vOffset);
        ADD_OPND(num_operands, opnd, deltaU);
        ADD_OPND(num_operands, opnd, deltaV);
        ADD_OPND(num_operands, opnd, u2d);
        ADD_OPND(num_operands, opnd, groupID);
        ADD_OPND(num_operands, opnd, verticalBlockNumber);
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, cntrl));
        ADD_OPND(num_operands, opnd, v2d);
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, execMode));
        ADD_OPND(num_operands, opnd, iefBypass);
        ADD_OPND(num_operands, opnd, dst);

        CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        inst->createCisaInstruction(opcode, EXEC_SIZE_1, 0 , 0,opnd, num_operands, inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return CM_SUCCESS;
}
/************* END APPEND APIS ************************/
int VISAKernelImpl::AppendVISA3dSamplerMsgGeneric(ISA_Opcode opcode,
                                                  VISASampler3DSubOpCode subOpcode,
                                                  bool pixelNullMask,
                                                  bool cpsEnable,
                                                  bool uniformSampler,
                                                  VISA_PredOpnd * pred,
                                                  Common_VISA_EMask_Ctrl emask,
                                                  Common_ISA_Exec_Size executionSize,
                                                  ChannelMask srcChannel,
                                                  VISA_VectorOpnd *aoffimmi,
                                                  VISA_StateOpndHandle *sampler,
                                                  VISA_StateOpndHandle *surface,
                                                  VISA_RawOpnd *dst,
                                                  unsigned int numMsgSpecificOpnds,
                                                  VISA_RawOpnd **opndArray)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;
    bool isLoad = (subOpcode == VISA_3D_LD_MSC || subOpcode == VISA_3D_LD ||
        subOpcode == VISA_3D_LD2DMS_W || subOpcode == VISA_3D_LD_LZ);
    bool isSample4 = (  subOpcode == VISA_3D_GATHER4    ||
                        subOpcode == VISA_3D_GATHER4_C  ||
                        subOpcode == VISA_3D_GATHER4_PO ||
                        subOpcode == VISA_3D_GATHER4_PO_C );

    if(IS_GEN_BOTH_PATH)
    {
        CreateGenRawDstOperand(dst);
        G4_SrcRegRegion* g4params[32];

        for(unsigned int i = 0; i< numMsgSpecificOpnds; ++i)
        {
#if START_ASSERT_CHECK
            if(opndArray[i] == NULL)
            {
                CmAssert( 0 );
                return CM_FAILURE;
            }
#endif
            CreateGenRawSrcOperand(opndArray[i]);
            g4params[i] = opndArray[i]->g4opnd->asSrcRegRegion();
        }
        G4_Predicate * g4Pred = (pred != NULL)? pred->g4opnd->asPredicate() : NULL;

        if (isLoad)
        {
            status = m_builder->translateVISALoad3DInst(subOpcode, pixelNullMask,
                                                        g4Pred, executionSize,
                                                        emask, srcChannel,
                                                        aoffimmi->g4opnd, surface->g4opnd,
                                                        dst->g4opnd->asDstRegRegion(),
                                                        (uint8_t)numMsgSpecificOpnds,
                                                        g4params);
        }
        else if (isSample4)
        {
            status = m_builder->translateVISAGather3dInst(subOpcode, pixelNullMask,
                                                          g4Pred, executionSize,
                                                          emask, srcChannel,
                                                          aoffimmi->g4opnd, sampler->g4opnd,
                                                          surface->g4opnd,
                                                          dst->g4opnd->asDstRegRegion(),
                                                          numMsgSpecificOpnds, g4params);
        }
        else
        {
            status = m_builder->translateVISASampler3DInst(subOpcode, pixelNullMask,
                                                           cpsEnable, uniformSampler, g4Pred, executionSize,
                                                           emask, srcChannel,
                                                           aoffimmi->g4opnd, sampler->g4opnd,
                                                           surface->g4opnd,
                                                           dst->g4opnd->asDstRegRegion(),
                                                           numMsgSpecificOpnds, g4params);
        }
    }
    if(IS_VISA_BOTH_PATH)
    {
        VISA_INST_Desc *inst_desc = (VISA_INST_Desc*)m_mem.alloc(sizeof(VISA_INST_Desc));
        *inst_desc = CISA_INST_table[opcode];
        VISA_opnd *opnd[30];
        int num_pred_desc_operands = 0;
        int num_operands = 0;

        // subOP, pixel null mask and CPS LOD compensation enable.
        // Bit 0-4 : subOp
        // Bit 5   : pixelNullMask
        // Bit 6   : cpsEnable
        int value = subOpcode + (pixelNullMask ? 1 << 5 : 0)
                              + (cpsEnable ? 1 << 6 : 0);
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, value));

        num_pred_desc_operands = 2;
        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, inst_desc );

        uint8_t channelVal = isSample4 ? (uint8_t) srcChannel.convertToSrcChannel() : (uint8_t) srcChannel.getBinary(opcode);
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, channelVal));

        //aoffimmi
        ADD_OPND(num_operands, opnd, aoffimmi);

        //sampler
        if( opcode == ISA_3D_SAMPLE ||
            opcode == ISA_3D_GATHER4 )
        {
            ADD_OPND(num_operands, opnd, sampler);
        }

        //surface
        ADD_OPND(num_operands, opnd, surface);

        //dst
        ADD_OPND(num_operands, opnd, dst);
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, numMsgSpecificOpnds));

        CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        for(unsigned int i = 0; i < numMsgSpecificOpnds; i++)
        {
            if(opndArray[i] == NULL)
            {
                CmAssert( 0 );
                return CM_FAILURE;
            }
            ADD_OPND(num_operands, opnd, opndArray[i]);
        }


        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        unsigned char size = executionSize;
        size += emask << 4;

        //pred id
        unsigned short pred_id = 0;
        if (pred != NULL)
            pred_id = pred->_opnd.v_opnd.opnd_val.pred_opnd.index;

        inst_desc->opnd_num = num_pred_desc_operands + num_operands;

        inst->createCisaInstruction(opcode, size, 0, pred_id, opnd, num_operands, inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}
int VISAKernelImpl::AppendVISA3dSampler(VISASampler3DSubOpCode subOpcode,
                                        bool pixelNullMask,
                                        bool cpsEnable,
                                        bool uniformSampler,
                                        VISA_PredOpnd *pred,
                                        Common_VISA_EMask_Ctrl emask,
                                        Common_ISA_Exec_Size executionSize,
                                        VISAChannelMask srcChannel,
                                        VISA_VectorOpnd *aoffimmi,
                                        VISA_StateOpndHandle *sampler,
                                        VISA_StateOpndHandle *surface,
                                        VISA_RawOpnd *dst,
                                        int numMsgSpecificOpnds,
                                        VISA_RawOpnd **opndArray)
{
    ISA_Opcode opcode = ISA_3D_SAMPLE; // generate Gen IR for opndArray and dst in below func
    return this->AppendVISA3dSamplerMsgGeneric(opcode, subOpcode, pixelNullMask,
                                               cpsEnable, uniformSampler, pred, emask, executionSize,
                                               ChannelMask::createFromAPI(srcChannel),
                                               aoffimmi, sampler, surface, dst,
                                               numMsgSpecificOpnds, opndArray);
}

int VISAKernelImpl::AppendVISA3dLoad(VISASampler3DSubOpCode subOpcode,
                                     bool pixelNullMask,
                                     VISA_PredOpnd *pred,
                                     Common_VISA_EMask_Ctrl emask,
                                     Common_ISA_Exec_Size executionSize,
                                     VISAChannelMask srcChannel,
                                     VISA_VectorOpnd *aoffimmi,
                                     VISA_StateOpndHandle *surface,
                                     VISA_RawOpnd *dst,
                                     int numMsgSpecificOpnds,
                                     VISA_RawOpnd **opndArray)
{
    ISA_Opcode opcode = ISA_3D_LOAD; // generate Gen IR for opndArray and dst in below func
    return this->AppendVISA3dSamplerMsgGeneric(opcode, subOpcode, pixelNullMask,
                                               /*cpsEnable*/false, /*uniformSampler*/true, pred, emask,
                                               executionSize,
                                               ChannelMask::createFromAPI(srcChannel),
                                               aoffimmi, NULL, surface, dst,
                                               numMsgSpecificOpnds, opndArray);
}

int VISAKernelImpl::AppendVISA3dGather4(VISASampler3DSubOpCode subOpcode,
                                        bool pixelNullMask,
                                        VISA_PredOpnd *pred,
                                        Common_VISA_EMask_Ctrl emask,
                                        Common_ISA_Exec_Size executionSize,
                                        VISASourceSingleChannel srcChannel,
                                        VISA_VectorOpnd *aoffimmi,
                                        VISA_StateOpndHandle *sampler,
                                        VISA_StateOpndHandle *surface,
                                        VISA_RawOpnd *dst,
                                        int numMsgSpecificOpnds,
                                        VISA_RawOpnd **opndArray)
{
    ISA_Opcode opcode = ISA_3D_GATHER4; // generate Gen IR for opndArray and dst in below func
    return this->AppendVISA3dSamplerMsgGeneric(opcode, subOpcode, pixelNullMask,
                                               /*cpsEnable*/false, /*uniformSampler*/true,
                                               pred, emask, executionSize,
                                               ChannelMask::createFromSingleChannel(srcChannel),
                                               aoffimmi, sampler, surface, dst,
                                               numMsgSpecificOpnds, opndArray);
}

int VISAKernelImpl::AppendVISA3dInfo(VISASampler3DSubOpCode subOpcode, Common_VISA_EMask_Ctrl emask,
                                     Common_ISA_Exec_Size executionSize, VISAChannelMask srcChannels,
                                     VISA_StateOpndHandle *surface,
                                     VISA_RawOpnd *lod, VISA_RawOpnd *dst)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;
    ChannelMask channels = ChannelMask::createFromAPI(srcChannels);
    if(IS_GEN_BOTH_PATH)
    {
        CreateGenRawDstOperand(dst);
        G4_SrcRegRegion * lodg4 = NULL;
        if(subOpcode == VISA_3D_RESINFO)
        {
            CreateGenRawSrcOperand(lod);
            lodg4 = lod->g4opnd->asSrcRegRegion();
            status = m_builder->translateVISAResInfoInst(executionSize, emask, channels, surface->g4opnd, lodg4,
                dst->g4opnd->asDstRegRegion());
        }
        else
        {
            status = m_builder->translateVISASampleInfoInst(executionSize, emask, channels, surface->g4opnd,
                dst->g4opnd->asDstRegRegion());
        }
    }
    if(IS_VISA_BOTH_PATH)
    {
        if( subOpcode != VISA_3D_RESINFO && subOpcode != VISA_3D_SAMPLEINFO )
        {
            CmAssert( 0 );
            return CM_FAILURE;
        }

        ISA_Opcode opcode = ISA_3D_INFO;
        VISA_INST_Desc *inst_desc = (VISA_INST_Desc*)m_mem.alloc(sizeof(VISA_INST_Desc));
        *inst_desc = CISA_INST_table[opcode];
        VISA_opnd *opnd[30];
        int num_pred_desc_operands = 0;
        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, inst_desc );
        int num_operands = 0;

        //subOP
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, subOpcode));
        //channel
		ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, channels.getBinary(opcode)));

        ADD_OPND(num_operands, opnd, surface);
        if(subOpcode == VISA_3D_RESINFO)
        {
            ADD_OPND(num_operands, opnd, lod);
            //opnd_num used in binary emiter, so need to have correct value.
            inst_desc = (VISA_INST_Desc*)m_mem.alloc(sizeof(VISA_INST_Desc));
            *inst_desc = CISA_INST_table[opcode];
            inst_desc->opnd_num++;
        }
        ADD_OPND(num_operands, opnd, dst);

		CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        unsigned char size = executionSize;
        size += emask << 4;

        num_pred_desc_operands = 1;
        inst_desc->opnd_num = num_pred_desc_operands + num_operands;

        inst->createCisaInstruction(opcode, size, 0 , 0,opnd, num_operands, inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISA3dRTWrite(VISA_PredOpnd *pred, Common_VISA_EMask_Ctrl emask, Common_ISA_Exec_Size executionSize,
                                            VISA_VectorOpnd* renderTargetIndex, vISA_RT_CONTROLS cntrls,
                                            VISA_StateOpndHandle *surface, VISA_RawOpnd *r1Header,
                                            VISA_VectorOpnd *sampleIndex, uint8_t numMsgSpecificOpnds,
                                            VISA_RawOpnd **opndArray)
{
    return AppendVISA3dRTWriteCPS(pred, emask, executionSize, renderTargetIndex, cntrls, surface, r1Header, sampleIndex, NULL, numMsgSpecificOpnds, opndArray);
}
int VISAKernelImpl::AppendVISA3dRTWriteCPS(VISA_PredOpnd *pred, Common_VISA_EMask_Ctrl emask, Common_ISA_Exec_Size executionSize,
                                            VISA_VectorOpnd* renderTargetIndex, vISA_RT_CONTROLS cntrls,
                                            VISA_StateOpndHandle *surface, VISA_RawOpnd *r1Header,
                                            VISA_VectorOpnd *sampleIndex, VISA_VectorOpnd *cPSCounter,
                                            uint8_t numMsgSpecificOpnds, VISA_RawOpnd **opndArray)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;

    if(IS_GEN_BOTH_PATH)
    {
        G4_SrcRegRegion* g4params[32];

#if START_ASSERT_CHECK
        if(numMsgSpecificOpnds >= 32)
        {
            CmAssert( 0 );
            return CM_FAILURE;
        }
#endif
        for(unsigned int i = 0; i< numMsgSpecificOpnds; ++i)
        {
#if START_ASSERT_CHECK
            if(opndArray[i] == NULL)
            {
                CmAssert( 0 );
                return CM_FAILURE;
            }
#endif
            CreateGenRawSrcOperand(opndArray[i]);
            g4params[i] = opndArray[i]->g4opnd->asSrcRegRegion();
        }

#if START_ASSERT_CHECK
        if(cPSCounter && !cPSCounter->g4opnd)
        {
            CmAssert( 0 );
            return CM_FAILURE;
        }
#endif
        G4_SrcRegRegion *cPSCounterOpnd = (cPSCounter) ? cPSCounter->g4opnd->asSrcRegRegion(): NULL;
        G4_SrcRegRegion *sampleIndexOpnd = (cntrls.isSampleIndex) ? sampleIndex->g4opnd->asSrcRegRegion() : NULL;
        G4_Operand *renderTargetIndexOpnd = (cntrls.RTIndexPresent) ? renderTargetIndex->g4opnd : NULL;
        G4_SrcRegRegion *r1HeaderOpnd = NULL;

        if (r1Header)
        {
            CreateGenRawSrcOperand(r1Header);
            r1HeaderOpnd = r1Header->g4opnd->asSrcRegRegion();
        }

        G4_Predicate * g4Pred = (pred != NULL)? pred->g4opnd->asPredicate() : NULL;
        status = m_builder->translateVISARTWrite3DInst(g4Pred, executionSize, emask,
            surface->g4opnd, r1HeaderOpnd, renderTargetIndexOpnd, cntrls, sampleIndexOpnd, cPSCounterOpnd, numMsgSpecificOpnds, g4params);
    }
    if(IS_VISA_BOTH_PATH)
    {
        ISA_Opcode opcode = ISA_3D_RT_WRITE;
        VISA_INST_Desc *inst_desc = (VISA_INST_Desc*)m_mem.alloc(sizeof(VISA_INST_Desc));
        *inst_desc = CISA_INST_table[opcode];
        VISA_opnd *opnd[30];
        int num_pred_desc_operands = 2;
        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, inst_desc );
        int num_operands = 0;
        bool isCPSCounter = (cPSCounter)? true: false;

        int mode =  ((int)cntrls.isSampleIndex << 11)  |
                    ((int)cntrls.isCoarseMode   << 10)  |
                    ((int)cntrls.isPerSample    << 9)   |
                    ((int)(isCPSCounter)        << 8)   |
                    (((int)cntrls.isLastWrite   << 7)   |
                    ((int)cntrls.isStencil      << 6)   |
                    ((int)cntrls.zPresent       << 5)   |
                    ((int)cntrls.oMPresent      << 4)   |
                    ((int)cntrls.s0aPresent     << 3)   |
                    ((int)cntrls.RTIndexPresent << 2));

        //mode
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, mode));
        //surface
        ADD_OPND(num_operands, opnd, surface);

        //r1Header
        ADD_OPND(num_operands, opnd, r1Header);

        if (cntrls.isSampleIndex)
            ADD_OPND(num_operands, opnd, sampleIndex);

        if(cPSCounter)
            ADD_OPND(num_operands, opnd, cPSCounter);

        if (cntrls.RTIndexPresent)
            ADD_OPND(num_operands, opnd, renderTargetIndex);

        for(int i = 0; i < numMsgSpecificOpnds; i++, num_operands++)
        {
            if( opndArray[i] == NULL )
            {
                CmAssert(0);
                return CM_FAILURE;
            }
            opnd[num_operands] = opndArray[i];
        }

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        unsigned char size = executionSize;
        size += emask << 4;

        //pred id
        unsigned short pred_id = 0;
        if (pred != NULL)
            pred_id = pred->_opnd.v_opnd.opnd_val.pred_opnd.index;

        inst_desc->opnd_num = num_pred_desc_operands + num_operands;

        inst->createCisaInstruction(opcode, size, 0 , pred_id, opnd, num_operands, inst_desc);
        addInstructionToEnd(inst);
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    }
    return status;
}

int VISAKernelImpl::AppendVISA3dURBWrite(VISA_PredOpnd *pred, Common_VISA_EMask_Ctrl emask, Common_ISA_Exec_Size executionSize,
                                         unsigned char numberOutputParams, VISA_RawOpnd *channelMask,
                                         unsigned short globalOffset, VISA_RawOpnd *URBHandle,
                                         VISA_RawOpnd *perSlotOffset, VISA_RawOpnd *vertexData)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif

    int status = CM_SUCCESS;

    if(IS_GEN_BOTH_PATH)
    {
        CreateGenRawSrcOperand(channelMask);
        CreateGenRawSrcOperand(URBHandle);
        CreateGenRawSrcOperand(perSlotOffset);
        CreateGenRawSrcOperand(vertexData);
        G4_Predicate * g4Pred = (pred != NULL)? pred->g4opnd->asPredicate() : NULL;
        status = m_builder->translateVISAURBWrite3DInst(g4Pred, executionSize, emask,
            numberOutputParams, globalOffset, channelMask->g4opnd->asSrcRegRegion(), URBHandle->g4opnd->asSrcRegRegion(),
            perSlotOffset->g4opnd->asSrcRegRegion(), vertexData->g4opnd->asSrcRegRegion());
    }
    if(IS_VISA_BOTH_PATH)
    {
        ISA_Opcode opcode = ISA_3D_URB_WRITE;
        VISA_INST_Desc *inst_desc = (VISA_INST_Desc*)m_mem.alloc(sizeof(VISA_INST_Desc));
        *inst_desc = CISA_INST_table[opcode];
        VISA_opnd *opnd[30];
        int num_pred_desc_operands = 2;
        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, inst_desc );
        int num_operands = 0;

        //number output operands
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, numberOutputParams));
        //channel mask
        ADD_OPND(num_operands, opnd,  channelMask);
        //globalOffset
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, globalOffset));
        //urb handle
        ADD_OPND(num_operands, opnd, URBHandle);
        //per slot offset
        ADD_OPND(num_operands, opnd, perSlotOffset);
        //vertex data
        ADD_OPND(num_operands, opnd, vertexData);

        CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        unsigned char size = executionSize;
        size += emask << 4;

        //pred id
        unsigned short pred_id = 0;
        if (pred != NULL)
            pred_id = pred->_opnd.v_opnd.opnd_val.pred_opnd.index;

        inst_desc->opnd_num = num_pred_desc_operands + num_operands;

        inst->createCisaInstruction(opcode, size, 0 , pred_id,opnd, num_operands, inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISA3dTypedAtomic(
    VISAAtomicOps subOp, bool is16Bit, VISA_PredOpnd *pred,
    Common_VISA_EMask_Ctrl emask, Common_ISA_Exec_Size executionSize,
    VISA_StateOpndHandle *surface, VISA_RawOpnd *u, VISA_RawOpnd *v,
    VISA_RawOpnd *r, VISA_RawOpnd *lod, VISA_RawOpnd *src0, VISA_RawOpnd *src1,
    VISA_RawOpnd *dst)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif

        int status = CM_SUCCESS;

    if(IS_GEN_BOTH_PATH)
    {
        CreateGenRawSrcOperand(u);
        CreateGenRawSrcOperand(v);
        CreateGenRawSrcOperand(r);
        CreateGenRawSrcOperand(lod);
        CreateGenRawSrcOperand(src0);
        CreateGenRawSrcOperand(src1);
        CreateGenRawDstOperand(dst);
        G4_Predicate * g4Pred = (pred != nullptr) ? pred->g4opnd->asPredicate() : nullptr;
        status = m_builder->translateVISATypedAtomicInst(
            subOp, is16Bit, g4Pred, emask, executionSize, surface->g4opnd,
            u->g4opnd->asSrcRegRegion(), v->g4opnd->asSrcRegRegion(),
            r->g4opnd->asSrcRegRegion(), lod->g4opnd->asSrcRegRegion(),
            src0->g4opnd->asSrcRegRegion(), src1->g4opnd->asSrcRegRegion(),
            dst->g4opnd->asDstRegRegion());
    }

    if(IS_VISA_BOTH_PATH)
    {
        ISA_Opcode opcode = ISA_3D_TYPED_ATOMIC;
        VISA_INST_Desc *inst_desc = &CISA_INST_table[opcode];
        VISA_opnd *opnd[30];
        int num_pred_desc_operands = 0;
        int num_operands = 0;

        //number output operands
        uint8_t OpAnd16BitTag = uint8_t(subOp) | uint8_t((is16Bit ? 1 : 0) << 5);
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, OpAnd16BitTag));
        num_pred_desc_operands = 2;
        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, inst_desc );
        //surface
        ADD_OPND(num_operands, opnd, surface);
        //u
        ADD_OPND(num_operands, opnd, u);
        //v
        ADD_OPND(num_operands, opnd, v);
        //r
        ADD_OPND(num_operands, opnd, r);
        //lod
        ADD_OPND(num_operands, opnd, lod);
        //src0
        ADD_OPND(num_operands, opnd, src0);
        //src1
        ADD_OPND(num_operands, opnd, src1);
        //dst
        ADD_OPND(num_operands, opnd, dst);

        CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        unsigned char size = executionSize;
        size += emask << 4;

        //pred id
        unsigned short pred_id = 0;
        if (pred != NULL)
            pred_id = pred->_opnd.v_opnd.opnd_val.pred_opnd.index;

        inst_desc->opnd_num = num_pred_desc_operands + num_operands;

        inst->createCisaInstruction(opcode, size, 0 , pred_id,opnd, num_operands, inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return CM_SUCCESS;
}

int VISAKernelImpl::AppendVISAVABooleanCentroid(VISA_StateOpndHandle *surface, VISA_VectorOpnd * uOffset,
                                                VISA_VectorOpnd *vOffset, VISA_VectorOpnd *vSize, VISA_VectorOpnd *hSize, VISA_RawOpnd *dst)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;

    ISA_VA_Sub_Opcode subOp = BoolCentroid_FOPCODE;
    if(IS_GEN_BOTH_PATH)
    {
        CreateGenRawDstOperand(dst);
        G4_DstRegRegion *dstOpnd = dst->g4opnd->asDstRegRegion();
        status = m_builder->translateVISASamplerVAGenericInst(surface->g4opnd, NULL, uOffset->g4opnd,
            vOffset->g4opnd, vSize->g4opnd, hSize->g4opnd, NULL, 0, 0, subOp,
            dstOpnd, dstOpnd->getType(), 16 * G4_Type_Table[dstOpnd->getBase()->asRegVar()->getDeclare()->getElemType()].byteSize);
    }
    if(IS_VISA_BOTH_PATH)
    {
        ISA_Opcode opcode = ISA_VA;
        VISA_INST_Desc *inst_desc = &CISA_INST_table[opcode];
        VISA_opnd *opnd[30];
        int num_pred_desc_operands = 0;
        int num_operands = 0;

        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, subOp));
        ADD_OPND(num_operands, opnd, surface);
        ADD_OPND(num_operands, opnd, uOffset);
        ADD_OPND(num_operands, opnd, vOffset);
        ADD_OPND(num_operands, opnd, vSize);
        ADD_OPND(num_operands, opnd, hSize);
        ADD_OPND(num_operands, opnd, dst);

        //CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        unsigned char size = EXEC_SIZE_1;

        //pred id
        unsigned short pred_id = 0;
        inst->createCisaInstruction(opcode, size, 0 , pred_id,opnd, num_operands, inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISAVACentroid(VISA_StateOpndHandle *surface, VISA_VectorOpnd * uOffset,
                                         VISA_VectorOpnd *vOffset, VISA_VectorOpnd *vSize, VISA_RawOpnd *dst)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;

    ISA_VA_Sub_Opcode subOp = Centroid_FOPCODE;
    if(IS_GEN_BOTH_PATH)
    {
        CreateGenRawDstOperand(dst);
        G4_DstRegRegion *dstOpnd = dst->g4opnd->asDstRegRegion();
        status = m_builder->translateVISASamplerVAGenericInst(surface->g4opnd, NULL, uOffset->g4opnd,
            vOffset->g4opnd, vSize->g4opnd, NULL, NULL, 0, 0, subOp,
            dstOpnd, dstOpnd->getType(), 32 * G4_Type_Table[dstOpnd->getBase()->asRegVar()->getDeclare()->getElemType()].byteSize);
    }
    if(IS_VISA_BOTH_PATH)
    {
        ISA_Opcode opcode = ISA_VA;
        VISA_INST_Desc *inst_desc = &CISA_INST_table[opcode];
        VISA_opnd *opnd[30];
        int num_pred_desc_operands = 0;
        int num_operands = 0;

        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, subOp));
        ADD_OPND(num_operands, opnd, surface);
        ADD_OPND(num_operands, opnd, uOffset);
        ADD_OPND(num_operands, opnd, vOffset);
        ADD_OPND(num_operands, opnd, vSize);
        ADD_OPND(num_operands, opnd, dst);

        //CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        unsigned char size = EXEC_SIZE_1;

        //pred id
        unsigned short pred_id = 0;
        inst->createCisaInstruction(opcode, size, 0 , pred_id,opnd, num_operands, inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISAVAConvolve(VISA_StateOpndHandle *sampler, VISA_StateOpndHandle *surface, VISA_VectorOpnd * uOffset,
                                         VISA_VectorOpnd *vOffset, CONVExecMode execMode, bool isBigKernel, VISA_RawOpnd *dst)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;

    ISA_VA_Sub_Opcode subOp = Convolve_FOPCODE;
    if(IS_GEN_BOTH_PATH)
    {
        CreateGenRawDstOperand(dst);
        G4_DstRegRegion *dstOpnd = dst->g4opnd->asDstRegRegion();
        unsigned int dstSize = conv_exec_mode_size[execMode] * G4_Type_Table[dstOpnd->getBase()->asRegVar()->getDeclare()->getElemType()].byteSize;
        status = m_builder->translateVISASamplerVAGenericInst(surface->g4opnd, sampler->g4opnd, uOffset->g4opnd,
            vOffset->g4opnd, NULL, NULL, NULL, 0, execMode, subOp,
            dstOpnd, dstOpnd->getType(), dstSize, isBigKernel);
    }
    if(IS_VISA_BOTH_PATH)
    {
        ISA_Opcode opcode = ISA_VA;
        VISA_INST_Desc *inst_desc = &CISA_INST_table[opcode];
        VISA_opnd *opnd[30];
        int num_pred_desc_operands = 0;
        int num_operands = 0;
        uint8_t properties = execMode;
        properties = properties | (isBigKernel << 4);
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, subOp));
        ADD_OPND(num_operands, opnd, sampler);
        ADD_OPND(num_operands, opnd, surface);
        ADD_OPND(num_operands, opnd, uOffset);
        ADD_OPND(num_operands, opnd, vOffset);
        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, inst_desc );
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, properties, true, subOp));
        ADD_OPND(num_operands, opnd, dst);

        //CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        unsigned char size = EXEC_SIZE_1;

        //pred id
        unsigned short pred_id = 0;
        inst->createCisaInstruction(opcode, size, 0 , pred_id,opnd, num_operands, inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISAVAErodeDilate(EDMode mode, VISA_StateOpndHandle *sampler, VISA_StateOpndHandle *surface, VISA_VectorOpnd * uOffset,
                                            VISA_VectorOpnd *vOffset, EDExecMode execMode, VISA_RawOpnd *dst)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;

    ISA_VA_Sub_Opcode subOp = ERODE_FOPCODE;

    if(mode == CM_DILATE)
    {
        subOp = Dilate_FOPCODE;
    }

    if(IS_GEN_BOTH_PATH)
    {
        CreateGenRawDstOperand(dst);
        G4_DstRegRegion *dstOpnd = dst->g4opnd->asDstRegRegion();
        unsigned int dstSize = ed_exec_mode_byte_size[execMode];
        status = m_builder->translateVISASamplerVAGenericInst(surface->g4opnd, sampler->g4opnd, uOffset->g4opnd,
            vOffset->g4opnd, NULL, NULL, NULL, 0, execMode, subOp,
            dstOpnd, dstOpnd->getType(), dstSize, false);
    }
    if(IS_VISA_BOTH_PATH)
    {
        ISA_Opcode opcode = ISA_VA;
        VISA_INST_Desc *inst_desc = &CISA_INST_table[opcode];
        VISA_opnd *opnd[30];
        int num_pred_desc_operands = 0;
        int num_operands = 0;

        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, subOp));
        ADD_OPND(num_operands, opnd, sampler);
        ADD_OPND(num_operands, opnd, surface);
        ADD_OPND(num_operands, opnd, uOffset);
        ADD_OPND(num_operands, opnd, vOffset);
        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, inst_desc );
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, execMode, true, subOp));
        ADD_OPND(num_operands, opnd, dst);

        //CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        unsigned char size = EXEC_SIZE_1;

        //pred id
        unsigned short pred_id = 0;
        inst->createCisaInstruction(opcode, size, 0 , pred_id,opnd, num_operands, inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISAVAMinMax(VISA_StateOpndHandle *surface, VISA_VectorOpnd * uOffset,
                                       VISA_VectorOpnd *vOffset, VISA_VectorOpnd *mmMode, VISA_RawOpnd *dst)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;

    ISA_VA_Sub_Opcode subOp = MINMAX_FOPCODE;

    if(IS_GEN_BOTH_PATH)
    {
        CreateGenRawDstOperand(dst);
        G4_DstRegRegion *dstOpnd = dst->g4opnd->asDstRegRegion();
        status = m_builder->translateVISASamplerVAGenericInst(surface->g4opnd, NULL, uOffset->g4opnd,
            vOffset->g4opnd, NULL, NULL, mmMode->g4opnd, 0, 0, subOp,
            dstOpnd, dstOpnd->getType(), 32, false);
    }
    if(IS_VISA_BOTH_PATH)
    {
        ISA_Opcode opcode = ISA_VA;
        VISA_INST_Desc *inst_desc = &CISA_INST_table[opcode];
        VISA_opnd *opnd[30];
        int num_pred_desc_operands = 0;
        int num_operands = 0;

        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, inst_desc );
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, subOp));
        ADD_OPND(num_operands, opnd, surface);
        ADD_OPND(num_operands, opnd, uOffset);
        ADD_OPND(num_operands, opnd, vOffset);
        ADD_OPND(num_operands, opnd, mmMode);
        ADD_OPND(num_operands, opnd, dst);

        //CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        unsigned char size = EXEC_SIZE_1;

        //pred id
        unsigned short pred_id = 0;
        inst->createCisaInstruction(opcode, size, 0 , pred_id,opnd, num_operands, inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISAVAMinMaxFilter(VISA_StateOpndHandle *sampler, VISA_StateOpndHandle *surface, VISA_VectorOpnd * uOffset,
                                             VISA_VectorOpnd *vOffset, OutputFormatControl cntrl, MMFExecMode execMode, VISA_VectorOpnd *mmfMode, VISA_RawOpnd *dst)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;
    ISA_VA_Sub_Opcode subOp = MINMAXFILTER_FOPCODE;

    if(cntrl != CM_16_FULL && cntrl != CM_8_FULL)
    {
        CmAssert(0);
        return CM_FAILURE;
    }

    if(IS_GEN_BOTH_PATH)
    {
        CreateGenRawDstOperand(dst);
        G4_DstRegRegion *dstOpnd = dst->g4opnd->asDstRegRegion();
        unsigned dstSize = (CM_MMF_1x1 == execMode) ? 4 : ( mmf_exec_mode_size[execMode] * format_control_byteSize2[cntrl] ) ;
        status = m_builder->translateVISASamplerVAGenericInst(surface->g4opnd, sampler->g4opnd, uOffset->g4opnd,
            vOffset->g4opnd, NULL, NULL, mmfMode->g4opnd, cntrl, execMode, subOp,
            dstOpnd, dstOpnd->getType(), dstSize);
    }
    if(IS_VISA_BOTH_PATH)
    {
        ISA_Opcode opcode = ISA_VA;
        VISA_INST_Desc *inst_desc = &CISA_INST_table[opcode];
        VISA_opnd *opnd[30];
        int num_pred_desc_operands = 0;
        int num_operands = 0;

        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, subOp));
        ADD_OPND(num_operands, opnd, sampler);
        ADD_OPND(num_operands, opnd, surface);
        ADD_OPND(num_operands, opnd, uOffset);
        ADD_OPND(num_operands, opnd, vOffset);
        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, inst_desc );
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, cntrl, true, subOp));
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, inst_desc, execMode, true, subOp));
        ADD_OPND(num_operands, opnd, mmfMode);
        ADD_OPND(num_operands, opnd, dst);

        //CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        unsigned char size = EXEC_SIZE_1;

        //pred id
        unsigned short pred_id = 0;
        inst->createCisaInstruction(opcode, size, 0 , pred_id,opnd, num_operands, inst_desc);
        addInstructionToEnd(inst);
    }
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISAVACorrelationSearch(VISA_StateOpndHandle *surface, VISA_VectorOpnd * uOffset,
                                                  VISA_VectorOpnd *vOffset, VISA_VectorOpnd *vOrigin, VISA_VectorOpnd *hOrigin,
                                                  VISA_VectorOpnd *xDirectionSize, VISA_VectorOpnd *yDirectionSize,
                                                  VISA_VectorOpnd *xDirectionSearchSize, VISA_VectorOpnd *yDirectionSearchSize,
                                                  VISA_RawOpnd *dst)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;
    ISA_VA_Sub_Opcode subOp = VA_OP_CODE_CORRELATION_SEARCH;

    if(IS_GEN_BOTH_PATH)
    {
        CreateGenRawDstOperand(dst);
        G4_DstRegRegion *dstOpnd = dst->g4opnd->asDstRegRegion();

        G4_Declare* dstDcl = dstOpnd->getBase()->asRegVar()->getDeclare();
        G4_Type dstType = dstDcl->getElemType();
        unsigned int dstSize = dstDcl->getNumElems() * dstDcl->getNumRows() * G4_Type_Table[dstType].byteSize;

        uint8_t execMode = 0;
        uint8_t functionality = 0x3; /*reserved*/
        status = m_builder->translateVISAVaSklPlusGeneralInst(
                        subOp, surface->g4opnd, NULL /*sampler*/, execMode, functionality,
                        //rest
                        uOffset->g4opnd              , vOffset->g4opnd  ,

                        //1pixel convolve
                        NULL /*offsetOpnd*/,

                        //FloodFill
                        NULL /*loopCountOpnd*/          , NULL /*pixelhMasOpnd*/,
                        NULL /*pixelVMaskLeftOpnd*/     , NULL /*pixelVMaskRightOpnd*/,

                        //LBP Correlation
                        NULL /*disparityOpnd*/          ,

                        //correlation search
                        vOrigin->g4opnd          , hOrigin->g4opnd  ,
                        xDirectionSize->g4opnd        , yDirectionSize->g4opnd   ,
                        xDirectionSearchSize->g4opnd , yDirectionSearchSize->g4opnd ,

                        //general
                        dstOpnd, dstType, dstSize,

                        //hdc
                        0 /*pixelSize*/                 , NULL /*dstSurfaceOpnd*/,
                        NULL  /*dstXOffOnd*/            , NULL /*dstYOffOpnd*/,
                        false);
    }
    if(IS_VISA_BOTH_PATH)
    {
        ISA_Opcode opcode = ISA_VA_SKL_PLUS;
        VISA_INST_Desc *instDesc = &CISA_INST_table[opcode];
        VISA_opnd *opnd[30];
        int num_pred_desc_operands = 0;
        int num_operands = 0;

        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, instDesc );
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, instDesc, subOp));
        ADD_OPND(num_operands, opnd, surface);
        ADD_OPND(num_operands, opnd, uOffset);
        ADD_OPND(num_operands, opnd, vOffset);
        ADD_OPND(num_operands, opnd, vOrigin);
        ADD_OPND(num_operands, opnd, hOrigin);
        ADD_OPND(num_operands, opnd, xDirectionSize);
        ADD_OPND(num_operands, opnd, yDirectionSize);
        ADD_OPND(num_operands, opnd, xDirectionSearchSize);
        ADD_OPND(num_operands, opnd, yDirectionSearchSize);
        ADD_OPND(num_operands, opnd, dst);

        //CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        unsigned char size = EXEC_SIZE_1;

        //pred id
        unsigned short pred_id = 0;
        inst->createCisaInstruction(opcode, size, 0 , pred_id,opnd, num_operands, instDesc);
        addInstructionToEnd(inst);
    }

#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISAVAFloodFill(bool is8Connect, VISA_RawOpnd *pixelMaskHDirection,
                                                            VISA_VectorOpnd *pixelMaskVDirectionLeft, VISA_VectorOpnd *pixelMaskVDirectionRight,
                                                            VISA_VectorOpnd *loopCount, VISA_RawOpnd *dst)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;
    ISA_VA_Sub_Opcode subOp = VA_OP_CODE_FLOOD_FILL;

    if(IS_GEN_BOTH_PATH)
    {
        CreateGenRawSrcOperand(pixelMaskHDirection);
        CreateGenRawDstOperand(dst);
        G4_DstRegRegion *dstOpnd = dst->g4opnd->asDstRegRegion();

        G4_Declare* dstDcl = dstOpnd->getBase()->asRegVar()->getDeclare();
        G4_Type dstType = dstDcl->getElemType();
        /*should be UW*/
        unsigned int dstSize = 8 * G4_Type_Table[dstType].byteSize;

        uint8_t execMode = is8Connect;
        uint8_t functionality = 0x3; /*reserved*/
        status = m_builder->translateVISAVaSklPlusGeneralInst(
                        subOp, NULL /*surface*/, NULL /*sampler*/, execMode, functionality,
                        //rest
                        NULL /*uOffset*/              , NULL /*vOffset*/  ,

                        //1pixel convolve
                        NULL /*offsetOpnd*/,

                        //FloodFill
                        loopCount->g4opnd /*loopCountOpnd*/          , pixelMaskHDirection->g4opnd /*pixelhMasOpnd*/,
                        pixelMaskVDirectionLeft->g4opnd /*pixelVMaskLeftOpnd*/     , pixelMaskVDirectionRight->g4opnd /*pixelVMaskRightOpnd*/,

                        //LBP Correlation
                        NULL /*disparityOpnd*/          ,

                        //correlation search
                        NULL        ,   NULL  ,
                        NULL        ,   NULL   ,
                        NULL        ,   NULL ,

                        //general
                        dstOpnd, dstType, dstSize,

                        //hdc
                        0 /*pixelSize*/                 , NULL /*dstSurfaceOpnd*/,
                        NULL  /*dstXOffOnd*/            , NULL /*dstYOffOpnd*/,
                        false);
    }
    if(IS_VISA_BOTH_PATH)
    {
        ISA_Opcode opcode = ISA_VA_SKL_PLUS;
        VISA_INST_Desc *instDesc = &CISA_INST_table[opcode];
        VISA_opnd *opnd[30];
        int num_pred_desc_operands = 0;
        int num_operands = 0;

        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, instDesc );
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, instDesc, subOp));
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, instDesc, is8Connect, true, subOp));
        ADD_OPND(num_operands, opnd, pixelMaskHDirection);
        ADD_OPND(num_operands, opnd, pixelMaskVDirectionLeft);
        ADD_OPND(num_operands, opnd, pixelMaskVDirectionRight);
        ADD_OPND(num_operands, opnd, loopCount);
        ADD_OPND(num_operands, opnd, dst);

        //CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        unsigned char size = EXEC_SIZE_1;

        //pred id
        unsigned short pred_id = 0;
        inst->createCisaInstruction(opcode, size, 0 , pred_id,opnd, num_operands, instDesc);
        addInstructionToEnd(inst);
    }

#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISAVALBPCorrelation(VISA_StateOpndHandle *surface, VISA_VectorOpnd * uOffset,
                                                            VISA_VectorOpnd *vOffset, VISA_VectorOpnd *disparity,
                                                            VISA_RawOpnd *dst)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;
    ISA_VA_Sub_Opcode subOp = VA_OP_CODE_LBP_CORRELATION;

    if(IS_GEN_BOTH_PATH)
    {
        uint8_t execMode = 0;
        uint8_t functionality = 0x3; /*reserved*/

        CreateGenRawDstOperand(dst);
        G4_DstRegRegion *dstOpnd = dst->g4opnd->asDstRegRegion();

        G4_Declare* dstDcl = dstOpnd->getBase()->asRegVar()->getDeclare();
        G4_Type dstType = dstDcl->getElemType();
        /*should be UB*/
        unsigned int dstSize = lbp_correlation_mode_size[execMode]* G4_Type_Table[dstType].byteSize;


        status = m_builder->translateVISAVaSklPlusGeneralInst(
                        subOp, surface->g4opnd /*surface*/, NULL /*sampler*/, execMode, functionality,
                        //rest
                        uOffset->g4opnd /*uOffset*/              , vOffset->g4opnd /*vOffset*/  ,

                        //1pixel convolve
                        NULL /*offsetOpnd*/,

                        //FloodFill
                        NULL /*loopCountOpnd*/          , NULL /*pixelhMasOpnd*/,
                        NULL /*pixelVMaskLeftOpnd*/     , NULL /*pixelVMaskRightOpnd*/,

                        //LBP Correlation
                        disparity->g4opnd /*disparityOpnd*/          ,

                        //correlation search
                        NULL        ,   NULL  ,
                        NULL        ,   NULL   ,
                        NULL        ,   NULL ,

                        //general
                        dstOpnd, dstType, dstSize,

                        //hdc
                        0 /*pixelSize*/                 , NULL /*dstSurfaceOpnd*/,
                        NULL  /*dstXOffOnd*/            , NULL /*dstYOffOpnd*/,
                        false);
    }
    if(IS_VISA_BOTH_PATH)
    {
        ISA_Opcode opcode = ISA_VA_SKL_PLUS;
        VISA_INST_Desc *instDesc = &CISA_INST_table[opcode];
        VISA_opnd *opnd[30];
        int num_pred_desc_operands = 0;
        int num_operands = 0;

        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, instDesc );
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, instDesc, subOp));
        ADD_OPND(num_operands, opnd, surface);
        ADD_OPND(num_operands, opnd, uOffset);
        ADD_OPND(num_operands, opnd, vOffset);
        ADD_OPND(num_operands, opnd, disparity);
        ADD_OPND(num_operands, opnd, dst);

        //CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        unsigned char size = EXEC_SIZE_1;

        //pred id
        unsigned short pred_id = 0;
        inst->createCisaInstruction(opcode, size, 0 , pred_id,opnd, num_operands, instDesc);
        addInstructionToEnd(inst);
    }

#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISAVALBPCreation(VISA_StateOpndHandle *surface, VISA_VectorOpnd * uOffset,
                                                            VISA_VectorOpnd *vOffset, LBPCreationMode mode,
                                                            VISA_RawOpnd *dst)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;
    ISA_VA_Sub_Opcode subOp = VA_OP_CODE_LBP_CREATION;

    if(IS_GEN_BOTH_PATH)
    {
        uint8_t execMode = 0;
        uint8_t functionality = mode; /*reserved*/

        CreateGenRawDstOperand(dst);
        G4_DstRegRegion *dstOpnd = dst->g4opnd->asDstRegRegion();

        G4_Declare* dstDcl = dstOpnd->getBase()->asRegVar()->getDeclare();
        G4_Type dstType = dstDcl->getElemType();
        /*should be UB*/
        unsigned int dstSize = lbp_creation_exec_mode_size[functionality]* G4_Type_Table[dstType].byteSize;


        status = m_builder->translateVISAVaSklPlusGeneralInst(
                        subOp, surface->g4opnd /*surface*/, NULL /*sampler*/, execMode, functionality,
                        //rest
                        uOffset->g4opnd /*uOffset*/              , vOffset->g4opnd /*vOffset*/  ,

                        //1pixel convolve
                        NULL /*offsetOpnd*/,

                        //FloodFill
                        NULL /*loopCountOpnd*/          , NULL /*pixelhMasOpnd*/,
                        NULL /*pixelVMaskLeftOpnd*/     , NULL /*pixelVMaskRightOpnd*/,

                        //LBP Correlation
                        NULL /*disparityOpnd*/          ,

                        //correlation search
                        NULL        ,   NULL  ,
                        NULL        ,   NULL   ,
                        NULL        ,   NULL ,

                        //general
                        dstOpnd, dstType, dstSize,

                        //hdc
                        0 /*pixelSize*/                 , NULL /*dstSurfaceOpnd*/,
                        NULL  /*dstXOffOnd*/            , NULL /*dstYOffOpnd*/,
                        false);
    }
    if(IS_VISA_BOTH_PATH)
    {
        ISA_Opcode opcode = ISA_VA_SKL_PLUS;
        VISA_INST_Desc *instDesc = &CISA_INST_table[opcode];
        VISA_opnd *opnd[30];
        int num_pred_desc_operands = 0;
        int num_operands = 0;

        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, instDesc );
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, instDesc, subOp));
        ADD_OPND(num_operands, opnd, surface);
        ADD_OPND(num_operands, opnd, uOffset);
        ADD_OPND(num_operands, opnd, vOffset);
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, instDesc, mode, true, subOp));
        ADD_OPND(num_operands, opnd, dst);

        //CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        unsigned char size = EXEC_SIZE_1;

        //pred id
        unsigned short pred_id = 0;
        inst->createCisaInstruction(opcode, size, 0 , pred_id,opnd, num_operands, instDesc);
        addInstructionToEnd(inst);
    }

#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISAVAConvolve1D(VISA_StateOpndHandle *sampler, VISA_StateOpndHandle *surface, VISA_VectorOpnd * uOffset,
                                                            VISA_VectorOpnd *vOffset, CONVExecMode mode, Convovle1DDirection direction, VISA_RawOpnd *dst)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;
    ISA_VA_Sub_Opcode subOp = VA_OP_CODE_1D_CONVOLVE_VERTICAL;

    if(direction == CM_H_DIRECTION)
        subOp = VA_OP_CODE_1D_CONVOLVE_HORIZONTAL;

    if(IS_GEN_BOTH_PATH)
    {
        uint8_t execMode = mode;
        uint8_t functionality = 0x3; /*reserved*/

        CreateGenRawDstOperand(dst);
        G4_DstRegRegion *dstOpnd = dst->g4opnd->asDstRegRegion();

        G4_Declare* dstDcl = dstOpnd->getBase()->asRegVar()->getDeclare();
        G4_Type dstType = dstDcl->getElemType();
        /*should be W*/
        unsigned int dstSize = conv_exec_mode_size[execMode]* G4_Type_Table[dstType].byteSize;


        status = m_builder->translateVISAVaSklPlusGeneralInst(
                        subOp, surface->g4opnd /*surface*/, sampler->g4opnd /*sampler*/, execMode, functionality,
                        //rest
                        uOffset->g4opnd /*uOffset*/              , vOffset->g4opnd /*vOffset*/  ,

                        //1pixel convolve
                        NULL /*offsetOpnd*/,

                        //FloodFill
                        NULL /*loopCountOpnd*/          , NULL /*pixelhMasOpnd*/,
                        NULL /*pixelVMaskLeftOpnd*/     , NULL /*pixelVMaskRightOpnd*/,

                        //LBP Correlation
                        NULL /*disparityOpnd*/          ,

                        //correlation search
                        NULL        ,   NULL  ,
                        NULL        ,   NULL   ,
                        NULL        ,   NULL ,

                        //general
                        dstOpnd, dstType, dstSize,

                        //hdc
                        0 /*pixelSize*/                 , NULL /*dstSurfaceOpnd*/,
                        NULL  /*dstXOffOnd*/            , NULL /*dstYOffOpnd*/,
                        false);
    }
    if(IS_VISA_BOTH_PATH)
    {
        ISA_Opcode opcode = ISA_VA_SKL_PLUS;
        VISA_INST_Desc *instDesc = &CISA_INST_table[opcode];
        VISA_opnd *opnd[30];
        int num_pred_desc_operands = 0;
        int num_operands = 0;

        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, instDesc );
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, instDesc, subOp));
        ADD_OPND(num_operands, opnd, sampler);
        ADD_OPND(num_operands, opnd, surface);
        ADD_OPND(num_operands, opnd, uOffset);
        ADD_OPND(num_operands, opnd, vOffset);
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, instDesc, mode, true, subOp));
        ADD_OPND(num_operands, opnd, dst);

        //CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        unsigned char size = EXEC_SIZE_1;

        //pred id
        unsigned short pred_id = 0;
        inst->createCisaInstruction(opcode, size, 0 , pred_id,opnd, num_operands, instDesc);
        addInstructionToEnd(inst);
    }

#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISAVAConvolve1Pixel(VISA_StateOpndHandle *sampler, VISA_StateOpndHandle *surface, VISA_VectorOpnd * uOffset,
                                                            VISA_VectorOpnd *vOffset, CONV1PixelExecMode mode, VISA_RawOpnd *offsets, VISA_RawOpnd *dst)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;
    ISA_VA_Sub_Opcode subOp = VA_OP_CODE_1PIXEL_CONVOLVE;

    if(IS_GEN_BOTH_PATH)
    {
        uint8_t execMode = mode;
        uint8_t functionality = 0x3; /*reserved*/

        CreateGenRawSrcOperand(offsets);
        CreateGenRawDstOperand(dst);
        G4_DstRegRegion *dstOpnd = dst->g4opnd->asDstRegRegion();

        G4_Declare* dstDcl = dstOpnd->getBase()->asRegVar()->getDeclare();
        G4_Type dstType = dstDcl->getElemType();
        /*should be W*/
        unsigned int dstSize = conv_exec_mode_size[execMode]* G4_Type_Table[dstType].byteSize;


        status = m_builder->translateVISAVaSklPlusGeneralInst(
                        subOp, surface->g4opnd /*surface*/, sampler->g4opnd /*sampler*/, execMode, functionality,
                        //rest
                        uOffset->g4opnd /*uOffset*/              , vOffset->g4opnd /*vOffset*/  ,

                        //1pixel convolve
                        offsets->g4opnd /*offsetOpnd*/,

                        //FloodFill
                        NULL /*loopCountOpnd*/          , NULL /*pixelhMasOpnd*/,
                        NULL /*pixelVMaskLeftOpnd*/     , NULL /*pixelVMaskRightOpnd*/,

                        //LBP Correlation
                        NULL /*disparityOpnd*/          ,

                        //correlation search
                        NULL        ,   NULL  ,
                        NULL        ,   NULL   ,
                        NULL        ,   NULL ,

                        //general
                        dstOpnd, dstType, dstSize,

                        //hdc
                        0 /*pixelSize*/                 , NULL /*dstSurfaceOpnd*/,
                        NULL  /*dstXOffOnd*/            , NULL /*dstYOffOpnd*/,
                        false);
    }
    if(IS_VISA_BOTH_PATH)
    {
        ISA_Opcode opcode = ISA_VA_SKL_PLUS;
        VISA_INST_Desc *instDesc = &CISA_INST_table[opcode];
        VISA_opnd *opnd[30];
        int num_pred_desc_operands = 0;
        int num_operands = 0;

        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, instDesc );
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, instDesc, subOp));
        ADD_OPND(num_operands, opnd, sampler);
        ADD_OPND(num_operands, opnd, surface);
        ADD_OPND(num_operands, opnd, uOffset);
        ADD_OPND(num_operands, opnd, vOffset);
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, instDesc, mode, true, subOp));
        ADD_OPND(num_operands, opnd, offsets);
        ADD_OPND(num_operands, opnd, dst);

        //CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        unsigned char size = EXEC_SIZE_1;

        //pred id
        unsigned short pred_id = 0;
        inst->createCisaInstruction(opcode, size, 0 , pred_id,opnd, num_operands, instDesc);
        addInstructionToEnd(inst);
    }

#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISAVAHDCConvolve(VISA_StateOpndHandle *sampler, VISA_StateOpndHandle *surface, VISA_VectorOpnd * uOffset,
                                                            VISA_VectorOpnd *vOffset, HDCReturnFormat returnFormat, CONVHDCRegionSize regionSize,
                                                            VISA_StateOpndHandle *dstSurface, VISA_VectorOpnd *xOffset, VISA_VectorOpnd *yOffset)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;
    ISA_VA_Sub_Opcode subOp = ISA_HDC_CONV;

    if(IS_GEN_BOTH_PATH)
    {
        uint8_t execMode = CM_CONV_16x4;
        uint8_t functionality = regionSize; /*reserved*/
        uint8_t pixelSize = returnFormat;

        status = m_builder->translateVISAVaSklPlusGeneralInst(
                        subOp, surface->g4opnd /*surface*/, sampler->g4opnd /*sampler*/, execMode, functionality,
                        //rest
                        uOffset->g4opnd /*uOffset*/              , vOffset->g4opnd /*vOffset*/  ,

                        //1pixel convolve
                        NULL /*offsetOpnd*/,

                        //FloodFill
                        NULL /*loopCountOpnd*/          , NULL /*pixelhMasOpnd*/,
                        NULL /*pixelVMaskLeftOpnd*/     , NULL /*pixelVMaskRightOpnd*/,

                        //LBP Correlation
                        NULL /*disparityOpnd*/          ,

                        //correlation search
                        NULL        ,   NULL  ,
                        NULL        ,   NULL   ,
                        NULL        ,   NULL ,

                        //general
                        NULL, Type_UNDEF, 0,

                        //hdc
                        pixelSize /*pixelSize*/                 , dstSurface->g4opnd /*dstSurfaceOpnd*/,
                        xOffset->g4opnd  /*dstXOffOnd*/            , yOffset->g4opnd /*dstYOffOpnd*/,
                        true);
    }
    if(IS_VISA_BOTH_PATH)
    {
        ISA_Opcode opcode = ISA_VA_SKL_PLUS;
        VISA_INST_Desc *instDesc = &CISA_INST_table[opcode];
        VISA_opnd *opnd[30];
        int num_pred_desc_operands = 0;
        int num_operands = 0;
        uint8_t properties = returnFormat;
        properties = properties | (regionSize << 4);
        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, instDesc );
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, instDesc, subOp));
        ADD_OPND(num_operands, opnd, sampler);
        ADD_OPND(num_operands, opnd, surface);
        ADD_OPND(num_operands, opnd, uOffset);
        ADD_OPND(num_operands, opnd, vOffset);
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, instDesc, properties, true, subOp));
        ADD_OPND(num_operands, opnd, dstSurface);
        ADD_OPND(num_operands, opnd, xOffset);
        ADD_OPND(num_operands, opnd, yOffset);

        //CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        unsigned char size = EXEC_SIZE_1;

        //pred id
        unsigned short pred_id = 0;
        inst->createCisaInstruction(opcode, size, 0 , pred_id,opnd, num_operands, instDesc);
        addInstructionToEnd(inst);
    }

#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISAVAHDCErodeDilate(EDMode subOpED, VISA_StateOpndHandle *sampler, VISA_StateOpndHandle *surface, VISA_VectorOpnd * uOffset,
                                                            VISA_VectorOpnd *vOffset, VISA_StateOpndHandle *dstSurface, VISA_VectorOpnd *xOffset,
                                                            VISA_VectorOpnd *yOffset)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;
    ISA_VA_Sub_Opcode subOp = ISA_HDC_ERODE;

    if(subOpED == CM_DILATE)
        subOp = ISA_HDC_DILATE;

    if(IS_GEN_BOTH_PATH)
    {
        uint8_t execMode = CM_ED_64x4;
        uint8_t functionality = 0x3; /*reserved*/
        uint8_t pixelSize = 1;

        status = m_builder->translateVISAVaSklPlusGeneralInst(
                        subOp, surface->g4opnd /*surface*/, sampler->g4opnd /*sampler*/, execMode, functionality,
                        //rest
                        uOffset->g4opnd /*uOffset*/              , vOffset->g4opnd /*vOffset*/  ,

                        //1pixel convolve
                        NULL /*offsetOpnd*/,

                        //FloodFill
                        NULL /*loopCountOpnd*/          , NULL /*pixelhMasOpnd*/,
                        NULL /*pixelVMaskLeftOpnd*/     , NULL /*pixelVMaskRightOpnd*/,

                        //LBP Correlation
                        NULL /*disparityOpnd*/          ,

                        //correlation search
                        NULL        ,   NULL  ,
                        NULL        ,   NULL   ,
                        NULL        ,   NULL ,

                        //general
                        NULL, Type_UNDEF, 0,

                        //hdc
                        pixelSize /*pixelSize*/                 , dstSurface->g4opnd /*dstSurfaceOpnd*/,
                        xOffset->g4opnd  /*dstXOffOnd*/            , yOffset->g4opnd /*dstYOffOpnd*/,
                        true);
    }
    if(IS_VISA_BOTH_PATH)
    {
        ISA_Opcode opcode = ISA_VA_SKL_PLUS;
        VISA_INST_Desc *instDesc = &CISA_INST_table[opcode];
        VISA_opnd *opnd[30];
        int num_pred_desc_operands = 0;
        int num_operands = 0;

        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, instDesc );
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, instDesc, subOp));
        ADD_OPND(num_operands, opnd, sampler);
        ADD_OPND(num_operands, opnd, surface);
        ADD_OPND(num_operands, opnd, uOffset);
        ADD_OPND(num_operands, opnd, vOffset);
        ADD_OPND(num_operands, opnd, dstSurface);
        ADD_OPND(num_operands, opnd, xOffset);
        ADD_OPND(num_operands, opnd, yOffset);

        //CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        unsigned char size = EXEC_SIZE_1;

        //pred id
        unsigned short pred_id = 0;
        inst->createCisaInstruction(opcode, size, 0 , pred_id,opnd, num_operands, instDesc);
        addInstructionToEnd(inst);
    }

#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISAVAHDCMinMaxFilter(VISA_StateOpndHandle *sampler, VISA_StateOpndHandle *surface, VISA_VectorOpnd * uOffset,
                                                            VISA_VectorOpnd *vOffset, HDCReturnFormat returnFormat, MMFEnableMode mmfMode,
                                                            VISA_StateOpndHandle *dstSurface, VISA_VectorOpnd *xOffset, VISA_VectorOpnd *yOffset)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;
    ISA_VA_Sub_Opcode subOp = ISA_HDC_MMF;

    if(IS_GEN_BOTH_PATH)
    {
        uint8_t execMode = CM_CONV_16x4;
        uint8_t functionality = mmfMode; /*reserved*/
        uint8_t pixelSize = returnFormat;

        status = m_builder->translateVISAVaSklPlusGeneralInst(
                        subOp, surface->g4opnd /*surface*/, sampler->g4opnd /*sampler*/, execMode, functionality,
                        //rest
                        uOffset->g4opnd /*uOffset*/              , vOffset->g4opnd /*vOffset*/  ,

                        //1pixel convolve
                        NULL /*offsetOpnd*/,

                        //FloodFill
                        NULL /*loopCountOpnd*/          , NULL /*pixelhMasOpnd*/,
                        NULL /*pixelVMaskLeftOpnd*/     , NULL /*pixelVMaskRightOpnd*/,

                        //LBP Correlation
                        NULL /*disparityOpnd*/          ,

                        //correlation search
                        NULL        ,   NULL  ,
                        NULL        ,   NULL   ,
                        NULL        ,   NULL ,

                        //general
                        NULL, Type_UNDEF, 0,

                        //hdc
                        pixelSize /*pixelSize*/                 , dstSurface->g4opnd /*dstSurfaceOpnd*/,
                        xOffset->g4opnd  /*dstXOffOnd*/            , yOffset->g4opnd /*dstYOffOpnd*/,
                        true);
    }
    if(IS_VISA_BOTH_PATH)
    {
        ISA_Opcode opcode = ISA_VA_SKL_PLUS;
        VISA_INST_Desc *instDesc = &CISA_INST_table[opcode];
        VISA_opnd *opnd[30];
        int num_pred_desc_operands = 0;
        int num_operands = 0;

        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, instDesc );
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, instDesc, subOp));
        ADD_OPND(num_operands, opnd, sampler);
        ADD_OPND(num_operands, opnd, surface);
        ADD_OPND(num_operands, opnd, uOffset);
        ADD_OPND(num_operands, opnd, vOffset);
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, instDesc, returnFormat, true, subOp));
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, instDesc, mmfMode, true, subOp));
        ADD_OPND(num_operands, opnd, dstSurface);
        ADD_OPND(num_operands, opnd, xOffset);
        ADD_OPND(num_operands, opnd, yOffset);

        //CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        unsigned char size = EXEC_SIZE_1;

        //pred id
        unsigned short pred_id = 0;
        inst->createCisaInstruction(opcode, size, 0 , pred_id,opnd, num_operands, instDesc);
        addInstructionToEnd(inst);
    }

#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISAVAHDCLBPCorrelation(VISA_StateOpndHandle *surface, VISA_VectorOpnd * uOffset,
                                                            VISA_VectorOpnd *vOffset, VISA_VectorOpnd *disparity,
                                                            VISA_StateOpndHandle *dstSurface, VISA_VectorOpnd *xOffset, VISA_VectorOpnd *yOffset)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;
    ISA_VA_Sub_Opcode subOp = ISA_HDC_LBPCORRELATION;

    if(IS_GEN_BOTH_PATH)
    {
        uint8_t execMode = CM_CONV_16x4;
        uint8_t functionality = 0x3; /*reserved*/
        uint8_t pixelSize = 1;

        status = m_builder->translateVISAVaSklPlusGeneralInst(
                        subOp, surface->g4opnd /*surface*/, NULL /*sampler*/, execMode, functionality,
                        //rest
                        uOffset->g4opnd /*uOffset*/              , vOffset->g4opnd /*vOffset*/  ,

                        //1pixel convolve
                        NULL /*offsetOpnd*/,

                        //FloodFill
                        NULL /*loopCountOpnd*/          , NULL /*pixelhMasOpnd*/,
                        NULL /*pixelVMaskLeftOpnd*/     , NULL /*pixelVMaskRightOpnd*/,

                        //LBP Correlation
                        disparity->g4opnd /*disparityOpnd*/          ,

                        //correlation search
                        NULL        ,   NULL  ,
                        NULL        ,   NULL   ,
                        NULL        ,   NULL ,

                        //general
                        NULL, Type_UNDEF, 0,

                        //hdc
                        pixelSize /*pixelSize*/                 , dstSurface->g4opnd /*dstSurfaceOpnd*/,
                        xOffset->g4opnd  /*dstXOffOnd*/            , yOffset->g4opnd /*dstYOffOpnd*/,
                        true);
    }
    if(IS_VISA_BOTH_PATH)
    {
        ISA_Opcode opcode = ISA_VA_SKL_PLUS;
        VISA_INST_Desc *instDesc = &CISA_INST_table[opcode];
        VISA_opnd *opnd[30];
        int num_pred_desc_operands = 0;
        int num_operands = 0;

        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, instDesc );
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, instDesc, subOp));
        ADD_OPND(num_operands, opnd, surface);
        ADD_OPND(num_operands, opnd, uOffset);
        ADD_OPND(num_operands, opnd, vOffset);
        ADD_OPND(num_operands, opnd, disparity);
        ADD_OPND(num_operands, opnd, dstSurface);
        ADD_OPND(num_operands, opnd, xOffset);
        ADD_OPND(num_operands, opnd, yOffset);

        //CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        unsigned char size = EXEC_SIZE_1;

        //pred id
        unsigned short pred_id = 0;
        inst->createCisaInstruction(opcode, size, 0 , pred_id,opnd, num_operands, instDesc);
        addInstructionToEnd(inst);
    }

#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISAVAHDCLBPCreation(VISA_StateOpndHandle *surface, VISA_VectorOpnd * uOffset,
                                                            VISA_VectorOpnd *vOffset, LBPCreationMode mode,
                                                            VISA_StateOpndHandle *dstSurface, VISA_VectorOpnd *xOffset, VISA_VectorOpnd *yOffset)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;
    ISA_VA_Sub_Opcode subOp = ISA_HDC_LBPCREATION;

    if(mode == CM_3x3_AND_5x5)
    {
        CmAssert(0);
        return CM_FAILURE;
    }

    if(IS_GEN_BOTH_PATH)
    {
        uint8_t execMode = CM_CONV_16x4;
        uint8_t functionality = mode; /*reserved*/
        uint8_t pixelSize = 1;

        status = m_builder->translateVISAVaSklPlusGeneralInst(
                        subOp, surface->g4opnd /*surface*/, NULL /*sampler*/, execMode, functionality,
                        //rest
                        uOffset->g4opnd /*uOffset*/              , vOffset->g4opnd /*vOffset*/  ,

                        //1pixel convolve
                        NULL /*offsetOpnd*/,

                        //FloodFill
                        NULL /*loopCountOpnd*/          , NULL /*pixelhMasOpnd*/,
                        NULL /*pixelVMaskLeftOpnd*/     , NULL /*pixelVMaskRightOpnd*/,

                        //LBP Correlation
                        NULL /*disparityOpnd*/          ,

                        //correlation search
                        NULL        ,   NULL  ,
                        NULL        ,   NULL   ,
                        NULL        ,   NULL ,

                        //general
                        NULL, Type_UNDEF, 0,

                        //hdc
                        pixelSize /*pixelSize*/                 , dstSurface->g4opnd /*dstSurfaceOpnd*/,
                        xOffset->g4opnd  /*dstXOffOnd*/            , yOffset->g4opnd /*dstYOffOpnd*/,
                        true);
    }
    if(IS_VISA_BOTH_PATH)
    {
        ISA_Opcode opcode = ISA_VA_SKL_PLUS;
        VISA_INST_Desc *instDesc = &CISA_INST_table[opcode];
        VISA_opnd *opnd[30];
        int num_pred_desc_operands = 0;
        int num_operands = 0;

        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, instDesc );
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, instDesc, subOp));
        ADD_OPND(num_operands, opnd, surface);
        ADD_OPND(num_operands, opnd, uOffset);
        ADD_OPND(num_operands, opnd, vOffset);
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, instDesc, mode, true, subOp));
        ADD_OPND(num_operands, opnd, dstSurface);
        ADD_OPND(num_operands, opnd, xOffset);
        ADD_OPND(num_operands, opnd, yOffset);

        //CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        unsigned char size = EXEC_SIZE_1;

        //pred id
        unsigned short pred_id = 0;
        inst->createCisaInstruction(opcode, size, 0 , pred_id,opnd, num_operands, instDesc);
        addInstructionToEnd(inst);
    }

#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISAVAHDCConvolve1D(VISA_StateOpndHandle *sampler, VISA_StateOpndHandle *surface, VISA_VectorOpnd * uOffset,
                                                            VISA_VectorOpnd *vOffset, HDCReturnFormat returnFormat, Convovle1DDirection direction,
                                                            VISA_StateOpndHandle *dstSurface, VISA_VectorOpnd *xOffset, VISA_VectorOpnd *yOffset)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;
    ISA_VA_Sub_Opcode subOp = ISA_HDC_1DCONV_H;

    if( direction == CM_V_DIRECTION )
    {
        subOp = ISA_HDC_1DCONV_V;
    }

    if(IS_GEN_BOTH_PATH)
    {
        uint8_t execMode = CM_CONV_16x4;
        uint8_t functionality = 0x3; /*reserved*/
        uint8_t pixelSize = returnFormat;

        status = m_builder->translateVISAVaSklPlusGeneralInst(
                        subOp, surface->g4opnd /*surface*/, sampler->g4opnd /*sampler*/, execMode, functionality,
                        //rest
                        uOffset->g4opnd /*uOffset*/              , vOffset->g4opnd /*vOffset*/  ,

                        //1pixel convolve
                        NULL /*offsetOpnd*/,

                        //FloodFill
                        NULL /*loopCountOpnd*/          , NULL /*pixelhMasOpnd*/,
                        NULL /*pixelVMaskLeftOpnd*/     , NULL /*pixelVMaskRightOpnd*/,

                        //LBP Correlation
                        NULL /*disparityOpnd*/          ,

                        //correlation search
                        NULL        ,   NULL  ,
                        NULL        ,   NULL   ,
                        NULL        ,   NULL ,

                        //general
                        NULL, Type_UNDEF, 0,

                        //hdc
                        pixelSize /*pixelSize*/                 , dstSurface->g4opnd /*dstSurfaceOpnd*/,
                        xOffset->g4opnd  /*dstXOffOnd*/            , yOffset->g4opnd /*dstYOffOpnd*/,
                        true);
    }
    if(IS_VISA_BOTH_PATH)
    {
        ISA_Opcode opcode = ISA_VA_SKL_PLUS;
        VISA_INST_Desc *instDesc = &CISA_INST_table[opcode];
        VISA_opnd *opnd[30];
        int num_pred_desc_operands = 0;
        int num_operands = 0;

        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, instDesc );
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, instDesc, subOp));
        ADD_OPND(num_operands, opnd, sampler);
        ADD_OPND(num_operands, opnd, surface);
        ADD_OPND(num_operands, opnd, uOffset);
        ADD_OPND(num_operands, opnd, vOffset);
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, instDesc, returnFormat, true, subOp));
        ADD_OPND(num_operands, opnd, dstSurface);
        ADD_OPND(num_operands, opnd, xOffset);
        ADD_OPND(num_operands, opnd, yOffset);

        //CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        unsigned char size = EXEC_SIZE_1;

        //pred id
        unsigned short pred_id = 0;
        inst->createCisaInstruction(opcode, size, 0 , pred_id,opnd, num_operands, instDesc);
        addInstructionToEnd(inst);
    }

#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISAVAHDCConvolve1Pixel(VISA_StateOpndHandle *sampler, VISA_StateOpndHandle *surface, VISA_VectorOpnd * uOffset,
                                                            VISA_VectorOpnd *vOffset, HDCReturnFormat returnFormat, VISA_RawOpnd *offsets,
                                                            VISA_StateOpndHandle *dstSurface, VISA_VectorOpnd *xOffset, VISA_VectorOpnd *yOffset)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;
    ISA_VA_Sub_Opcode subOp = ISA_HDC_1PIXELCONV;

    if(IS_GEN_BOTH_PATH)
    {
        CreateGenRawSrcOperand(offsets);
        uint8_t execMode = CM_CONV_16x4;
        uint8_t functionality = 0x3; /*reserved*/
        uint8_t pixelSize = returnFormat;

        status = m_builder->translateVISAVaSklPlusGeneralInst(
                        subOp, surface->g4opnd /*surface*/, sampler->g4opnd /*sampler*/, execMode, functionality,
                        //rest
                        uOffset->g4opnd /*uOffset*/              , vOffset->g4opnd /*vOffset*/  ,

                        //1pixel convolve
                        offsets->g4opnd /*offsetOpnd*/,

                        //FloodFill
                        NULL /*loopCountOpnd*/          , NULL /*pixelhMasOpnd*/,
                        NULL /*pixelVMaskLeftOpnd*/     , NULL /*pixelVMaskRightOpnd*/,

                        //LBP Correlation
                        NULL /*disparityOpnd*/          ,

                        //correlation search
                        NULL        ,   NULL  ,
                        NULL        ,   NULL   ,
                        NULL        ,   NULL ,

                        //general
                        NULL, Type_UNDEF, 0,

                        //hdc
                        pixelSize /*pixelSize*/                 , dstSurface->g4opnd /*dstSurfaceOpnd*/,
                        xOffset->g4opnd  /*dstXOffOnd*/            , yOffset->g4opnd /*dstYOffOpnd*/,
                        true);
    }
    if(IS_VISA_BOTH_PATH)
    {
        ISA_Opcode opcode = ISA_VA_SKL_PLUS;
        VISA_INST_Desc *instDesc = &CISA_INST_table[opcode];
        VISA_opnd *opnd[30];
        int num_pred_desc_operands = 0;
        int num_operands = 0;

        GET_NUM_PRED_DESC_OPNDS(num_pred_desc_operands, instDesc );
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, instDesc, subOp));
        ADD_OPND(num_operands, opnd, sampler);
        ADD_OPND(num_operands, opnd, surface);
        ADD_OPND(num_operands, opnd, uOffset);
        ADD_OPND(num_operands, opnd, vOffset);
        ADD_OPND(num_operands, opnd, this->CreateOtherOpndHelper(num_pred_desc_operands, num_operands, instDesc, returnFormat, true, subOp));
        ADD_OPND(num_operands, opnd, offsets);
        ADD_OPND(num_operands, opnd, dstSurface);
        ADD_OPND(num_operands, opnd, xOffset);
        ADD_OPND(num_operands, opnd, yOffset);

        //CHECK_NUM_OPNDS(inst_desc, num_operands, num_pred_desc_operands);

        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        unsigned char size = EXEC_SIZE_1;

        //pred id
        unsigned short pred_id = 0;
        inst->createCisaInstruction(opcode, size, 0 , pred_id,opnd, num_operands, instDesc);
        addInstructionToEnd(inst);
    }

#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}

int VISAKernelImpl::AppendVISALifetime(VISAVarLifetime startOrEnd, VISA_VectorOpnd *var)
{
    AppendVISAInstCommon();
#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
        startTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    int status = CM_SUCCESS;
    unsigned char properties = (unsigned char)startOrEnd;

    if(IS_GEN_BOTH_PATH)
    {
        if(var->g4opnd->isGreg())
        {
			properties |= (OPERAND_GENERAL << 4);
        }
        else if(var->g4opnd->isAddress())
        {
			properties |= (OPERAND_ADDRESS << 4);
        }
        else if(var->g4opnd->isFlag())
        {
            properties |= (OPERAND_PREDICATE << 4);
        }

        status = m_builder->translateVISALifetimeInst(properties, var->g4opnd);
    }

    if(IS_VISA_BOTH_PATH)
    {
        VISA_INST_Desc *inst_desc = NULL;
        VISA_opnd* opnd[2];
        ISA_Opcode opcode = ISA_LIFETIME;
        CisaFramework::CisaInst * inst = new(m_mem)CisaFramework::CisaInst(m_mem);

        inst_desc = &CISA_INST_table[opcode];

        opnd[0] = (VISA_opnd*)m_mem.alloc(sizeof(VISA_opnd));
        opnd[0]->_opnd.other_opnd = properties;
        opnd[0]->opnd_type = CISA_OPND_OTHER;
        opnd[0]->size = Get_Common_ISA_Type_Size((VISA_Type)inst_desc->opnd_desc[0].data_type);
        opnd[0]->tag = (uint8_t) inst_desc->opnd_desc[0].opnd_type;

        opnd[1] = (VISA_opnd*)m_mem.alloc(sizeof(VISA_opnd));
        if(var->_opnd.v_opnd.tag == OPERAND_GENERAL)
        {
			opnd[0]->_opnd.other_opnd |= (OPERAND_GENERAL << 4);
            opnd[1]->_opnd.other_opnd = var->_opnd.v_opnd.opnd_val.gen_opnd.index;
        }
        else if(var->_opnd.v_opnd.tag == OPERAND_ADDRESS)
        {
			opnd[0]->_opnd.other_opnd |= (OPERAND_ADDRESS << 4);
            opnd[1]->_opnd.other_opnd = var->_opnd.v_opnd.opnd_val.addr_opnd.index;
        }
        else if(var->_opnd.v_opnd.tag == OPERAND_PREDICATE)
        {
			opnd[0]->_opnd.other_opnd |= (OPERAND_PREDICATE << 4);
            opnd[1]->_opnd.other_opnd = var->_opnd.v_opnd.opnd_val.pred_opnd.index;
        }
        opnd[1]->opnd_type = CISA_OPND_OTHER;
        opnd[1]->size = Get_Common_ISA_Type_Size((VISA_Type)inst_desc->opnd_desc[1].data_type);
        opnd[1]->tag = (uint8_t) inst_desc->opnd_desc[1].opnd_type;

        inst->createCisaInstruction(opcode, 1, 0, 0, opnd, 2, inst_desc);
        addInstructionToEnd(inst);

    }

#if defined(MEASURE_COMPILATION_TIME) && defined(TIME_BUILDER)
    stopTimer(TIMER_VISA_BUILDER_APPEND_INST);
#endif
    return status;
}


int VISAKernelImpl::patchLastInst(VISA_LabelOpnd *label)
{
    if(label->_opnd.other_opnd == CISA_INVALID_VAR_ID)
    {
        std::map<unsigned int, std::string>::iterator iter = this->m_forward_label_pool.find(label->index);

        if( iter == this->m_forward_label_pool.end() )
        {
            CmAssert( 0 );
            return CM_FAILURE;
        }
        if((ISA_Opcode)label->tag == ISA_SUBROUTINE)
        {
            this->m_lastInst->setLabelInfo(iter->second, true, true);
        }else
        {
            this->m_lastInst->setLabelInfo(iter->second, false, true);
        }
    }
    return CM_SUCCESS;
}

uint32_t VISAKernelImpl::addStringPool(std::string str)
{
    if (strcmp(str.c_str(), ""))
    {
        m_string_pool.push_back(str);
        m_string_pool_size += (int) str.size()+1; //to account for a null terminating character
        return (uint32_t)(m_string_pool.size()-1);
    }
    else
    {
        return 0;
    }
}

void VISAKernelImpl::addInstructionToEnd(CisaInst * inst)
{
    m_instruction_list.push_back(inst);
    m_lastInst = inst;
    CISA_INST * cisaInst = inst->getCISAInst();
    cisaInst->id = this->getvIsaInstCount();
    this->m_instruction_size += inst->getSize();
    DEBUG_PRINT_SIZE_INSTRUCTION("size after instruction added: ", inst->m_inst_desc->opcode, SIZE_VALUE_INST);
    return;
}

int VISAKernelImpl::addLabel(label_info_t * lbl, char * label_name)
{
    return m_label_count++;
}

int VISAKernelImpl::addFunctionDirective(char * func_name)
{
    /*
    label_info_t *lbl = (label_info_t *)m_mem.alloc(sizeof(label_info_t));
    //memset(lbl,0,sizeof(label_info_t));
    int labelID = this->addLabel(lbl, func_name);
    lbl->kind = LABEL_SUBROUTINE;
    this->m_funcName_to_labelID_map[std::string(func_name)] = labelID;
    return labelID;
    */
    return 0;
}

void VISAKernelImpl::setGenxDebugInfoBuffer(char * buffer, unsigned long size)
{
    this->m_genx_debug_info_buffer = buffer;
    this->m_genx_debug_info_size = size;
}

void VISAKernelImpl::patchLabels()
{
    std::list<CisaInst *>::iterator iter =  m_instruction_list.begin();
    for(; iter != m_instruction_list.end(); iter++)
    {
        CisaInst * inst = *iter;
        if(inst->needLabelPatch())
        {
            if(inst->isFuncLabel())
            {
                int labelID = this->getLabelIdFromFunctionName(inst->getLabelName());
                MUST_BE_TRUE(labelID != INVALID_LABEL_ID, "Invalid Function Name.");
                inst->setLabelIndex(labelID);

            }else
            {
                std::string label_name = inst->getLabelName();
                MUST_BE_TRUE(label_name != "", "Invalid Label discovered during patching label process.");
                unsigned int labelID = this->getIndexFromLabelName(label_name);
                MUST_BE_TRUE(labelID != ((unsigned int) INVALID_LABEL_ID), "Invalid Label Name.");
                inst->setLabelIndex(labelID);
            }
        }
    }

    //For switch statements
    //Fixing labelIDs

    std::list<VISA_opnd *>::iterator it_operand = m_pending_labels.begin();
    std::list<std::string>::iterator it_lbl_name = m_pending_label_names.begin();

    while(it_operand != m_pending_labels.end())
    {
        MUST_BE_TRUE( it_lbl_name != m_pending_label_names.end(),  "Number of label objects doesn't match number of label names in switch" );
        VISA_opnd * temp_opnd = * it_operand;
        temp_opnd->_opnd.other_opnd = this->getIndexFromLabelName(* it_lbl_name);
        MUST_BE_TRUE( temp_opnd->_opnd.other_opnd != (unsigned int)INVALID_LABEL_ID,  "Invalid jump label detected." );
        it_operand++;
        it_lbl_name++;
    }

    return;
}
/**
* This function is called right before the kernel instructions are outputed in to a buffer.
* It assumes that all the VISA instructions have already been generated.
*/
void VISAKernelImpl::finalizeKernel()
{
    if(!mTargetAttributeSet)
    {
        VISATarget target = m_options->getTarget();
        AddKernelAttribute("Target", 1, &target);
    }
    patchLabels();
    m_cisa_kernel.string_count = (uint32_t)m_string_pool.size();
    m_cisa_kernel.strings = (const char **) m_mem.alloc(m_cisa_kernel.string_count * sizeof(char *));
    auto it_string = m_string_pool.begin(), et_string = m_string_pool.end();
    int size_check = 0;

    for(int i = 0; it_string != et_string; i++, ++it_string)
    {
        char* string = (char*) m_mem.alloc( it_string->size() + 1 );
        memcpy_s(string, it_string->size() + 1, it_string->c_str(), it_string->size()+1);
        m_cisa_kernel.strings[i] = string;
        size_check += (int) it_string->size()+1;
    }

    m_kernel_data_size = sizeof(m_cisa_kernel.string_count);
    m_kernel_data_size += this->m_string_pool_size;

    DEBUG_PRINT_SIZE("\nsize after string_count: ", SIZE_VALUE);

    //already set
    m_kernel_data_size += sizeof(m_cisa_kernel.name_index);

    DEBUG_PRINT_SIZE("size after name_index: ", SIZE_VALUE);

    /****VARIABLES*******/
    unsigned int adjVarInfoCount = m_var_info_count - m_num_pred_vars;
    m_cisa_kernel.variable_count = adjVarInfoCount;
    m_cisa_kernel.variables = (var_info_t * ) m_mem.alloc(sizeof(var_info_t) * adjVarInfoCount);

    for(unsigned int i = 0; i < adjVarInfoCount; i++)
    {
        var_info_t * temp = &m_var_info_list.at(i + m_num_pred_vars)->genVar;
        m_cisa_kernel.variables[i] = *temp;
        m_var_info_size += Get_Size_Var_Info_CISA3(temp);
    }
    m_kernel_data_size += sizeof(m_cisa_kernel.variable_count);
    m_kernel_data_size += this->m_var_info_size;

    DEBUG_PRINT_SIZE("size after variables: ", SIZE_VALUE);

    /****ADDRESSES**********/

    m_cisa_kernel.address_count = (uint16_t)this->m_addr_info_count;

    m_cisa_kernel.addresses = (addr_info_t *) m_mem.alloc(sizeof(addr_info_t) * m_addr_info_count);

    std::vector<CISA_GEN_VAR *>::iterator it_addr_info = m_addr_info_list.begin();
    for(unsigned int i = 0; i < m_addr_info_count; i++, it_addr_info++)
    {
        MUST_BE_TRUE( it_addr_info != m_addr_info_list.end(),  "Count of addresses does not correspond with number of items." );
        m_cisa_kernel.addresses[i] = (*it_addr_info)->addrVar;
    }

    m_kernel_data_size += sizeof(m_cisa_kernel.address_count);
    m_kernel_data_size += this->m_adress_info_size;

    DEBUG_PRINT_SIZE("size after addresses: ", SIZE_VALUE);

    /****PREDICATES*********/
    m_cisa_kernel.predicate_count = (uint16_t)this->m_pred_info_count;
    m_cisa_kernel.predicates = (pred_info_t *) m_mem.alloc(sizeof(pred_info_t) * m_pred_info_count);

    std::vector<CISA_GEN_VAR *>::iterator it_pred_info = m_pred_info_list.begin();
    for(unsigned int i = 0; i < m_pred_info_count; i++, it_pred_info++)
    {
        MUST_BE_TRUE( it_pred_info != m_pred_info_list.end(),  "Count of predicates does not correspond with number of items." );
        pred_info_t * temp = &(*it_pred_info)->predVar;
        m_cisa_kernel.predicates[i] = *temp;
    }
    m_kernel_data_size += sizeof(m_cisa_kernel.predicate_count);
    m_kernel_data_size += this->m_predicate_info_size;

    DEBUG_PRINT_SIZE("size after predicates: ", SIZE_VALUE);

    /****LABELS**********/
    m_cisa_kernel.label_count = (uint16_t)this->m_label_count;
    m_cisa_kernel.labels = (label_info_t *) m_mem.alloc(sizeof(label_info_t) * m_label_count);

    std::vector<label_info_t *>::const_iterator it_label_info = m_label_info_list.cbegin();
    std::vector<label_info_t *>::const_iterator it_label_info_end = m_label_info_list.cend();
    for(unsigned int i = 0; i < m_label_count; i++, it_label_info++)
    {
        MUST_BE_TRUE( it_label_info != it_label_info_end,  "Count of labels does not correspond with number of items." );
        label_info_t * temp = *it_label_info;
        m_cisa_kernel.labels[i] = *temp;
    }
    m_kernel_data_size += sizeof(m_cisa_kernel.label_count);
    m_kernel_data_size += this->m_label_info_size;

    DEBUG_PRINT_SIZE("size after labels: ", SIZE_VALUE);

    /*****SAMPLERS*********/
    m_cisa_kernel.sampler_count = (uint8_t)this->m_sampler_count;
    m_cisa_kernel.samplers = (state_info_t * ) m_mem.alloc(sizeof(state_info_t) * this->m_sampler_count);

    std::vector<CISA_GEN_VAR*>::iterator  it_sampler_info = m_sampler_info_list.begin();
    for(unsigned int i = 0; i < m_sampler_count; i++, it_sampler_info++)
    {
        MUST_BE_TRUE( it_sampler_info != m_sampler_info_list.end(),  "Count of sampler declarations does not correspond with number of items." );
        state_info_t * temp = &(*it_sampler_info)->stateVar;
        m_cisa_kernel.samplers[i] = *temp;
    }

    m_kernel_data_size += sizeof(m_cisa_kernel.sampler_count);
    m_kernel_data_size += m_sampler_info_size;


    DEBUG_PRINT_SIZE("size after samplers: ", SIZE_VALUE);

    /*****SURFACES******/
    unsigned int adjSurfaceCount = m_surface_count - Get_CISA_PreDefined_Surf_Count();
    m_cisa_kernel.surface_count = (uint8_t) adjSurfaceCount;
    m_cisa_kernel.surfaces = (state_info_t * ) m_mem.alloc(sizeof(state_info_t) * adjSurfaceCount);

    for(unsigned int i = 0, j = Get_CISA_PreDefined_Surf_Count(); i < adjSurfaceCount; i++, j++)
    {
        state_info_t * temp = &m_surface_info_list.at(j)->stateVar;
        m_cisa_kernel.surfaces[i] = *temp;
        m_surface_info_size += Get_Size_State_Info(temp);
    }

    m_kernel_data_size += sizeof(m_cisa_kernel.surface_count);
    m_kernel_data_size += m_surface_info_size;

    DEBUG_PRINT_SIZE("size after surfaces: ", SIZE_VALUE);

    /*****VMES********/
    m_cisa_kernel.vme_count = (uint8_t)this->m_vme_count;
    m_cisa_kernel.vmes = (state_info_t * ) m_mem.alloc(sizeof(state_info_t) * this->m_vme_count);

    std::vector<CISA_GEN_VAR *>::iterator  it_vme_info = m_vme_info_list.begin();
    for(unsigned int i = 0; i < m_vme_count; i++, it_vme_info++)
    {
        MUST_BE_TRUE( it_vme_info != m_vme_info_list.end(),  "Count of vme declarations does not correspond with number of items." );
        state_info_t * temp = &(*it_vme_info)->stateVar;
        m_cisa_kernel.vmes[i] = *temp;
    }

    m_kernel_data_size += sizeof(m_cisa_kernel.vme_count);
    m_kernel_data_size += m_vme_info_size;

    DEBUG_PRINT_SIZE("size after VMEs: ", SIZE_VALUE);


    /*****INPUTS******/

    if (this->m_isKernel)
    {
        m_input_offset = m_kernel_data_size;
        m_cisa_kernel.input_count = (uint8_t)this->m_input_count;
        m_cisa_kernel.inputs = (input_info_t *) m_mem.alloc(sizeof(input_info_t) * m_input_count );

        std::vector<input_info_t *>::iterator it_input_info = m_input_info_list.begin();
        for(unsigned int i = 0; i < m_input_count; i++, it_input_info++)
        {
            MUST_BE_TRUE( it_input_info != m_input_info_list.end(),  "Count of inputs does not correspond with number of items." );
            input_info_t * temp = *it_input_info;
            m_cisa_kernel.inputs[i] = *temp;
        }
        m_kernel_data_size += sizeof(m_cisa_kernel.input_count);
        m_kernel_data_size += this->m_input_info_size;

        DEBUG_PRINT_SIZE("size after inputs: ", SIZE_VALUE);
    }

    /*******INSTRUCTIONS SIZE*****/
    m_kernel_data_size += sizeof(m_cisa_kernel.size);
    m_cisa_kernel.size = this->m_instruction_size;

    DEBUG_PRINT_SIZE("size after size: ", SIZE_VALUE);

    /******OFFSET OF FIRST INSTRUCTION FROM KERNEL START*********/
    m_kernel_data_size += sizeof(m_cisa_kernel.entry);

    DEBUG_PRINT_SIZE("size after entry: ", SIZE_VALUE);

    if (!this->getIsKernel())
    {
        m_kernel_data_size += sizeof(m_cisa_kernel.input_size);
        DEBUG_PRINT_SIZE("size after input size: ", SIZE_VALUE);

        m_kernel_data_size += sizeof(m_cisa_kernel.return_type);
        DEBUG_PRINT_SIZE("size after return type: ", SIZE_VALUE);
    }

    /*******ATTRIBUTES**************/
    m_cisa_kernel.attribute_count = (uint16_t)this->m_attribute_count;
    m_cisa_kernel.attributes = (attribute_info_t *) m_mem.alloc(sizeof(attribute_info_t) * m_attribute_count);

    std::list<attribute_info_t *>::iterator it_attribute_info = m_attribute_info_list.begin();
    for(unsigned int i = 0; i < m_attribute_count; i++, it_attribute_info++)
    {
        MUST_BE_TRUE( it_attribute_info != m_attribute_info_list.end(),  "Count of attributes does not correspond with number of items." );
        attribute_info_t * temp = *it_attribute_info;
        m_cisa_kernel.attributes[i] = *temp;
    }
    m_kernel_data_size += sizeof(m_cisa_kernel.attribute_count);
    m_kernel_data_size += this->m_attribute_info_size;

    DEBUG_PRINT_SIZE("size after attributes: ", SIZE_VALUE);

    /******Setting Entry*********/
    m_cisa_kernel.entry = m_kernel_data_size;

    this->m_cisa_binary_size = m_instruction_size + m_kernel_data_size;
    this->m_cisa_binary_buffer = (char * ) m_mem.alloc(m_cisa_binary_size);
    //memset(m_cisa_binary_buffer, 0, m_cisa_binary_size);

}

unsigned long VISAKernelImpl::writeInToCisaBinaryBuffer(const void * value, int size)
{
    MUST_BE_TRUE( m_bytes_written_cisa_buffer + size <= m_cisa_binary_size,
        "Size of VISA instructions binary buffer is exceeded." );

    memcpy_s( &m_cisa_binary_buffer[m_bytes_written_cisa_buffer], size, value, size );
    m_bytes_written_cisa_buffer += size;

    return m_bytes_written_cisa_buffer;
}

VISA_LabelOpnd* VISAKernelImpl::getLabelOperandFromFunctionName(std::string name)
{
    std::map<std::string, VISA_LabelOpnd *>::iterator it;
    it = m_funcName_to_labelID_map.find(name);
    if(m_funcName_to_labelID_map.end() == it)
    {
        return NULL;
    }else
    {
        return it->second;
    }
}
unsigned int VISAKernelImpl::getLabelIdFromFunctionName(std::string name)
{
    std::map<std::string, VISA_LabelOpnd *>::iterator it;
    it = m_funcName_to_labelID_map.find(name);
    if(m_funcName_to_labelID_map.end() == it)
    {
        return INVALID_LABEL_ID;
    }else
    {
        return it->second->_opnd.other_opnd;
    }
}

unsigned int VISAKernelImpl::getIndexFromName(const std::string &name)
{
    std::map<std::string, CISA_GEN_VAR *>::iterator it;
    it = m_var_name_to_index_map.find(name);
    if(m_var_name_to_index_map.end() == it)
    {
        return CISA_INVALID_VAR_ID;
    }else
    {
        return it->second->index;
    }
}

CISA_GEN_VAR * VISAKernelImpl::getDeclFromName(const std::string &name)
{
    std::map<std::string, CISA_GEN_VAR *>::iterator it;
    it = m_var_name_to_index_map.find(name);
    if(m_var_name_to_index_map.end() == it)
    {
        return NULL;
    }else
    {
        return it->second;
    }
}

bool VISAKernelImpl::setNameIndexMap(const std::string &name, CISA_GEN_VAR * genDecl, bool unique)
{
    bool succeeded = true;

    //make sure mapping doesn't already exist
    if (unique && getIndexFromName(name) != CISA_INVALID_VAR_ID )
    {
        return false;
    }
    m_var_name_to_index_map[name] = genDecl;
    return succeeded;
}

unsigned int VISAKernelImpl::getIndexFromLabelName(const std::string &name)
{
    std::map<std::string, VISA_LabelOpnd *>::iterator it;
    it = m_label_name_to_index_map.find(name);
    if(m_label_name_to_index_map.end() == it)
    {
        return CISA_INVALID_VAR_ID;
    }else
    {
        return it->second->_opnd.other_opnd;
    }
}

VISA_LabelOpnd* VISAKernelImpl::getLabelOpndFromLabelName(const std::string &name)
{
    std::map<std::string, VISA_LabelOpnd *>::iterator it;
    it = m_label_name_to_index_map.find(name);
    if(m_label_name_to_index_map.end() == it)
    {
        return NULL;
    }else
    {
        return (VISA_LabelOpnd *)it->second;
    }
}

bool VISAKernelImpl::setLabelNameIndexMap(const std::string &name, VISA_LabelOpnd *lbl)
{
    bool succeeded = true;

    //make sure mapping doesn't already exist
    if( getIndexFromLabelName(name) != CISA_INVALID_VAR_ID )
    {
        return false;
    }
    m_label_name_to_index_map[name] = lbl;
    return succeeded;
}

unsigned short VISAKernelImpl::get_hash_key(const char* str)
{
    const char *str_pt = str;
    unsigned short key=0;
    unsigned char c;
    while ((c = *str_pt++) != '\0') key = (key+c)<<1;

    return key % HASH_TABLE_SIZE;
}
string_pool_entry** VISAKernelImpl::new_string_pool()
{
    string_pool_entry ** sp = (string_pool_entry**)m_mem.alloc(sizeof(string_pool_entry *) * HASH_TABLE_SIZE);
    //memset(sp, 0, sizeof(string_pool_entry *) * HASH_TABLE_SIZE);

    return sp;
}

bool VISAKernelImpl::string_pool_lookup_and_insert_branch_targets( char *str,
                                                                  Common_ISA_Var_Class type,
                                                                  VISA_Type data_type)
{
    unsigned short key = 0;
    string_pool_entry* entry;
    char *s;
    int len = (int) strlen(str);

    key = get_hash_key(str);

    for( entry = m_branch_targets[key]; entry != NULL; entry = entry->next ){
        s = (char *)entry->value;
        if(!strcmp(s, str))
            return false;
    }

    s = (char*)m_mem.alloc(len + 1);
    memcpy_s(s, len+1, str, len+1);
    s[len] = '\0';

    entry = (string_pool_entry*)m_mem.alloc(sizeof(string_pool_entry));
    //memset(entry, 0, sizeof(entry));
    entry->value = s;
    entry->type = type;
    entry->data_type = data_type;

    //entry->next = m_string_pool_name[key];
    m_branch_targets[key] = entry;

    return true;
}

void VISAKernelImpl::CISAPostFileParse()
{
    //Checking if target labels have been declared
    for (int i = 0; i < HASH_TABLE_SIZE; i++) {
        if (m_branch_targets[i]) {
            string_pool_entry * l = m_branch_targets[i];
            while(l != NULL) {
                l = l->next;
            }
        }
    }
    return;
}

VISAKernelImpl::~VISAKernelImpl()
{
    std::list<CisaFramework::CisaInst *>::iterator iter =  m_instruction_list.begin();
    for(; iter != m_instruction_list.end(); iter++)
    {
        CisaFramework::CisaInst * inst = *iter;
        inst->~CisaInst();
    }

    m_var_info_list.clear();
    m_input_info_list.clear();
    m_label_info_list.clear();
    m_addr_info_list.clear();

    if (IS_GEN_BOTH_PATH)
    {
        //need to call destructor even thought it is allocated in memory pool.
        //so that internal data structures get cleared.
        m_kernel->~G4_Kernel();
        m_builder->~IR_Builder();
        delete m_globalMem;
        delete m_kernelMem;
    }
}

int VISAKernelImpl::GetGenxBinary(void *&buffer, int &size)
{
    buffer = this->m_genx_binary_buffer;
    size = this->m_genx_binary_size;
    return CM_SUCCESS;
}

int VISAKernelImpl::GetGenReloc(BasicRelocEntry*& relocs, unsigned int& numRelocs)
{
    computeAllRelocs(numRelocs, relocs);
    return CM_SUCCESS;
}

int VISAKernelImpl::GetGenRelocEntryBuffer(void *&buffer, unsigned int &byteSize, unsigned int &numEntries)
{
    G4_Kernel::RelocationTableTy& reloc_table = m_kernel->getRelocationTable();
    numEntries = reloc_table.size();
    byteSize = sizeof(GenRelocEntry) * numEntries;

    if (reloc_table.empty())
        return CM_SUCCESS;

    // allocate the buffer for relocation table
    buffer = allocCodeBlock(byteSize);

    if (buffer == NULL || buffer == nullptr)
        return CM_FAILURE;

    GenRelocEntry* buffer_p = (GenRelocEntry*)buffer;
    for (auto reloc : reloc_table)
    {
        buffer_p->r_type = reloc.getType();
        buffer_p->r_offset = (uint32_t)reloc.getInst()->getGenOffset();
        assert(reloc.getSymbolName().size() <= MAX_SYMBOL_NAME_LENGTH);
        strcpy_s(buffer_p->r_symbol, MAX_SYMBOL_NAME_LENGTH, reloc.getSymbolName().c_str());
        ++buffer_p;
    }

    return CM_SUCCESS;
}

int VISAKernelImpl::GetGenxDebugInfo(void *&buffer, unsigned int &size, void*& mapGenISAOffsetToVISAIndex, unsigned int& mapNumElems)
{
    unsigned int i = 0;
    buffer = this->m_genx_debug_info_buffer;
    size = this->m_genx_debug_info_size;

    auto& vecToUse = m_kernel->getKernelDebugInfo()->getMapGenISAOffsetToCISAIndex();
    mapNumElems = (unsigned int)vecToUse.size();
    mapGenISAOffsetToVISAIndex = mapNumElems ? (void*)allocCodeBlock(sizeof(unsigned int) * 2*mapNumElems) : nullptr;
    for (auto& entries : vecToUse)
    {
        ((unsigned int*)mapGenISAOffsetToVISAIndex)[i * 2] = entries.first;
        ((unsigned int*)mapGenISAOffsetToVISAIndex)[i * 2+1] = entries.second;
        i++;
    }

    return CM_SUCCESS;
}

int VISAKernelImpl::GetJitInfo(FINALIZER_INFO *&jitInfo)
{
    jitInfo = this->m_jitInfo;
    return CM_SUCCESS;
}

int VISAKernelImpl::GetCompilerStats(CompilerStats &compilerStats)
{
    compilerStats.Link(this->m_compilerStats);
    return CM_SUCCESS;
}

int VISAKernelImpl::GetErrorMessage(const char *&errorMsg)
{
    errorMsg = this->errorMessage;
    return CM_SUCCESS;
}

int VISAKernelImpl::GetFunctionId(unsigned int& id)
{
    id = m_functionId;
    return CM_SUCCESS;
}

int VISAKernelImpl::SetGTPinInit(void* buffer)
{
    if (buffer)
    {
        auto gtpin = m_kernel->getGTPinData();
        if (gtpin)
        {
            gtpin->setGTPinInit(buffer);
        }
    }

    return CM_SUCCESS;
}

int VISAKernelImpl::GetGTPinBuffer(void*& buffer, unsigned int& size)
{
    buffer = nullptr;
    size = 0;

    if (m_kernel->hasGTPinInit())
    {
        auto gtpin = m_kernel->getGTPinData();
        if (gtpin)
        {
            buffer = gtpin->getGTPinInfoBuffer(size);
        }
    }

    return CM_SUCCESS;
}

int VISAKernelImpl::GetFreeGRFInfo(void*& buffer, unsigned int& size)
{
    buffer = nullptr;
    size = 0;

    if (getOptions()->getOption(vISA_GetFreeGRFInfo))
    {
        auto gtpin = m_kernel->getGTPinData();
        if (gtpin)
        {
            buffer = gtpin->getFreeGRFInfo(size);
        }
    }
    return CM_SUCCESS;
}

// index
VISA_opnd* VISAKernelImpl::CreateOtherOpnd(unsigned int value, VISA_Type opndType)
{
    VISA_opnd *temp = getOpndFromPool();

    temp->_opnd.other_opnd = value;
    temp->opnd_type = CISA_OPND_OTHER;
    temp->size = (uint16_t) Get_Common_ISA_Type_Size(opndType);
    return temp;
}

//FIXME: this needs major rework
VISA_opnd* VISAKernelImpl::CreateOtherOpndHelper(int num_pred_desc_operands, int num_operands, VISA_INST_Desc *inst_desc, unsigned int value, bool hasSubOpcode, uint8_t subOpcode)
{
    VISA_Type dataType = ISA_TYPE_NUM;
    VISA_opnd *temp = getOpndFromPool();

    if(!hasSubOpcode)
    {
        dataType = (VISA_Type)inst_desc->opnd_desc[num_pred_desc_operands + num_operands].data_type;
    }
    else
    {
        //Accounts for all the operands added so far to instruction, minus predefined ones: execSize, pred, subOpcode
        dataType = (VISA_Type)inst_desc->getSubInstDesc(subOpcode).opnd_desc[num_operands - (inst_desc->opnd_num - num_pred_desc_operands) ].data_type;
    }
    temp->_opnd.other_opnd = value;
    temp->opnd_type = CISA_OPND_OTHER;
    temp->size = Get_Common_ISA_Type_Size(dataType);
    temp->tag = (uint8_t)inst_desc->opnd_desc[num_pred_desc_operands + num_operands].opnd_type;

    return temp;
}

VISA_opnd* VISAKernelImpl::getOpndFromPool()
{
    if (IS_VISA_BOTH_PATH)
    {
        return (VISA_opnd *)m_mem.alloc(sizeof(VISA_opnd));
    }
    else
    {
        return &m_fastPathOpndPool[(m_opndCounter++) % vISA_NUMBER_OF_OPNDS_IN_POOL];
    }
}

G4_Operand* VISAKernelImpl::CommonISABuildPreDefinedSrc(int index, uint16_t vStride, uint16_t width,
                                                        uint16_t hStride, uint8_t rowOffset, uint8_t colOffset, VISA_Modifier modifier)
{
    RegionDesc *rd = m_builder->createRegionDesc( vStride, width, hStride );
    G4_Operand* tmpsrc = NULL;
    PreDefinedVarsInternal internalIndex = mapExternalToInternalPreDefVar(index);
    switch (internalIndex)
    {
    case PreDefinedVarsInternal::X:
    case PreDefinedVarsInternal::Y:
    case PreDefinedVarsInternal::LOCAL_ID_X:
    case PreDefinedVarsInternal::LOCAL_ID_Y:
    case PreDefinedVarsInternal::LOCAL_SIZE_X:
    case PreDefinedVarsInternal::LOCAL_SIZE_Y:
    case PreDefinedVarsInternal::GROUP_ID_X:
    case PreDefinedVarsInternal::GROUP_ID_Y:
    case PreDefinedVarsInternal::GROUP_ID_Z:
    case PreDefinedVarsInternal::GROUP_COUNT_X:
    case PreDefinedVarsInternal::GROUP_COUNT_Y:
        {
            G4_Type type = Get_G4_Type_From_Common_ISA_Type(getPredefinedVarType(internalIndex));
            // R0 is already declared
            G4_Declare *pre_var_dcl = getGenVar(index)->genVar.dcl;
            tmpsrc = m_builder->createSrcRegRegion(
                Get_G4_SrcMod_From_Common_ISA_Mod(modifier),
                Direct,
                pre_var_dcl->getRegVar(),
                0,
                0,
                rd,
                type);
            break;
        }
    case PreDefinedVarsInternal::TSC:
    case PreDefinedVarsInternal::R0:
    case PreDefinedVarsInternal::SR0:
    case PreDefinedVarsInternal::CR0:
    case PreDefinedVarsInternal::CE0:
    case PreDefinedVarsInternal::ARG:
    case PreDefinedVarsInternal::RET:
    case PreDefinedVarsInternal::FE_SP:
    case PreDefinedVarsInternal::FE_FP:
    case PreDefinedVarsInternal::HW_TID:
	case PreDefinedVarsInternal::DBG:
    case PreDefinedVarsInternal::COLOR:
        {
        G4_Type type = Get_G4_Type_From_Common_ISA_Type(getPredefinedVarType(internalIndex));
            G4_Declare *preVarDcl = getGenVar(index)->genVar.dcl;
            tmpsrc = m_builder->createSrcRegRegion(
                Get_G4_SrcMod_From_Common_ISA_Mod(modifier),
                Direct,
                preVarDcl->getRegVar(),
                rowOffset,
                colOffset,
                rd,
                type);
            break;
        }
    default:
        ASSERT_USER( false, "unsupported pre-defined variable");
    }

    m_builder->preDefVars.setHasPredefined(internalIndex, true);
    return tmpsrc;
}

void VISAKernelImpl::getHeightWidth(G4_Type type, unsigned int numberElements, unsigned short &dclWidth, unsigned short &dclHeight, int &totalByteSize)
{
    dclWidth = 1, dclHeight = 1;
    totalByteSize = numberElements * G4_Type_Table[type].byteSize;
    if( totalByteSize <= G4_GRF_REG_NBYTES )
    {
        dclWidth = (uint16_t)numberElements;
    }
    else{
        // here we assume that the start point of the var is the beginning of a GRF?
        // so subregister must be 0?
        dclWidth = G4_GRF_REG_NBYTES / G4_Type_Table[type].byteSize;
        dclHeight = totalByteSize / G4_GRF_REG_NBYTES;
        if( totalByteSize % G4_GRF_REG_NBYTES != 0 ){
            dclHeight++;
        }
    }
}

void VISAKernelImpl::setName(const char* n)
{
    if (!strcmp("", n)) return;
    m_cisa_kernel.name_index = addStringPool(n);
    m_name = m_string_pool[m_cisa_kernel.name_index];
    if(m_kernel != NULL)
    {
        this->m_kernel->setName(m_name.c_str());
    }
}

void VISAKernelImpl::setupRelocTable()
{
    IR_Builder* builder = getIRBuilder();

    if( getRelocTablePresent() &&
        builder != NULL)
    {
        unsigned int numVarRelocs = getVarRelocSize();
        reloc_symtab* varSymTab = (reloc_symtab*)alloc( sizeof(reloc_symtab) );
        varSymTab->num_syms = (uint16_t)numVarRelocs;
        varSymTab->reloc_syms = (reloc_sym*)alloc(numVarRelocs * sizeof(reloc_sym) );

        for( unsigned int i = 0; i < numVarRelocs; i++ )
        {
            unsigned int symIdx, resIdx;
            getVarRelocEntry(i, symIdx, resIdx);
            varSymTab->reloc_syms[i].symbolic_index = (uint16_t)symIdx;
            varSymTab->reloc_syms[i].resolved_index = (uint16_t)resIdx;
        }

        builder->setVarRelocTable(varSymTab);

        unsigned int numFuncRelocs = getFuncRelocSize();
        reloc_symtab* funcSymTab = (reloc_symtab*)alloc( sizeof(reloc_symtab) );
        funcSymTab->num_syms = (uint16_t)numFuncRelocs;
        funcSymTab->reloc_syms = (reloc_sym*)alloc(numFuncRelocs * sizeof(reloc_sym) );

        for( unsigned int i = 0; i < numFuncRelocs; i++ )
        {
            unsigned int symIdx, resIdx;
            getFuncRelocEntry(i, symIdx, resIdx);
            funcSymTab->reloc_syms[i].symbolic_index = (uint16_t)symIdx;
            funcSymTab->reloc_syms[i].resolved_index = (uint16_t)resIdx;
        }

        builder->setFuncRelocTable(funcSymTab);
    }
}

void VISAKernelImpl::setInputSize( uint8_t size )
{
    m_cisa_kernel.input_size = size;
}

void VISAKernelImpl::setReturnSize( unsigned int size )
{
    m_cisa_kernel.return_value_size = (uint8_t)size;
}

int VISAKernelImpl::SetFunctionInputSize(unsigned int size)
{
    setInputSize((uint8_t)size);
    return CM_SUCCESS;
}

int VISAKernelImpl::SetFunctionReturnSize(unsigned int size)
{
    setReturnSize(size);
    return CM_SUCCESS;
}

void VISAKernelImpl::addFileScopeVar(VISA_FileVar* filescopeVar, unsigned int index)
{
    // To be invoked only via fast path

    // Create G4_Declare in kernel
    filescope_var_info_t curVar = filescopeVar->fileVar;
    VISA_Type varType = (VISA_Type) (curVar.bit_properties & 0xf);
    G4_Type typeFS = Get_G4_Type_From_Common_ISA_Type(varType);

    unsigned short dclWidthFS = 1, dclHeightFS = 1;
    int totalByteSizeFS = 0;
    getHeightWidth(typeFS, curVar.num_elements, dclWidthFS, dclHeightFS, totalByteSizeFS);

    G4_Declare* dcl = getIRBuilder()->createDeclareNoLookup((const char *)curVar.name, G4_GRF, dclWidthFS, dclHeightFS, typeFS);
    dcl->setHasFileScope();

    VISA_Align align_bits= (VISA_Align) ((curVar.bit_properties >> 4) & 0x7);
    setDeclAlignment(dcl, align_bits);

    fileScopeMap[index] = dcl;
}

// common tasks for AppendVISAInst* functions
// currently we just increment the VISA offset to make sure it is set correctly for each GEN instruction
void VISAKernelImpl::AppendVISAInstCommon()
{
    this->m_vISAInstCount++;
    if (IS_GEN_BOTH_PATH)
    {
        m_builder->curCISAOffset = getvIsaInstCount();
    }
}

int VISAKernelImpl::getVISAOffset() const
{
    if (IS_GEN_BOTH_PATH)
    {
        return m_builder->curCISAOffset;
    }
    // ToDo: we should probably move vISA offset in VISKernelImpl so that we have it in vISA path too
    return -1;
}

void VISAKernelImpl::computeFCInfo(BinaryEncodingBase* binEncodingInstance)
{
    // This function iterates over all instructions in kernel and sets up data
    // structures used to emit FC patch file later on after compilation for
    // all kernels is complete.
    // This function should be invoked only after binary encoding pass.
    std::map<BinInst*, std::pair<G4_INST*, bool>> FCInstMap;
    G4_Kernel* kernel = getKernel();
    IR_Builder* builder = getIRBuilder();

    if(isFCCallerKernel() == false && isFCCallableKernel() == false)
    {
        // No need to do anything since the kernel doesnt
        // have any FC calls.
        return;
    }

    // First populate FCInstMap map that holds all pseudo_fc_call/ret
    // instructions in the kernel.
    BB_LIST_ITER bb_end = kernel->fg.BBs.end();
    for(BB_LIST_ITER bb_it = kernel->fg.BBs.begin();
        bb_it != bb_end;
        bb_it++)
    {
        G4_BB* bb = (*bb_it);

        INST_LIST_ITER inst_end = bb->end();
        for(INST_LIST_ITER inst_it = bb->begin();
            inst_it != inst_end;
            inst_it++)
        {
            G4_INST* inst = (*inst_it);
            G4_opcode opc = inst->opcode();

            if(opc == G4_pseudo_fc_call)
            {
                FCInstMap.insert(make_pair(inst->getBinInst(), make_pair(inst, true)));
            }
            else if(opc == G4_pseudo_fc_ret)
            {
                FCInstMap.insert(make_pair(inst->getBinInst(), make_pair(inst, false)));
            }
        }
    }

    BinInstList& binInstList = binEncodingInstance->getBinInstList();
    for (unsigned i = 0, size = (unsigned) binInstList.size(); i < size; i++)
    {
        BinInst* bin = binInstList[i];

        std::map<BinInst*, std::pair<G4_INST*, bool>>::iterator fcMapIt = FCInstMap.find(bin);

        if(fcMapIt != FCInstMap.end())
        {
            if(fcMapIt->second.second == true)
            {
                // pseudo_fc_call
                FCCalls* callToPatch = (FCCalls*)builder->mem.alloc(sizeof(FCCalls));
                callToPatch->callOffset = i;
                unsigned int strLength = (uint32_t) strlen(((G4_Label*)(fcMapIt->second.first->getSrc(0)))->getLabel());
                char* labelString = (char*)builder->mem.alloc(strLength + 1);

                strcpy_s(labelString, strLength + 1, ((G4_Label*)(fcMapIt->second.first->getSrc(0)))->getLabel());

                callToPatch->calleeLabelString = labelString;

                builder->getFCPatchInfo()->getFCCallsToPatch().push_back(callToPatch);
            }
            else
            {
                // pseduo_fc_ret
                builder->getFCPatchInfo()->getFCReturnsToPatch().push_back(i);
            }
        }
    }
}

void VISAKernelImpl::computeFCInfo() {
    // This function iterates over all instructions in kernel and sets up data
    // structures used to emit FC patch file later on after compilation for
    // all kernels is complete.
    // This function should be invoked only after binary encoding pass.
    G4_Kernel* kernel = getKernel();
    IR_Builder* builder = getIRBuilder();

    if (isFCCallerKernel() == false && isFCCallableKernel() == false) {
        // No need to do anything since the kernel doesnt
        // have any FC calls.
        return;
    }

    // First populate FCInstMap map that holds all pseudo_fc_call/ret
    // instructions in the kernel.
    BB_LIST_ITER bb_end = kernel->fg.BBs.end();
    for (BB_LIST_ITER bb_it = kernel->fg.BBs.begin();
        bb_it != bb_end;
        bb_it++) {
        G4_BB* bb = (*bb_it);

        INST_LIST_ITER inst_end = bb->end();
        for (INST_LIST_ITER inst_it = bb->begin();
            inst_it != inst_end;
            inst_it++) {
            G4_INST* inst = (*inst_it);
            G4_opcode opc = inst->opcode();

            if(opc == G4_pseudo_fc_call) {
                // TODO: Need to create FCCalls and push into calls-to-patch.
                // FCInstMap.insert(make_pair(inst->getBinInst(), make_pair(inst, true)));
                ASSERT_USER(inst->getGenOffset() % 16 == 0, "Non-128-bit instruction is found!");
                unsigned Slot = unsigned(inst->getGenOffset()) / 16;
                FCCalls *CallToPatch = (FCCalls *)builder->mem.alloc(sizeof(FCCalls));
                CallToPatch->callOffset = Slot;
                G4_Label *Label = inst->getSrc(0)->asLabel();
                size_t Len = strlen(Label->getLabel());
                char *S = (char *)builder->mem.alloc(Len + 1);
                strcpy_s(S, Len + 1, Label->getLabel());
                CallToPatch->calleeLabelString = S;
                builder->getFCPatchInfo()->getFCCallsToPatch().push_back(CallToPatch);
            } else if (opc == G4_pseudo_fc_ret) {
                ASSERT_USER(inst->getGenOffset() % 16 == 0, "Non-128-bit instruction is found!");
                unsigned Slot = unsigned(inst->getGenOffset()) / 16;
                builder->getFCPatchInfo()->getFCReturnsToPatch().push_back(Slot);
            }
        }
    }
}


///Gets declaration id GenVar
int VISAKernelImpl::getDeclarationID(VISA_GenVar *decl)
{
    return decl->index;
}

///Gets declaration id VISA_AddrVar
int VISAKernelImpl::getDeclarationID(VISA_AddrVar *decl)
{
    return decl->index;
}

///Gets declaration id VISA_PredVar
int VISAKernelImpl::getDeclarationID(VISA_PredVar *decl)
{
    return decl->index;
}

///Gets declaration id VISA_SamplerVar
int VISAKernelImpl::getDeclarationID(VISA_SamplerVar *decl)
{
    return decl->index;
}

///Gets declaration id VISA_SurfaceVar
int VISAKernelImpl::getDeclarationID(VISA_SurfaceVar *decl)
{
    return decl->index;
}

///Gets declaration id VISA_VMEVar
int VISAKernelImpl::getDeclarationID(VISA_VMEVar *decl)
{
    return decl->index;
}

///Gets declaration id VISA_LabelVar
int VISAKernelImpl::getDeclarationID(VISA_LabelVar *decl)
{
    return decl->index;
}

///Gets declaration id VISA_FileVar
int VISAKernelImpl::getDeclarationID(VISA_FileVar *decl)
{
    return decl->index;
}

int64_t VISAKernelImpl::getGenOffset()
{
    assert(m_kernel->fg.BBs.begin() != m_kernel->fg.BBs.end());
    assert((*m_kernel->fg.BBs.begin())->begin() != (*m_kernel->fg.BBs.begin())->end());
    // the offset of the first gen inst in this kernel/function
    return (*(*m_kernel->fg.BBs.begin())->begin())->getGenOffset();
}

void VISAKernelImpl::computeAndEmitDebugInfo(std::list<VISAKernelImpl*>& functions)
{
    std::list<VISAKernelImpl*> compilationUnitsForDebugInfo;
    compilationUnitsForDebugInfo.push_back(this);
    auto funcEndIt = functions.end();
    for(auto funcIt = functions.begin();
        funcIt != funcEndIt;
        funcIt++)
    {
        compilationUnitsForDebugInfo.push_back((*funcIt));
    }

    std::list<G4_BB*> stackCallEntryBBs;
    auto cunitsEnd = compilationUnitsForDebugInfo.end();
    for(auto cunitsIt = compilationUnitsForDebugInfo.begin();
        cunitsIt != cunitsEnd;
        cunitsIt++)
    {
        VISAKernelImpl* cunit = (*cunitsIt);
        if(cunit->getIsKernel() == false)
        {
            stackCallEntryBBs.push_back(cunit->getKernel()->fg.getEntryBB());
        }
    }

    for(auto cunitsIt = compilationUnitsForDebugInfo.begin();
        cunitsIt != cunitsEnd;
        cunitsIt++)
    {
        G4_Kernel& curKernel = *(*cunitsIt)->getKernel();
        curKernel.getKernelDebugInfo()->computeDebugInfo(stackCallEntryBBs);
    }

#ifndef DLL_MODE
    if (getOptions()->getOption(vISA_outputToFile))
    {
        std::string asmNameStr = this->getAsmName();
        std::string debugFileNameStr = asmNameStr + ".dbg";
        emitDebugInfo(this, functions, debugFileNameStr);
    }
#else
    void* ptr;
    unsigned size;
    emitDebugInfoToMem(this, functions, ptr, size);
    setGenxDebugInfoBuffer((char*)ptr, size);
#endif
}

void VISAKernelImpl::computeAllRelocs(unsigned int& numRelocs, BasicRelocEntry*& output)
{
    vector<BasicRelocEntry> relocs;

    for (auto bbs : getKernel()->fg.BBs)
    {
        for (auto insts : *bbs)
        {
            for (auto i = 0; i < insts->getNumSrc(); i++)
            {
                auto opnd = insts->getSrc(i);

                if (opnd &&
                    opnd->isRelocImm())
                {
                    BasicRelocEntry newReloc;
                    G4_Reloc_Imm* relocImmOpnd = (G4_Reloc_Imm*)opnd;
                    newReloc.relocOffset = (uint64_t)relocImmOpnd->getRelocInfo().nativeOffset;
                    newReloc.info = relocImmOpnd->getRelocInfo().input.info;
                    newReloc.addend = relocImmOpnd->getRelocInfo().input.addend;
                    relocs.push_back(newReloc);
                }
            }
        }
    }

    numRelocs = (uint32_t) relocs.size();
    if (numRelocs > 0)
    {
        output = (BasicRelocEntry*)allocCodeBlock(sizeof(BasicRelocEntry) * numRelocs);
        if (!output)
        {
            numRelocs = 0;
            return;
        }
        for (unsigned int idx = 0; idx < numRelocs; idx++)
        {
            output[idx].relocOffset = relocs[idx].relocOffset;
            output[idx].info = relocs[idx].info;
            output[idx].addend = relocs[idx].addend;
            idx++;
        }
    }
}

void VISAKernelImpl::emitAllRelocs(unsigned int numRelocs, BasicRelocEntry* relocs)
{
    if (numRelocs == 0 || relocs == nullptr)
        return;

    FILE* fp;
    const char* buf = nullptr;
    getOptions()->getOption(vISA_RelocFilename, buf);

    std::string fname;
    if (buf != nullptr)
    {
        fname = std::string(buf);
    }

    fname += getName();
    fname += "_out";

    fp = fopen(fname.c_str(), "wb");
    fwrite(relocs, sizeof(BasicRelocEntry), numRelocs, fp);
    fclose(fp);
}

extern "C" void freeBlock(void* ptr);

void VISAKernelImpl::computeAndEmitGenRelocs()
{
    unsigned int numRelocs;
    BasicRelocEntry* relocs = nullptr;

    computeAllRelocs(numRelocs, relocs);
    emitAllRelocs(numRelocs, relocs);

    freeBlock(relocs);
}

bool VISAKernelImpl::getIntKernelAttributeValue(const char* attrName, int& value)
{
    // Iterate over all kernel attributes and return true if name found and is
    // of type int. Return value if found.
    for (auto it : m_attribute_info_list)
    {
        if (it->isInt)
        {
            if (strcmp(m_string_pool[it->nameIndex].c_str(), attrName) == 0)
            {
                value = it->value.intVal;
                return true;
            }
        }
    }

    return false;
}

// buf contains instance of gtpin_init_t
bool enableSrcLine(void* buf)
{
    if (!buf)
        return false;

    auto gtpin_init_data = (gtpin::igc::igc_init_t*)buf;
    return gtpin_init_data->srcline_mapping != 0;
}
