Skip to content

Commit 00090a2

Browse files
committed
Support complex target features combinations
This patch is mainly doing two things: 1. Adding support for parentheses, making the combination of target features more diverse; 2. Making the priority of ’,‘ is higher than that of '|' by default. So I need to make some change with PTX Builtin function. Differential Revision: https://reviews.llvm.org/D89184
1 parent 30e7df0 commit 00090a2

File tree

7 files changed

+496
-406
lines changed

7 files changed

+496
-406
lines changed

clang/include/clang/Basic/BuiltinsNVPTX.def

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
#define PTX60 "ptx60|" PTX61
4444

4545
#pragma push_macro("AND")
46-
#define AND(a, b) a "," b
46+
#define AND(a, b) "(" a "),(" b ")"
4747

4848
// Special Registers
4949

clang/lib/CodeGen/CodeGenFunction.cpp

+17-38
Original file line numberDiff line numberDiff line change
@@ -2307,34 +2307,6 @@ void CGBuilderInserter::InsertHelper(
23072307
CGF->InsertHelper(I, Name, BB, InsertPt);
23082308
}
23092309

2310-
static bool hasRequiredFeatures(const SmallVectorImpl<StringRef> &ReqFeatures,
2311-
CodeGenModule &CGM, const FunctionDecl *FD,
2312-
std::string &FirstMissing) {
2313-
// If there aren't any required features listed then go ahead and return.
2314-
if (ReqFeatures.empty())
2315-
return false;
2316-
2317-
// Now build up the set of caller features and verify that all the required
2318-
// features are there.
2319-
llvm::StringMap<bool> CallerFeatureMap;
2320-
CGM.getContext().getFunctionFeatureMap(CallerFeatureMap, FD);
2321-
2322-
// If we have at least one of the features in the feature list return
2323-
// true, otherwise return false.
2324-
return std::all_of(
2325-
ReqFeatures.begin(), ReqFeatures.end(), [&](StringRef Feature) {
2326-
SmallVector<StringRef, 1> OrFeatures;
2327-
Feature.split(OrFeatures, '|');
2328-
return llvm::any_of(OrFeatures, [&](StringRef Feature) {
2329-
if (!CallerFeatureMap.lookup(Feature)) {
2330-
FirstMissing = Feature.str();
2331-
return false;
2332-
}
2333-
return true;
2334-
});
2335-
});
2336-
}
2337-
23382310
// Emits an error if we don't have a valid set of target features for the
23392311
// called function.
23402312
void CodeGenFunction::checkTargetFeatures(const CallExpr *E,
@@ -2361,19 +2333,20 @@ void CodeGenFunction::checkTargetFeatures(SourceLocation Loc,
23612333
// listed cpu and any listed features.
23622334
unsigned BuiltinID = TargetDecl->getBuiltinID();
23632335
std::string MissingFeature;
2336+
llvm::StringMap<bool> CallerFeatureMap;
2337+
CGM.getContext().getFunctionFeatureMap(CallerFeatureMap, FD);
23642338
if (BuiltinID) {
2365-
SmallVector<StringRef, 1> ReqFeatures;
2366-
const char *FeatureList =
2367-
CGM.getContext().BuiltinInfo.getRequiredFeatures(BuiltinID);
2339+
StringRef FeatureList(
2340+
CGM.getContext().BuiltinInfo.getRequiredFeatures(BuiltinID));
23682341
// Return if the builtin doesn't have any required features.
2369-
if (!FeatureList || StringRef(FeatureList) == "")
2342+
if (FeatureList.empty())
23702343
return;
2371-
StringRef(FeatureList).split(ReqFeatures, ',');
2372-
if (!hasRequiredFeatures(ReqFeatures, CGM, FD, MissingFeature))
2344+
assert(FeatureList.find(' ') == StringRef::npos &&
2345+
"Space in feature list");
2346+
TargetFeatures TF(CallerFeatureMap);
2347+
if (!TF.hasRequiredFeatures(FeatureList))
23732348
CGM.getDiags().Report(Loc, diag::err_builtin_needs_feature)
2374-
<< TargetDecl->getDeclName()
2375-
<< CGM.getContext().BuiltinInfo.getRequiredFeatures(BuiltinID);
2376-
2349+
<< TargetDecl->getDeclName() << FeatureList;
23772350
} else if (!TargetDecl->isMultiVersion() &&
23782351
TargetDecl->hasAttr<TargetAttr>()) {
23792352
// Get the required features for the callee.
@@ -2396,7 +2369,13 @@ void CodeGenFunction::checkTargetFeatures(SourceLocation Loc,
23962369
if (F.getValue())
23972370
ReqFeatures.push_back(F.getKey());
23982371
}
2399-
if (!hasRequiredFeatures(ReqFeatures, CGM, FD, MissingFeature))
2372+
if (!llvm::all_of(ReqFeatures, [&](StringRef Feature) {
2373+
if (!CallerFeatureMap.lookup(Feature)) {
2374+
MissingFeature = Feature.str();
2375+
return false;
2376+
}
2377+
return true;
2378+
}))
24002379
CGM.getDiags().Report(Loc, diag::err_function_needs_feature)
24012380
<< FD->getDeclName() << TargetDecl->getDeclName() << MissingFeature;
24022381
}

clang/lib/CodeGen/CodeGenFunction.h

+71
Original file line numberDiff line numberDiff line change
@@ -4688,6 +4688,77 @@ class CodeGenFunction : public CodeGenTypeCache {
46884688
llvm::Value *FormResolverCondition(const MultiVersionResolverOption &RO);
46894689
};
46904690

4691+
/// TargetFeatures - This class is used to check whether the builtin function
4692+
/// has the required tagert specific features. It is able to support the
4693+
/// combination of ','(and), '|'(or), and '()'. By default, the priority of
4694+
/// ',' is higher than that of '|' .
4695+
/// E.g:
4696+
/// A,B|C means the builtin function requires both A and B, or C.
4697+
/// If we want the builtin function requires both A and B, or both A and C,
4698+
/// there are two ways: A,B|A,C or A,(B|C).
4699+
/// The FeaturesList should not contain spaces, and brackets must appear in
4700+
/// pairs.
4701+
class TargetFeatures {
4702+
struct FeatureListStatus {
4703+
bool HasFeatures;
4704+
StringRef CurFeaturesList;
4705+
};
4706+
4707+
const llvm::StringMap<bool> &CallerFeatureMap;
4708+
4709+
FeatureListStatus getAndFeatures(StringRef FeatureList) {
4710+
int InParentheses = 0;
4711+
bool HasFeatures = true;
4712+
size_t SubexpressionStart = 0;
4713+
for (size_t i = 0, e = FeatureList.size(); i < e; ++i) {
4714+
char CurrentToken = FeatureList[i];
4715+
switch (CurrentToken) {
4716+
default:
4717+
break;
4718+
case '(':
4719+
if (InParentheses == 0)
4720+
SubexpressionStart = i + 1;
4721+
++InParentheses;
4722+
break;
4723+
case ')':
4724+
--InParentheses;
4725+
assert(InParentheses >= 0 && "Parentheses are not in pair");
4726+
LLVM_FALLTHROUGH;
4727+
case '|':
4728+
case ',':
4729+
if (InParentheses == 0) {
4730+
if (HasFeatures && i != SubexpressionStart) {
4731+
StringRef F = FeatureList.slice(SubexpressionStart, i);
4732+
HasFeatures = CurrentToken == ')' ? hasRequiredFeatures(F)
4733+
: CallerFeatureMap.lookup(F);
4734+
}
4735+
SubexpressionStart = i + 1;
4736+
if (CurrentToken == '|') {
4737+
return {HasFeatures, FeatureList.substr(SubexpressionStart)};
4738+
}
4739+
}
4740+
break;
4741+
}
4742+
}
4743+
assert(InParentheses == 0 && "Parentheses are not in pair");
4744+
if (HasFeatures && SubexpressionStart != FeatureList.size())
4745+
HasFeatures =
4746+
CallerFeatureMap.lookup(FeatureList.substr(SubexpressionStart));
4747+
return {HasFeatures, StringRef()};
4748+
}
4749+
4750+
public:
4751+
bool hasRequiredFeatures(StringRef FeatureList) {
4752+
FeatureListStatus FS = {false, FeatureList};
4753+
while (!FS.HasFeatures && !FS.CurFeaturesList.empty())
4754+
FS = getAndFeatures(FS.CurFeaturesList);
4755+
return FS.HasFeatures;
4756+
}
4757+
4758+
TargetFeatures(const llvm::StringMap<bool> &CallerFeatureMap)
4759+
: CallerFeatureMap(CallerFeatureMap) {}
4760+
};
4761+
46914762
inline DominatingLLVMValue::saved_type
46924763
DominatingLLVMValue::save(CodeGenFunction &CGF, llvm::Value *value) {
46934764
if (!needsSaving(value)) return saved_type(value, false);

0 commit comments

Comments
 (0)