//===-- DxilTargetTransformInfo.cpp - DXIL specific TTI pass ----------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // \file // This file implements a TargetTransformInfo analysis pass specific to the // DXIL. Only implemented isSourceOfDivergence for DivergenceAnalysis. // //===----------------------------------------------------------------------===// #include "DxilTargetTransformInfo.h" #include "dxc/DXIL/DxilModule.h" #include "dxc/DXIL/DxilOperations.h" #include "llvm/CodeGen/BasicTTIImpl.h" using namespace llvm; using namespace hlsl; #define DEBUG_TYPE "DXILtti" // For BasicTTImpl cl::opt llvm::PartialUnrollingThreshold("partial-unrolling-threshold", cl::init(0), cl::desc("Threshold for partial unrolling"), cl::Hidden); DxilTTIImpl::DxilTTIImpl(const TargetMachine *TM, const Function &F, hlsl::DxilModule &DM, bool ThreadGroup) : BaseT(TM, F.getParent()->getDataLayout()), m_pHlslOP(DM.GetOP()), m_isThreadGroup(ThreadGroup) {} namespace { bool IsDxilOpSourceOfDivergence(const CallInst *CI, OP *hlslOP, bool ThreadGroup) { DXIL::OpCode opcode = hlslOP->GetDxilOpFuncCallInst(CI); switch (opcode) { case DXIL::OpCode::AtomicBinOp: case DXIL::OpCode::AtomicCompareExchange: case DXIL::OpCode::LoadInput: case DXIL::OpCode::BufferUpdateCounter: case DXIL::OpCode::CycleCounterLegacy: case DXIL::OpCode::DomainLocation: case DXIL::OpCode::Coverage: case DXIL::OpCode::EvalCentroid: case DXIL::OpCode::EvalSampleIndex: case DXIL::OpCode::EvalSnapped: case DXIL::OpCode::FlattenedThreadIdInGroup: case DXIL::OpCode::GSInstanceID: case DXIL::OpCode::InnerCoverage: case DXIL::OpCode::LoadOutputControlPoint: case DXIL::OpCode::LoadPatchConstant: case DXIL::OpCode::OutputControlPointID: case DXIL::OpCode::PrimitiveID: case DXIL::OpCode::RenderTargetGetSampleCount: case DXIL::OpCode::RenderTargetGetSamplePosition: case DXIL::OpCode::ThreadId: case DXIL::OpCode::ThreadIdInGroup: return true; case DXIL::OpCode::GroupId: return !ThreadGroup; default: return false; } } } /// /// \returns true if the result of the value could potentially be /// different across dispatch or thread group. bool DxilTTIImpl::isSourceOfDivergence(const Value *V) const { if (dyn_cast(V)) return true; // Atomics are divergent because they are executed sequentially: when an // atomic operation refers to the same address in each thread, then each // thread after the first sees the value written by the previous thread as // original value. if (isa(V) || isa(V)) return true; if (const CallInst *CI = dyn_cast(V)) { // Assume none dxil instrincis function calls are a source of divergence. if (!m_pHlslOP->IsDxilOpFuncCallInst(CI)) return true; return IsDxilOpSourceOfDivergence(CI, m_pHlslOP, m_isThreadGroup); } return false; }