Skip to content

Commit 800b9c6

Browse files
srividyakarumuriZuul
authored andcommitted
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)