Skip to content

Commit 800b9c6

Browse files
srividyakarumuriZuul
authored and
Zuul
committed
Supporting vector types in constant folding
Few refactoring related to moving functions that are used in multiple passes into helper.cpp/.h Added support for vector type in constant folding and in finding interesting constants Change-Id: I4ebf93c3c508eec79429e7f4bc916d39f0c57d16
1 parent 6069a55 commit 800b9c6

File tree

7 files changed

+282
-156
lines changed

7 files changed

+282
-156
lines changed

IGC/Compiler/CISACodeGen/helper.cpp

Lines changed: 108 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -344,13 +344,15 @@ namespace IGC
344344
instList.push_back(baseValue);
345345
}
346346

347-
unsigned bufId = 0;
348-
IGC::BufferType bufTy = BUFFER_TYPE_UNKNOWN;
349-
IGC::BufferAccessType accessTy = BUFFER_ACCESS_TYPE_UNKNOWN;
350-
if (GetResourcePointerInfo(baseValue, bufId, bufTy, accessTy))
347+
if (GenIntrinsicInst * inst = dyn_cast<GenIntrinsicInst>(baseValue))
351348
{
352-
srcPtr = baseValue;
353-
break;
349+
// For bindless pointers
350+
if ((inst->getIntrinsicID() == GenISAIntrinsic::GenISA_RuntimeValue) ||
351+
(inst->getIntrinsicID() == GenISAIntrinsic::GenISA_GetBufferPtr))
352+
{
353+
srcPtr = baseValue;
354+
break;
355+
}
354356
}
355357
else if (isa<Argument>(baseValue))
356358
{
@@ -539,6 +541,106 @@ namespace IGC
539541
return false;
540542
}
541543

544+
// Get GRF offset from GenISA_RuntimeValue intrinsic call
545+
bool GetGRFOffsetFromRTV(Value* pointerSrc, unsigned& GRFOffset)
546+
{
547+
if (GenIntrinsicInst * inst = dyn_cast<GenIntrinsicInst>(pointerSrc))
548+
{
549+
// For bindless pointers with encoded metadata
550+
if (inst->getIntrinsicID() == GenISAIntrinsic::GenISA_RuntimeValue)
551+
{
552+
GRFOffset = (unsigned)llvm::cast<llvm::ConstantInt>(inst->getOperand(0))->getZExtValue();
553+
return true;
554+
}
555+
}
556+
return false;
557+
}
558+
559+
bool GetStatelessBufferInfo(Value* pointer, unsigned& bufIdOrGRFOffset,
560+
BufferType & bufferTy, Value*& bufferSrcPtr, bool& isDirectBuf)
561+
{
562+
isDirectBuf = false;
563+
// If the buffer info is not encoded in the address space, we can still find it by
564+
// tracing the pointer to where it's created.
565+
Value * src = IGC::TracePointerSource(pointer);
566+
BufferAccessType accType;
567+
if (!src) return false;
568+
if (IGC::GetResourcePointerInfo(src, bufIdOrGRFOffset, bufferTy, accType))
569+
{
570+
bufferSrcPtr = src;
571+
isDirectBuf = true;
572+
return true;
573+
}
574+
else if (GetGRFOffsetFromRTV(src, bufIdOrGRFOffset))
575+
{
576+
bufferSrcPtr = src;
577+
bufferTy = BUFFER_TYPE_UNKNOWN;
578+
return true;
579+
}
580+
return false;
581+
}
582+
583+
bool EvalConstantAddress(Value* address, unsigned int& offset, const llvm::DataLayout* pDL, Value* ptrSrc)
584+
{
585+
if ((ptrSrc == nullptr && isa<ConstantPointerNull>(address)) ||
586+
(ptrSrc == address))
587+
{
588+
offset = 0;
589+
return true;
590+
}
591+
else if (Instruction * ptrExpr = dyn_cast<Instruction>(address))
592+
{
593+
if (ptrExpr->getOpcode() == Instruction::BitCast ||
594+
ptrExpr->getOpcode() == Instruction::AddrSpaceCast)
595+
{
596+
return EvalConstantAddress(ptrExpr->getOperand(0), offset, pDL, ptrSrc);
597+
}
598+
if (ptrExpr->getOpcode() == Instruction::IntToPtr)
599+
{
600+
Value * eltIdxVal = ptrExpr->getOperand(0);
601+
ConstantInt * eltIdx = dyn_cast<ConstantInt>(eltIdxVal);
602+
if (!eltIdx)
603+
return false;
604+
offset = int_cast<unsigned>(eltIdx->getZExtValue());
605+
return true;
606+
}
607+
else if (ptrExpr->getOpcode() == Instruction::GetElementPtr)
608+
{
609+
offset = 0;
610+
if (!EvalConstantAddress(ptrExpr->getOperand(0), offset, pDL, ptrSrc))
611+
{
612+
return false;
613+
}
614+
Type * Ty = ptrExpr->getType();
615+
gep_type_iterator GTI = gep_type_begin(ptrExpr);
616+
for (auto OI = ptrExpr->op_begin() + 1, E = ptrExpr->op_end(); OI != E; ++OI, ++GTI) {
617+
Value * Idx = *OI;
618+
if (StructType * StTy = GTI.getStructTypeOrNull()) {
619+
unsigned Field = int_cast<unsigned>(cast<ConstantInt>(Idx)->getZExtValue());
620+
if (Field) {
621+
offset += int_cast<unsigned int>(pDL->getStructLayout(StTy)->getElementOffset(Field));
622+
}
623+
Ty = StTy->getElementType(Field);
624+
}
625+
else {
626+
Ty = GTI.getIndexedType();
627+
if (const ConstantInt * CI = dyn_cast<ConstantInt>(Idx)) {
628+
offset += int_cast<unsigned int>(
629+
pDL->getTypeAllocSize(Ty) * CI->getSExtValue());
630+
631+
}
632+
else
633+
{
634+
return false;
635+
}
636+
}
637+
}
638+
return true;
639+
}
640+
}
641+
return false;
642+
}
643+
542644
///
543645
/// Wrapper method for changing PTRType for PromoteToBindless Pass.
544646
/// Replaces oldPtr with newPtr in a sample/ld intrinsic's argument list. The new instrinsic will

IGC/Compiler/CISACodeGen/helper.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,12 @@ namespace IGC
152152
llvm::Value* TracePointerSource(llvm::Value* resourcePtr);
153153
llvm::Value* TracePointerSource(llvm::Value* resourcePtr, bool hasBranching, bool fillList, std::vector<llvm::Value*>& instList);
154154
llvm::Value* TracePointerSource(llvm::Value* resourcePtr, bool hasBranching, bool fillList, std::vector<llvm::Value*>& instList, llvm::SmallSet<llvm::PHINode*, 8> & visitedPHIs);
155-
bool GetResourcePointerInfo(llvm::Value* srcPtr, unsigned& resID,
156-
IGC::BufferType& resTy, IGC::BufferAccessType& accessTy);
155+
bool GetResourcePointerInfo(llvm::Value* srcPtr, unsigned& resID, IGC::BufferType& resTy, IGC::BufferAccessType& accessTy);
156+
bool GetGRFOffsetFromRTV(llvm::Value* pointerSrc, unsigned& GRFOffset);
157+
bool GetStatelessBufferInfo(llvm::Value* pointer, unsigned& bufIdOrGRFOffset, IGC::BufferType& bufferTy, llvm::Value*& bufferSrcPtr, bool& isDirectBuf);
158+
// try to evaluate the address if it is constant.
159+
bool EvalConstantAddress(llvm::Value* address, unsigned int& offset, const llvm::DataLayout* pDL, llvm::Value* ptrSrc = nullptr);
160+
157161

158162
bool isSampleLoadGather4InfoInstruction(llvm::Instruction* inst);
159163
bool isSampleInstruction(llvm::Instruction* inst);

IGC/Compiler/CustomSafeOptPass.cpp

Lines changed: 88 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -2096,107 +2096,81 @@ static Constant* GetConstantValue(Type* type, char* rawData)
20962096
return nullptr;
20972097
}
20982098

2099-
bool IGCConstProp::EvalConstantAddress(Value* address, unsigned int& offset, Value* ptrSrc)
2099+
Constant* IGCConstProp::ReplaceFromDynConstants(unsigned bufId, unsigned eltId, unsigned int size_in_bytes, LoadInst* inst)
21002100
{
2101-
if ((ptrSrc == nullptr && isa<ConstantPointerNull>(address)) ||
2102-
(ptrSrc == address))
2103-
{
2104-
offset = 0;
2105-
return true;
2106-
}
2107-
else if (Instruction * ptrExpr = dyn_cast<Instruction>(address))
2101+
Type* type = inst->getType();
2102+
2103+
CodeGenContext* ctx = getAnalysis<CodeGenContextWrapper>().getCodeGenContext();
2104+
ModuleMetaData* modMD = ctx->getModuleMetaData();
2105+
2106+
// Handling for base types (Integer/FloatingPoint)
2107+
if (!(type->isVectorTy()))
21082108
{
2109-
if (ptrExpr->getOpcode() == Instruction::BitCast ||
2110-
ptrExpr->getOpcode() == Instruction::AddrSpaceCast)
2111-
{
2112-
return EvalConstantAddress(ptrExpr->getOperand(0), offset, ptrSrc);
2113-
}
2114-
if (ptrExpr->getOpcode() == Instruction::IntToPtr)
2115-
{
2116-
Value* eltIdxVal = ptrExpr->getOperand(0);
2117-
ConstantInt* eltIdx = dyn_cast<ConstantInt>(eltIdxVal);
2118-
if (!eltIdx)
2119-
return false;
2120-
offset = int_cast<unsigned>(eltIdx->getZExtValue());
2121-
return true;
2122-
}
2123-
else if (ptrExpr->getOpcode() == Instruction::GetElementPtr)
2109+
ConstantAddress cl;
2110+
cl.bufId = bufId;
2111+
cl.eltId = eltId;
2112+
cl.size = size_in_bytes;
2113+
2114+
// Inline the constants for constant buffer accesses of size <= 32bit only.
2115+
if (size_in_bytes > 4)
2116+
return nullptr;
2117+
2118+
auto it = modMD->inlineDynConstants.find(cl);
2119+
if (it != modMD->inlineDynConstants.end() && (it->first.size == cl.size))
21242120
{
2125-
offset = 0;
2126-
if (!EvalConstantAddress(ptrExpr->getOperand(0), offset, ptrSrc))
2127-
{
2128-
return false;
2129-
}
2130-
Type* Ty = ptrExpr->getType();
2131-
gep_type_iterator GTI = gep_type_begin(ptrExpr);
2132-
for (auto OI = ptrExpr->op_begin() + 1, E = ptrExpr->op_end(); OI != E; ++OI, ++GTI) {
2133-
Value* Idx = *OI;
2134-
if (StructType * StTy = GTI.getStructTypeOrNull()) {
2135-
unsigned Field = int_cast<unsigned>(cast<ConstantInt>(Idx)->getZExtValue());
2136-
if (Field) {
2137-
offset += int_cast<unsigned int>(m_TD->getStructLayout(StTy)->getElementOffset(Field));
2138-
}
2139-
Ty = StTy->getElementType(Field);
2140-
}
2141-
else {
2142-
Ty = GTI.getIndexedType();
2143-
if (const ConstantInt * CI = dyn_cast<ConstantInt>(Idx)) {
2144-
offset += int_cast<unsigned int>(
2145-
m_TD->getTypeAllocSize(Ty) * CI->getSExtValue());
2146-
}
2147-
else
2148-
{
2149-
return false;
2150-
}
2151-
}
2152-
}
2153-
return true;
2121+
// This constant is
2122+
// found in the Dynamic inline constants list, and
2123+
// sizes match (find only looking for bufId and eltId, so need to compare size field explicitly)
2124+
char* pConstVal;
2125+
pConstVal = (char*)(&(it->second));
2126+
return GetConstantValue(type, pConstVal);
21542127
}
21552128
}
2156-
return false;
2157-
}
2158-
2159-
bool GetStatelessBufferInfo(Value* pointer, unsigned& bufferId,
2160-
BufferType& bufferTy, Value*& bufferSrcPtr)
2161-
{
2162-
// If the buffer info is not encoded in the address space, we can still find it by
2163-
// tracing the pointer to where it's created.
2164-
Value* src = IGC::TracePointerSource(pointer);
2165-
BufferAccessType accType;
2166-
if (src && IGC::GetResourcePointerInfo(src, bufferId, bufferTy, accType))
2129+
else
21672130
{
2168-
bufferSrcPtr = src;
2169-
return true;
2170-
}
2171-
return false;
2172-
}
2131+
Type * srcEltTy = type->getVectorElementType();
2132+
uint32_t srcNElts = type->getVectorNumElements();
2133+
uint32_t eltSize_in_bytes = srcEltTy->getPrimitiveSizeInBits() / 8;
2134+
std::vector<uint32_t> constValVec;
21732135

2174-
Constant* IGCConstProp::ReplaceFromDynConstants(unsigned bufId, unsigned eltId, unsigned int size_in_bytes, Type* type)
2175-
{
2176-
ConstantAddress cl;
2177-
char* pConstVal;
2178-
cl.bufId = bufId;
2179-
cl.eltId = eltId;
2180-
cl.size = size_in_bytes;
2136+
if (eltSize_in_bytes > 4)
2137+
return nullptr;
21812138

2182-
CodeGenContext* ctx = getAnalysis<CodeGenContextWrapper>().getCodeGenContext();
2183-
ModuleMetaData* modMD = ctx->getModuleMetaData();
2139+
// First make sure all elements of vector are available in the dynamic inline constants
2140+
// If not, we cannot inline the vector
2141+
for (uint i = 0; i < srcNElts; i++)
2142+
{
2143+
ConstantAddress cl;
2144+
cl.bufId = bufId;
2145+
cl.eltId = eltId + (i * eltSize_in_bytes);
2146+
cl.size = eltSize_in_bytes;
21842147

2185-
auto it = modMD->inlineDynConstants.find(cl);
2186-
if ((it != modMD->inlineDynConstants.end()) && (it->first.size == cl.size))
2187-
{
2188-
// For constant buffer accesses of size <= 32bit.
2189-
if (size_in_bytes <= 4)
2148+
auto it = modMD->inlineDynConstants.find(cl);
2149+
if (it != modMD->inlineDynConstants.end() && (it->first.size == cl.size))
2150+
{
2151+
constValVec.push_back(it->second);
2152+
}
2153+
else
2154+
{
2155+
// All elements of the vector has to be available for inlining,
2156+
// otherwise we cannot replace the load instruction, hence return nullptr
2157+
return nullptr;
2158+
}
2159+
}
2160+
if (constValVec.size() == srcNElts)
21902161
{
2191-
// This constant is
2192-
// found in the Dynamic inline constants list, and
2193-
// sizes match (find only looking for bufId and eltId, so need to look for size explicitly)
2194-
if (!(type->isVectorTy()))
2162+
IRBuilder<> builder(inst);
2163+
Value * vectorValue = UndefValue::get(inst->getType());
2164+
for (uint i = 0; i < srcNElts; i++)
21952165
{
2196-
// Handling for base types (Integer/FloatingPoint)
2197-
pConstVal = (char*)(&(it->second));
2198-
return GetConstantValue(type, pConstVal);
2166+
char* pConstVal;
2167+
pConstVal = (char*)(&(constValVec[i]));
2168+
vectorValue = builder.CreateInsertElement(
2169+
vectorValue,
2170+
GetConstantValue(srcEltTy, pConstVal),
2171+
builder.getInt32(i));
21992172
}
2173+
return dyn_cast<Constant>(vectorValue);
22002174
}
22012175
}
22022176
return nullptr;
@@ -2206,7 +2180,8 @@ Constant* IGCConstProp::replaceShaderConstant(LoadInst* inst)
22062180
{
22072181
unsigned as = inst->getPointerAddressSpace();
22082182
bool directBuf = false;
2209-
unsigned bufId = 0;
2183+
bool statelessBuf = false;
2184+
unsigned bufIdOrGRFOffset = 0;
22102185
unsigned int size_in_bytes = 0;
22112186
CodeGenContext* ctx = getAnalysis<CodeGenContextWrapper>().getCodeGenContext();
22122187
ModuleMetaData* modMD = ctx->getModuleMetaData();
@@ -2216,32 +2191,47 @@ Constant* IGCConstProp::replaceShaderConstant(LoadInst* inst)
22162191

22172192
if (as == ADDRESS_SPACE_CONSTANT)
22182193
{
2219-
if (!GetStatelessBufferInfo(inst->getPointerOperand(), bufId, bufType, pointerSrc))
2194+
if (!GetStatelessBufferInfo(inst->getPointerOperand(), bufIdOrGRFOffset, bufType, pointerSrc, directBuf))
22202195
{
22212196
return nullptr;
22222197
}
2223-
directBuf = true;
2198+
if (!directBuf)
2199+
{
2200+
// Make sure constant folding is safe by looking up in pushableAddresses
2201+
CodeGenContext* ctx = getAnalysis<CodeGenContextWrapper>().getCodeGenContext();
2202+
PushInfo& pushInfo = ctx->getModuleMetaData()->pushInfo;
2203+
2204+
for (auto it : pushInfo.pushableAddresses)
2205+
{
2206+
if (bufIdOrGRFOffset * 4 == it.addressOffset && it.isStatic)
2207+
{
2208+
statelessBuf = true;
2209+
break;
2210+
}
2211+
}
2212+
}
22242213
}
22252214
else
22262215
{
2227-
bufType = IGC::DecodeAS4GFXResource(as, directBuf, bufId);
2216+
bufType = IGC::DecodeAS4GFXResource(as, directBuf, bufIdOrGRFOffset);
22282217
}
22292218

2230-
if (bufType == CONSTANT_BUFFER &&
2231-
directBuf && modMD)
2219+
// If it is statelessBuf, we made sure it is a constant buffer by finding it in pushableAddresses
2220+
if (modMD && ((directBuf && (bufType == CONSTANT_BUFFER)) || statelessBuf))
22322221
{
22332222
Value* ptrVal = inst->getPointerOperand();
22342223
unsigned eltId = 0;
22352224
size_in_bytes = inst->getType()->getPrimitiveSizeInBits() / 8;
2236-
if (!EvalConstantAddress(ptrVal, eltId, pointerSrc))
2225+
if (!EvalConstantAddress(ptrVal, eltId, m_TD, pointerSrc))
22372226
{
22382227
return nullptr;
22392228
}
22402229

22412230
if (size_in_bytes)
22422231
{
22432232
if (modMD->immConstant.data.size() &&
2244-
(bufId == modMD->pushInfo.inlineConstantBufferSlot))
2233+
((statelessBuf && (bufIdOrGRFOffset == modMD->pushInfo.inlineConstantBufferGRFOffset))||
2234+
(directBuf && (bufIdOrGRFOffset == modMD->pushInfo.inlineConstantBufferSlot))))
22452235
{
22462236
char* offset = &(modMD->immConstant.data[0]);
22472237
if (inst->getType()->isVectorTy())
@@ -2267,7 +2257,7 @@ Constant* IGCConstProp::replaceShaderConstant(LoadInst* inst)
22672257
}
22682258
else if ((!IGC_IS_FLAG_ENABLED(DisableDynamicConstantFolding)) && (modMD->inlineDynConstants.size() > 0))
22692259
{
2270-
return ReplaceFromDynConstants(bufId, eltId, size_in_bytes, inst->getType());
2260+
return ReplaceFromDynConstants(bufIdOrGRFOffset, eltId, size_in_bytes, inst);
22712261
}
22722262
}
22732263
}

0 commit comments

Comments
 (0)