97 строки
3.2 KiB
C++
97 строки
3.2 KiB
C++
//===-- 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<unsigned>
|
|
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<Argument>(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<AtomicRMWInst>(V) || isa<AtomicCmpXchgInst>(V))
|
|
return true;
|
|
|
|
if (const CallInst *CI = dyn_cast<CallInst>(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;
|
|
}
|