craig.topper created this revision. craig.topper added reviewers: rnk, echristo, erichkeane, RKSimon, spatel. Herald added a project: clang.
The validateOutputSize and validateInputSize need to check whether AVX or AVX512 are enabled. But this can be affected by the target attribute so we need to factor that in. This patch copies some of the code from CodeGen to create an appropriate feature map that we can pass to the function. Probably need some refactoring here to share more code with Codegen. Is there a good place to do that? Also need to support the cpu_specific attribute as well. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D68627 Files: clang/include/clang/Basic/TargetInfo.h clang/lib/Basic/Targets/X86.cpp clang/lib/Basic/Targets/X86.h clang/lib/Sema/SemaStmtAsm.cpp clang/test/CodeGen/x86_32-inline-asm.c
Index: clang/test/CodeGen/x86_32-inline-asm.c =================================================================== --- clang/test/CodeGen/x86_32-inline-asm.c +++ clang/test/CodeGen/x86_32-inline-asm.c @@ -70,3 +70,35 @@ __asm__ volatile("foo1 %0" : "=x" (val256)); // expected-error {{invalid output size for constraint '=x'}} #endif } + +int __attribute__((__target__("sse"))) _func2() { + __asm__ volatile("foo1 %0" : : "x" (val128)); // No error. + __asm__ volatile("foo1 %0" : "=x" (val128)); // No error. +#ifdef __AVX__ + __asm__ volatile("foo1 %0" : : "x" (val256)); // No error. + __asm__ volatile("foo1 %0" : "=x" (val256)); // No error. +#else + __asm__ volatile("foo1 %0" : : "x" (val256)); // expected-error {{invalid input size for constraint 'x'}} + __asm__ volatile("foo1 %0" : "=x" (val256)); // expected-error {{invalid output size for constraint '=x'}} +#endif + __asm__ volatile("foo1 %0" : : "x" (val512)); // expected-error {{invalid input size for constraint 'x'}} + __asm__ volatile("foo1 %0" : "=x" (val512)); // expected-error {{invalid output size for constraint '=x'}} +} + +int __attribute__((__target__("avx"))) _func3() { + __asm__ volatile("foo1 %0" : : "x" (val128)); // No error. + __asm__ volatile("foo1 %0" : "=x" (val128)); // No error. + __asm__ volatile("foo1 %0" : : "x" (val256)); // No error. + __asm__ volatile("foo1 %0" : "=x" (val256)); // No error. + __asm__ volatile("foo1 %0" : : "x" (val512)); // expected-error {{invalid input size for constraint 'x'}} + __asm__ volatile("foo1 %0" : "=x" (val512)); // expected-error {{invalid output size for constraint '=x'}} +} + +int __attribute__((__target__("avx512f"))) _func4() { + __asm__ volatile("foo1 %0" : : "x" (val128)); // No error. + __asm__ volatile("foo1 %0" : "=x" (val128)); // No error. + __asm__ volatile("foo1 %0" : : "x" (val256)); // No error. + __asm__ volatile("foo1 %0" : "=x" (val256)); // No error. + __asm__ volatile("foo1 %0" : : "x" (val512)); // No error. + __asm__ volatile("foo1 %0" : "=x" (val512)); // No error. +} Index: clang/lib/Sema/SemaStmtAsm.cpp =================================================================== --- clang/lib/Sema/SemaStmtAsm.cpp +++ clang/lib/Sema/SemaStmtAsm.cpp @@ -237,6 +237,44 @@ return SourceLocation(); } +void getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap, + DiagnosticsEngine &Diags, + const TargetInfo &Target, FunctionDecl *FD) { + StringRef TargetCPU = Target.getTargetOpts().CPU; + if (FD) { + if (const auto *TD = FD->getAttr<TargetAttr>()) { + TargetAttr::ParsedTargetAttr ParsedAttr = TD->parse(); + + ParsedAttr.Features.erase( + llvm::remove_if(ParsedAttr.Features, + [&](const std::string &Feat) { + return !Target.isValidFeatureName( + StringRef{Feat}.substr(1)); + }), + ParsedAttr.Features.end()); + + ParsedAttr.Features.insert(ParsedAttr.Features.begin(), + Target.getTargetOpts().FeaturesAsWritten.begin(), + Target.getTargetOpts().FeaturesAsWritten.end()); + + if (ParsedAttr.Architecture != "" && + Target.isValidCPUName(ParsedAttr.Architecture)) + TargetCPU = ParsedAttr.Architecture; + + // Now populate the feature map, first with the TargetCPU which is either + // the default or a new one from the target attribute string. Then we'll + // use the passed in features (FeaturesAsWritten) along with the new ones + // from the attribute. + Target.initFeatureMap(FeatureMap, Diags, TargetCPU, + ParsedAttr.Features); + return; + } + } + + Target.initFeatureMap(FeatureMap, Diags, TargetCPU, + Target.getTargetOpts().Features); +} + StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, bool IsVolatile, unsigned NumOutputs, unsigned NumInputs, IdentifierInfo **Names, @@ -255,6 +293,10 @@ // The parser verifies that there is a string literal here. assert(AsmString->isAscii()); + llvm::StringMap<bool> FeatureMap; + getFunctionFeatureMap(FeatureMap, Diags, Context.getTargetInfo(), + getCurFunctionDecl()); + for (unsigned i = 0; i != NumOutputs; i++) { StringLiteral *Literal = Constraints[i]; assert(Literal->isAscii()); @@ -325,7 +367,8 @@ } unsigned Size = Context.getTypeSize(OutputExpr->getType()); - if (!Context.getTargetInfo().validateOutputSize(Literal->getString(), + if (!Context.getTargetInfo().validateOutputSize(FeatureMap, + Literal->getString(), Size)) { targetDiag(OutputExpr->getBeginLoc(), diag::err_asm_invalid_output_size) << Info.getConstraintStr(); @@ -427,8 +470,8 @@ return StmtError(); unsigned Size = Context.getTypeSize(Ty); - if (!Context.getTargetInfo().validateInputSize(Literal->getString(), - Size)) + if (!Context.getTargetInfo().validateInputSize(FeatureMap, + Literal->getString(), Size)) return StmtResult( targetDiag(InputExpr->getBeginLoc(), diag::err_asm_invalid_input_size) << Info.getConstraintStr()); Index: clang/lib/Basic/Targets/X86.h =================================================================== --- clang/lib/Basic/Targets/X86.h +++ clang/lib/Basic/Targets/X86.h @@ -177,9 +177,11 @@ return false; } - bool validateOutputSize(StringRef Constraint, unsigned Size) const override; + bool validateOutputSize(const llvm::StringMap<bool> &FeatureMap, + StringRef Constraint, unsigned Size) const override; - bool validateInputSize(StringRef Constraint, unsigned Size) const override; + bool validateInputSize(const llvm::StringMap<bool> &FeatureMap, + StringRef Constraint, unsigned Size) const override; virtual bool checkCFProtectionReturnSupported(DiagnosticsEngine &Diags) const override { @@ -192,7 +194,8 @@ }; - virtual bool validateOperandSize(StringRef Constraint, unsigned Size) const; + virtual bool validateOperandSize(const llvm::StringMap<bool> &FeatureMap, + StringRef Constraint, unsigned Size) const; std::string convertConstraint(const char *&Constraint) const override; const char *getClobbers() const override { @@ -368,7 +371,8 @@ return -1; } - bool validateOperandSize(StringRef Constraint, unsigned Size) const override { + bool validateOperandSize(const llvm::StringMap<bool> &FeatureMap, + StringRef Constraint, unsigned Size) const override { switch (Constraint[0]) { default: break; @@ -386,7 +390,7 @@ return Size <= 64; } - return X86TargetInfo::validateOperandSize(Constraint, Size); + return X86TargetInfo::validateOperandSize(FeatureMap, Constraint, Size); } void setMaxAtomicWidth() override { Index: clang/lib/Basic/Targets/X86.cpp =================================================================== --- clang/lib/Basic/Targets/X86.cpp +++ clang/lib/Basic/Targets/X86.cpp @@ -1726,21 +1726,24 @@ } } -bool X86TargetInfo::validateOutputSize(StringRef Constraint, +bool X86TargetInfo::validateOutputSize(const llvm::StringMap<bool> &FeatureMap, + StringRef Constraint, unsigned Size) const { // Strip off constraint modifiers. while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&') Constraint = Constraint.substr(1); - return validateOperandSize(Constraint, Size); + return validateOperandSize(FeatureMap, Constraint, Size); } -bool X86TargetInfo::validateInputSize(StringRef Constraint, +bool X86TargetInfo::validateInputSize(const llvm::StringMap<bool> &FeatureMap, + StringRef Constraint, unsigned Size) const { - return validateOperandSize(Constraint, Size); + return validateOperandSize(FeatureMap, Constraint, Size); } -bool X86TargetInfo::validateOperandSize(StringRef Constraint, +bool X86TargetInfo::validateOperandSize(const llvm::StringMap<bool> &FeatureMap, + StringRef Constraint, unsigned Size) const { switch (Constraint[0]) { default: @@ -1765,7 +1768,7 @@ case 'z': case '0': // XMM0 - if (SSELevel >= SSE1) + if (FeatureMap.lookup("sse")) return Size <= 128U; return false; case 'i': @@ -1779,10 +1782,10 @@ LLVM_FALLTHROUGH; case 'v': case 'x': - if (SSELevel >= AVX512F) + if (FeatureMap.lookup("avx512f")) // 512-bit zmm registers can be used if target supports AVX512F. return Size <= 512U; - else if (SSELevel >= AVX) + else if (FeatureMap.lookup("avx")) // 256-bit ymm registers can be used if target supports AVX. return Size <= 256U; return Size <= 128U; Index: clang/include/clang/Basic/TargetInfo.h =================================================================== --- clang/include/clang/Basic/TargetInfo.h +++ clang/include/clang/Basic/TargetInfo.h @@ -944,12 +944,14 @@ bool validateInputConstraint(MutableArrayRef<ConstraintInfo> OutputConstraints, ConstraintInfo &info) const; - virtual bool validateOutputSize(StringRef /*Constraint*/, + virtual bool validateOutputSize(const llvm::StringMap<bool> &FeatureMap, + StringRef /*Constraint*/, unsigned /*Size*/) const { return true; } - virtual bool validateInputSize(StringRef /*Constraint*/, + virtual bool validateInputSize(const llvm::StringMap<bool> &FeatureMap, + StringRef /*Constraint*/, unsigned /*Size*/) const { return true; }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits