Skip to content

Commit 3ed2a81

Browse files
[SPIR-V] Fix issue #120078 and simplifies parsing of floating point decoration tips in demangled function name (#120128)
This PR fixes #120078 and improves/simplifies parsing of demangled function name that aims to detect a tip for floating point decorations. The latter improvement fixes also a complaint from `LLVM_USE_SANITIZER=Address`.
1 parent 3bcfa1a commit 3ed2a81

9 files changed

+110
-42
lines changed

llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ using namespace InstructionSet;
174174
namespace SPIRV {
175175
/// Parses the name part of the demangled builtin call.
176176
std::string lookupBuiltinNameHelper(StringRef DemangledCall,
177-
std::string *Postfix) {
177+
FPDecorationId *DecorationId) {
178178
const static std::string PassPrefix = "(anonymous namespace)::";
179179
std::string BuiltinName;
180180
// Itanium Demangler result may have "(anonymous namespace)::" prefix
@@ -232,12 +232,16 @@ std::string lookupBuiltinNameHelper(StringRef DemangledCall,
232232
"ReadClockKHR|SubgroupBlockReadINTEL|SubgroupImageBlockReadINTEL|"
233233
"SubgroupImageMediaBlockReadINTEL|SubgroupImageMediaBlockWriteINTEL|"
234234
"Convert|"
235-
"UConvert|SConvert|FConvert|SatConvert).*)_R(.*)");
235+
"UConvert|SConvert|FConvert|SatConvert).*)_R[^_]*_?(\\w+)?.*");
236236
std::smatch Match;
237-
if (std::regex_match(BuiltinName, Match, SpvWithR) && Match.size() > 3) {
238-
BuiltinName = Match[1].str();
239-
if (Postfix)
240-
*Postfix = Match[3].str();
237+
if (std::regex_match(BuiltinName, Match, SpvWithR) && Match.size() > 1) {
238+
std::ssub_match SubMatch;
239+
if (DecorationId && Match.size() > 3) {
240+
SubMatch = Match[3];
241+
*DecorationId = demangledPostfixToDecorationId(SubMatch.str());
242+
}
243+
SubMatch = Match[1];
244+
BuiltinName = SubMatch.str();
241245
}
242246

243247
return BuiltinName;

llvm/lib/Target/SPIRV/SPIRVBuiltins.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ namespace llvm {
2121
namespace SPIRV {
2222
/// Parses the name part of the demangled builtin call.
2323
std::string lookupBuiltinNameHelper(StringRef DemangledCall,
24-
std::string *Postfix = nullptr);
24+
FPDecorationId *DecorationId = nullptr);
2525
/// Lowers a builtin function call using the provided \p DemangledCall skeleton
2626
/// and external instruction \p Set.
2727
///

llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1876,18 +1876,6 @@ bool SPIRVEmitIntrinsics::insertAssignPtrTypeIntrs(Instruction *I,
18761876
return true;
18771877
}
18781878

1879-
static unsigned roundingModeMDToDecorationConst(StringRef S) {
1880-
if (S == "rte")
1881-
return SPIRV::FPRoundingMode::FPRoundingMode::RTE;
1882-
if (S == "rtz")
1883-
return SPIRV::FPRoundingMode::FPRoundingMode::RTZ;
1884-
if (S == "rtp")
1885-
return SPIRV::FPRoundingMode::FPRoundingMode::RTP;
1886-
if (S == "rtn")
1887-
return SPIRV::FPRoundingMode::FPRoundingMode::RTN;
1888-
return std::numeric_limits<unsigned>::max();
1889-
}
1890-
18911879
void SPIRVEmitIntrinsics::insertAssignTypeIntrs(Instruction *I,
18921880
IRBuilder<> &B) {
18931881
// TODO: extend the list of functions with known result types
@@ -1905,9 +1893,10 @@ void SPIRVEmitIntrinsics::insertAssignTypeIntrs(Instruction *I,
19051893
Function *CalledF = CI->getCalledFunction();
19061894
std::string DemangledName =
19071895
getOclOrSpirvBuiltinDemangledName(CalledF->getName());
1908-
std::string Postfix;
1896+
FPDecorationId DecorationId = FPDecorationId::NONE;
19091897
if (DemangledName.length() > 0)
1910-
DemangledName = SPIRV::lookupBuiltinNameHelper(DemangledName, &Postfix);
1898+
DemangledName =
1899+
SPIRV::lookupBuiltinNameHelper(DemangledName, &DecorationId);
19111900
auto ResIt = ResTypeWellKnown.find(DemangledName);
19121901
if (ResIt != ResTypeWellKnown.end()) {
19131902
IsKnown = true;
@@ -1919,18 +1908,29 @@ void SPIRVEmitIntrinsics::insertAssignTypeIntrs(Instruction *I,
19191908
break;
19201909
}
19211910
}
1922-
// check if a floating rounding mode info is present
1923-
StringRef S = Postfix;
1924-
SmallVector<StringRef, 8> Parts;
1925-
S.split(Parts, "_", -1, false);
1926-
if (Parts.size() > 1) {
1927-
// Convert the info about rounding mode into a decoration record.
1928-
unsigned RoundingModeDeco = roundingModeMDToDecorationConst(Parts[1]);
1929-
if (RoundingModeDeco != std::numeric_limits<unsigned>::max())
1930-
createRoundingModeDecoration(CI, RoundingModeDeco, B);
1931-
// Check if the SaturatedConversion info is present.
1932-
if (Parts[1] == "sat")
1933-
createSaturatedConversionDecoration(CI, B);
1911+
// check if a floating rounding mode or saturation info is present
1912+
switch (DecorationId) {
1913+
default:
1914+
break;
1915+
case FPDecorationId::SAT:
1916+
createSaturatedConversionDecoration(CI, B);
1917+
break;
1918+
case FPDecorationId::RTE:
1919+
createRoundingModeDecoration(
1920+
CI, SPIRV::FPRoundingMode::FPRoundingMode::RTE, B);
1921+
break;
1922+
case FPDecorationId::RTZ:
1923+
createRoundingModeDecoration(
1924+
CI, SPIRV::FPRoundingMode::FPRoundingMode::RTZ, B);
1925+
break;
1926+
case FPDecorationId::RTP:
1927+
createRoundingModeDecoration(
1928+
CI, SPIRV::FPRoundingMode::FPRoundingMode::RTP, B);
1929+
break;
1930+
case FPDecorationId::RTN:
1931+
createRoundingModeDecoration(
1932+
CI, SPIRV::FPRoundingMode::FPRoundingMode::RTN, B);
1933+
break;
19341934
}
19351935
}
19361936
}

llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -157,28 +157,52 @@ SPIRVType *SPIRVGlobalRegistry::getOpTypeVoid(MachineIRBuilder &MIRBuilder) {
157157
});
158158
}
159159

160+
void SPIRVGlobalRegistry::invalidateMachineInstr(MachineInstr *MI) {
161+
// TODO:
162+
// - take into account duplicate tracker case which is a known issue,
163+
// - review other data structure wrt. possible issues related to removal
164+
// of a machine instruction during instruction selection.
165+
const MachineFunction *MF = MI->getParent()->getParent();
166+
auto It = LastInsertedTypeMap.find(MF);
167+
if (It == LastInsertedTypeMap.end())
168+
return;
169+
if (It->second == MI)
170+
LastInsertedTypeMap.erase(MF);
171+
}
172+
160173
SPIRVType *SPIRVGlobalRegistry::createOpType(
161174
MachineIRBuilder &MIRBuilder,
162175
std::function<MachineInstr *(MachineIRBuilder &)> Op) {
163176
auto oldInsertPoint = MIRBuilder.getInsertPt();
164177
MachineBasicBlock *OldMBB = &MIRBuilder.getMBB();
178+
MachineBasicBlock *NewMBB = &*MIRBuilder.getMF().begin();
165179

166180
auto LastInsertedType = LastInsertedTypeMap.find(CurMF);
167181
if (LastInsertedType != LastInsertedTypeMap.end()) {
168182
auto It = LastInsertedType->second->getIterator();
169-
auto NewMBB = MIRBuilder.getMF().begin();
170-
MIRBuilder.setInsertPt(*NewMBB, It->getNextNode()
171-
? It->getNextNode()->getIterator()
172-
: NewMBB->end());
183+
// It might happen that this instruction was removed from the first MBB,
184+
// hence the Parent's check.
185+
MachineBasicBlock::iterator InsertAt;
186+
if (It->getParent() != NewMBB)
187+
InsertAt = oldInsertPoint->getParent() == NewMBB
188+
? oldInsertPoint
189+
: getInsertPtValidEnd(NewMBB);
190+
else if (It->getNextNode())
191+
InsertAt = It->getNextNode()->getIterator();
192+
else
193+
InsertAt = getInsertPtValidEnd(NewMBB);
194+
MIRBuilder.setInsertPt(*NewMBB, InsertAt);
173195
} else {
174-
MIRBuilder.setInsertPt(*MIRBuilder.getMF().begin(),
175-
MIRBuilder.getMF().begin()->begin());
196+
MIRBuilder.setInsertPt(*NewMBB, NewMBB->begin());
176197
auto Result = LastInsertedTypeMap.try_emplace(CurMF, nullptr);
177198
assert(Result.second);
178199
LastInsertedType = Result.first;
179200
}
180201

181202
MachineInstr *Type = Op(MIRBuilder);
203+
// We expect all users of this function to insert definitions at the insertion
204+
// point set above that is always the first MBB.
205+
assert(Type->getParent() == NewMBB);
182206
LastInsertedType->second = Type;
183207

184208
MIRBuilder.setInsertPt(*OldMBB, oldInsertPoint);

llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,10 @@ class SPIRVGlobalRegistry {
444444
bool isBitcastCompatible(const SPIRVType *Type1,
445445
const SPIRVType *Type2) const;
446446

447+
// Informs about removal of the machine instruction and invalidates data
448+
// structures referring this instruction.
449+
void invalidateMachineInstr(MachineInstr *MI);
450+
447451
private:
448452
SPIRVType *getOpTypeBool(MachineIRBuilder &MIRBuilder);
449453

llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,7 @@ bool SPIRVInstructionSelector::select(MachineInstr &I) {
431431
}
432432
MRI->setRegClass(SrcReg, MRI->getRegClass(DstReg));
433433
MRI->replaceRegWith(SrcReg, DstReg);
434+
GR.invalidateMachineInstr(&I);
434435
I.removeFromParent();
435436
return true;
436437
} else if (I.getNumDefs() == 1) {
@@ -445,6 +446,7 @@ bool SPIRVInstructionSelector::select(MachineInstr &I) {
445446
// erase it
446447
LLVM_DEBUG(dbgs() << "Instruction is folded and dead.\n");
447448
salvageDebugInfo(*MRI, I);
449+
GR.invalidateMachineInstr(&I);
448450
I.eraseFromParent();
449451
return true;
450452
}
@@ -464,6 +466,7 @@ bool SPIRVInstructionSelector::select(MachineInstr &I) {
464466
if (HasDefs) // Make all vregs 64 bits (for SPIR-V IDs).
465467
for (unsigned i = 0; i < I.getNumDefs(); ++i)
466468
MRI->setType(I.getOperand(i).getReg(), LLT::scalar(64));
469+
GR.invalidateMachineInstr(&I);
467470
I.removeFromParent();
468471
return true;
469472
}
@@ -2253,8 +2256,10 @@ bool SPIRVInstructionSelector::selectDiscard(Register ResVReg,
22532256
} else {
22542257
Opcode = SPIRV::OpKill;
22552258
// OpKill must be the last operation of any basic block.
2256-
MachineInstr *NextI = I.getNextNode();
2257-
NextI->removeFromParent();
2259+
if (MachineInstr *NextI = I.getNextNode()) {
2260+
GR.invalidateMachineInstr(NextI);
2261+
NextI->removeFromParent();
2262+
}
22582263
}
22592264

22602265
MachineBasicBlock &BB = *I.getParent();

llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,8 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
319319
// tighten these requirements. Many of these math functions are only legal on
320320
// specific bitwidths, so they are not selectable for
321321
// allFloatScalarsAndVectors.
322-
getActionDefinitionsBuilder({G_FPOW,
322+
getActionDefinitionsBuilder({G_STRICT_FSQRT,
323+
G_FPOW,
323324
G_FEXP,
324325
G_FEXP2,
325326
G_FLOG,

llvm/lib/Target/SPIRV/SPIRVUtils.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,19 @@ MachineBasicBlock::iterator getOpVariableMBBIt(MachineInstr &I) {
194194
return It;
195195
}
196196

197+
MachineBasicBlock::iterator getInsertPtValidEnd(MachineBasicBlock *MBB) {
198+
MachineBasicBlock::iterator I = MBB->end();
199+
if (I == MBB->begin())
200+
return I;
201+
--I;
202+
while (I->isTerminator() || I->isDebugValue()) {
203+
if (I == MBB->begin())
204+
break;
205+
--I;
206+
}
207+
return I;
208+
}
209+
197210
SPIRV::StorageClass::StorageClass
198211
addressSpaceToStorageClass(unsigned AddrSpace, const SPIRVSubtarget &STI) {
199212
switch (AddrSpace) {

llvm/lib/Target/SPIRV/SPIRVUtils.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,10 @@ void buildOpSpirvDecorations(Register Reg, MachineIRBuilder &MIRBuilder,
150150
// i.e., at the beginning of the first block of the function.
151151
MachineBasicBlock::iterator getOpVariableMBBIt(MachineInstr &I);
152152

153+
// Return a valid position for the instruction at the end of the block before
154+
// terminators and debug instructions.
155+
MachineBasicBlock::iterator getInsertPtValidEnd(MachineBasicBlock *MBB);
156+
153157
// Convert a SPIR-V storage class to the corresponding LLVM IR address space.
154158
// TODO: maybe the following two functions should be handled in the subtarget
155159
// to allow for different OpenCL vs Vulkan handling.
@@ -396,5 +400,18 @@ Register createVirtualRegister(const Type *Ty, SPIRVGlobalRegistry *GR,
396400
// Return true if there is an opaque pointer type nested in the argument.
397401
bool isNestedPointer(const Type *Ty);
398402

403+
enum FPDecorationId { NONE, RTE, RTZ, RTP, RTN, SAT };
404+
405+
inline FPDecorationId demangledPostfixToDecorationId(const std::string &S) {
406+
static std::unordered_map<std::string, FPDecorationId> Mapping = {
407+
{"rte", FPDecorationId::RTE},
408+
{"rtz", FPDecorationId::RTZ},
409+
{"rtp", FPDecorationId::RTP},
410+
{"rtn", FPDecorationId::RTN},
411+
{"sat", FPDecorationId::SAT}};
412+
auto It = Mapping.find(S);
413+
return It == Mapping.end() ? FPDecorationId::NONE : It->second;
414+
}
415+
399416
} // namespace llvm
400417
#endif // LLVM_LIB_TARGET_SPIRV_SPIRVUTILS_H

0 commit comments

Comments
 (0)