diff options
author | Kito Cheng <kito.cheng@sifive.com> | 2022-07-13 15:52:17 +0800 |
---|---|---|
committer | Kito Cheng <kito.cheng@sifive.com> | 2022-07-26 15:47:47 +0800 |
commit | 7a5cb15ea6facd82756adafae76d60f36a0b60fd (patch) | |
tree | da7a2edf49c6964a3d4e48ed34fcb1ccf939304e /clang/include | |
parent | 2f9fa9ef5387de3d87b0c866c678d93695c1c1f3 (diff) | |
download | llvm-7a5cb15ea6facd82756adafae76d60f36a0b60fd.zip llvm-7a5cb15ea6facd82756adafae76d60f36a0b60fd.tar.gz llvm-7a5cb15ea6facd82756adafae76d60f36a0b60fd.tar.bz2 |
[RISCV] Lazily add RVV C intrinsics.
Leverage the method OpenCL uses that adds C intrinsics when the lookup
failed. There is no need to define C intrinsics in the header file any
more. It could help to avoid the large header file to speed up the
compilation of RVV source code. Besides that, only the C intrinsics used
by the users will be added into the declaration table.
This patch is based on https://reviews.llvm.org/D103228 and inspired by
OpenCL implementation.
### Experimental Results
#### TL;DR:
- Binary size of clang increase ~200k, which is +0.07% for debug build and +0.13% for release build.
- Single file compilation speed up ~33x for debug build and ~8.5x for release build
- Regression time reduce ~10% (`ninja check-all`, enable all targets)
#### Header size change
```
| size | LoC |
------------------------------
Before | 4,434,725 | 69,749 |
After | 6,140 | 162 |
```
#### Single File Compilation Time
Testcase:
```
#include <riscv_vector.h>
vint32m1_t test_vadd_vv_vfloat32m1_t(vint32m1_t op1, vint32m1_t op2, size_t vl) {
return vadd(op1, op2, vl);
}
```
##### Debug build:
Before:
```
real 0m19.352s
user 0m19.252s
sys 0m0.092s
```
After:
```
real 0m0.576s
user 0m0.552s
sys 0m0.024s
```
~33x speed up for debug build
##### Release build:
Before:
```
real 0m0.773s
user 0m0.741s
sys 0m0.032s
```
After:
```
real 0m0.092s
user 0m0.080s
sys 0m0.012s
```
~8.5x speed up for release build
#### Regression time
Note: the failed case is `tools/llvm-debuginfod-find/debuginfod.test` which is unrelated to this patch.
##### Debug build
Before:
```
Testing Time: 1358.38s
Skipped : 11
Unsupported : 446
Passed : 75767
Expectedly Failed: 190
Failed : 1
```
After
```
Testing Time: 1220.29s
Skipped : 11
Unsupported : 446
Passed : 75767
Expectedly Failed: 190
Failed : 1
```
##### Release build
Before:
```
Testing Time: 381.98s
Skipped : 12
Unsupported : 1407
Passed : 74765
Expectedly Failed: 176
Failed : 1
```
After:
```
Testing Time: 346.25s
Skipped : 12
Unsupported : 1407
Passed : 74765
Expectedly Failed: 176
Failed : 1
```
#### Binary size of clang
##### Debug build
Before
```
text data bss dec hex filename
335261851 12726004 552812 348540667 14c64efb bin/clang
```
After
```
text data bss dec hex filename
335442803 12798708 552940 348794451 14ca2e53 bin/clang
```
+253K, +0.07% code size
##### Release build
Before
```
text data bss dec hex filename
144123975 8374648 483140 152981763 91e5103 bin/clang
```
After
```
text data bss dec hex filename
144255762 8447296 483268 153186326 9217016 bin/clang
```
+204K, +0.13%
Authored-by: Kito Cheng <kito.cheng@sifive.com>
Co-Authored-by: Hsiangkai Wang <kai.wang@sifive.com>
Reviewed By: khchen, aaron.ballman
Differential Revision: https://reviews.llvm.org/D111617
Diffstat (limited to 'clang/include')
-rw-r--r-- | clang/include/clang/Basic/CMakeLists.txt | 3 | ||||
-rw-r--r-- | clang/include/clang/Basic/TokenKinds.def | 3 | ||||
-rw-r--r-- | clang/include/clang/Parse/Parser.h | 1 | ||||
-rw-r--r-- | clang/include/clang/Sema/RISCVIntrinsicManager.h | 36 | ||||
-rw-r--r-- | clang/include/clang/Sema/Sema.h | 8 | ||||
-rw-r--r-- | clang/include/clang/Support/RISCVVIntrinsicUtils.h | 97 |
6 files changed, 127 insertions, 21 deletions
diff --git a/clang/include/clang/Basic/CMakeLists.txt b/clang/include/clang/Basic/CMakeLists.txt index 8cd8913..b930842 100644 --- a/clang/include/clang/Basic/CMakeLists.txt +++ b/clang/include/clang/Basic/CMakeLists.txt @@ -90,3 +90,6 @@ clang_tablegen(riscv_vector_builtins.inc -gen-riscv-vector-builtins clang_tablegen(riscv_vector_builtin_cg.inc -gen-riscv-vector-builtin-codegen SOURCE riscv_vector.td TARGET ClangRISCVVectorBuiltinCG) +clang_tablegen(riscv_vector_builtin_sema.inc -gen-riscv-vector-builtin-sema + SOURCE riscv_vector.td + TARGET ClangRISCVVectorBuiltinSema) diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index 7b65a15..84fc089 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -908,6 +908,9 @@ PRAGMA_ANNOTATION(pragma_fp) // Annotation for the attribute pragma directives - #pragma clang attribute ... PRAGMA_ANNOTATION(pragma_attribute) +// Annotation for the riscv pragma directives - #pragma clang riscv intrinsic ... +PRAGMA_ANNOTATION(pragma_riscv) + // Annotations for module import translated from #include etc. ANNOTATION(module_include) ANNOTATION(module_begin) diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index a9c85ce..41bfc9f 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -215,6 +215,7 @@ class Parser : public CodeCompletionHandler { std::unique_ptr<PragmaHandler> AttributePragmaHandler; std::unique_ptr<PragmaHandler> MaxTokensHerePragmaHandler; std::unique_ptr<PragmaHandler> MaxTokensTotalPragmaHandler; + std::unique_ptr<PragmaHandler> RISCVPragmaHandler; std::unique_ptr<CommentHandler> CommentSemaHandler; diff --git a/clang/include/clang/Sema/RISCVIntrinsicManager.h b/clang/include/clang/Sema/RISCVIntrinsicManager.h new file mode 100644 index 0000000..5051002 --- /dev/null +++ b/clang/include/clang/Sema/RISCVIntrinsicManager.h @@ -0,0 +1,36 @@ +//===- RISCVIntrinsicManager.h - RISC-V Intrinsic Handler -------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the RISCVIntrinsicManager, which handles RISC-V vector +// intrinsic functions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SEMA_RISCVINTRINSICMANAGER_H +#define LLVM_CLANG_SEMA_RISCVINTRINSICMANAGER_H + +namespace clang { +class Sema; +class LookupResult; +class IdentifierInfo; +class Preprocessor; + +namespace sema { +class RISCVIntrinsicManager { +public: + virtual ~RISCVIntrinsicManager() = default; + + // Create RISC-V intrinsic and insert into symbol table and return true if + // found, otherwise return false. + virtual bool CreateIntrinsicIfFound(LookupResult &LR, IdentifierInfo *II, + Preprocessor &PP) = 0; +}; +} // end namespace sema +} // end namespace clang + +#endif diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index b149c24..06ea0b4 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -226,6 +226,7 @@ namespace sema { class FunctionScopeInfo; class LambdaScopeInfo; class PossiblyUnreachableDiag; + class RISCVIntrinsicManager; class SemaPPCallbacks; class TemplateDeductionInfo; } @@ -1587,7 +1588,12 @@ public: /// assignment. llvm::DenseMap<const VarDecl *, int> RefsMinusAssignments; + /// Indicate RISC-V vector builtin functions enabled or not. + bool DeclareRISCVVBuiltins = false; + private: + std::unique_ptr<sema::RISCVIntrinsicManager> RVIntrinsicManager; + Optional<std::unique_ptr<DarwinSDKInfo>> CachedDarwinSDKInfo; bool WarnedDarwinSDKInfoMissing = false; @@ -13590,6 +13596,8 @@ void Sema::PragmaStack<Sema::AlignPackInfo>::Act(SourceLocation PragmaLocation, llvm::StringRef StackSlotLabel, AlignPackInfo Value); +std::unique_ptr<sema::RISCVIntrinsicManager> +CreateRISCVIntrinsicManager(Sema &S); } // end namespace clang namespace llvm { diff --git a/clang/include/clang/Support/RISCVVIntrinsicUtils.h b/clang/include/clang/Support/RISCVVIntrinsicUtils.h index a5e7e6d..727f48d 100644 --- a/clang/include/clang/Support/RISCVVIntrinsicUtils.h +++ b/clang/include/clang/Support/RISCVVIntrinsicUtils.h @@ -18,6 +18,10 @@ #include <string> #include <vector> +namespace llvm { +class raw_ostream; +} // end namespace llvm + namespace clang { namespace RISCV { @@ -104,12 +108,14 @@ struct PrototypeDescriptor { uint8_t TM = static_cast<uint8_t>(TypeModifier::NoModifier); bool operator!=(const PrototypeDescriptor &PD) const { - return PD.PT != PT || PD.VTM != VTM || PD.TM != TM; + return !(*this == PD); } - bool operator>(const PrototypeDescriptor &PD) const { - return !(PD.PT <= PT && PD.VTM <= VTM && PD.TM <= TM); + bool operator==(const PrototypeDescriptor &PD) const { + return PD.PT == PT && PD.VTM == VTM && PD.TM == TM; + } + bool operator<(const PrototypeDescriptor &PD) const { + return std::tie(PT, VTM, TM) < std::tie(PD.PT, PD.VTM, PD.TM); } - static const PrototypeDescriptor Mask; static const PrototypeDescriptor Vector; static const PrototypeDescriptor VL; @@ -224,8 +230,12 @@ public: bool isFloat(unsigned Width) const { return isFloat() && ElementBitwidth == Width; } - + bool isConstant() const { return IsConstant; } bool isPointer() const { return IsPointer; } + unsigned getElementBitwidth() const { return ElementBitwidth; } + + ScalarTypeKind getScalarType() const { return ScalarType; } + VScaleVal getScale() const { return Scale; } private: // Verify RVV vector type and set Valid. @@ -263,18 +273,6 @@ public: PrototypeDescriptor Proto); }; -using RISCVPredefinedMacroT = uint8_t; - -enum RISCVPredefinedMacro : RISCVPredefinedMacroT { - Basic = 0, - V = 1 << 1, - Zvfh = 1 << 2, - RV64 = 1 << 3, - VectorMaxELen64 = 1 << 4, - VectorMaxELenFp32 = 1 << 5, - VectorMaxELenFp64 = 1 << 6, -}; - enum PolicyScheme : uint8_t { SchemeNone, HasPassthruOperand, @@ -302,7 +300,6 @@ private: // The types we use to obtain the specific LLVM intrinsic. They are index of // InputTypes. -1 means the return type. std::vector<int64_t> IntrinsicTypes; - RISCVPredefinedMacroT RISCVPredefinedMacros = 0; unsigned NF = 1; public: @@ -333,9 +330,6 @@ public: llvm::StringRef getIRName() const { return IRName; } llvm::StringRef getManualCodegen() const { return ManualCodegen; } PolicyScheme getPolicyScheme() const { return Scheme; } - RISCVPredefinedMacroT getRISCVPredefinedMacros() const { - return RISCVPredefinedMacros; - } unsigned getNF() const { return NF; } const std::vector<int64_t> &getIntrinsicTypes() const { return IntrinsicTypes; @@ -349,6 +343,67 @@ public: llvm::ArrayRef<PrototypeDescriptor> PrototypeDescriptors); }; +// RVVRequire should be sync'ed with target features, but only +// required features used in riscv_vector.td. +enum RVVRequire : uint8_t { + RVV_REQ_None = 0, + RVV_REQ_RV64 = 1 << 0, + RVV_REQ_FullMultiply = 1 << 1, + + LLVM_MARK_AS_BITMASK_ENUM(RVV_REQ_FullMultiply) +}; + +// Raw RVV intrinsic info, used to expand later. +// This struct is highly compact for minimized code size. +struct RVVIntrinsicRecord { + // Intrinsic name, e.g. vadd_vv + const char *Name; + + // Overloaded intrinsic name, could be empty if it can be computed from Name. + // e.g. vadd + const char *OverloadedName; + + // Prototype for this intrinsic, index of RVVSignatureTable. + uint16_t PrototypeIndex; + + // Prototype for masked intrinsic, index of RVVSignatureTable. + uint16_t MaskedPrototypeIndex; + + // Suffix of intrinsic name, index of RVVSignatureTable. + uint16_t SuffixIndex; + + // Suffix of overloaded intrinsic name, index of RVVSignatureTable. + uint16_t OverloadedSuffixIndex; + + // Length of the prototype. + uint8_t PrototypeLength; + + // Length of prototype of masked intrinsic. + uint8_t MaskedPrototypeLength; + + // Length of intrinsic name suffix. + uint8_t SuffixLength; + + // Length of overloaded intrinsic suffix. + uint8_t OverloadedSuffixSize; + + // Required target features for this intrinsic. + uint8_t RequiredExtensions; + + // Supported type, mask of BasicType. + uint8_t TypeRangeMask; + + // Supported LMUL. + uint8_t Log2LMULMask; + + // Number of fields, greater than 1 if it's segment load/store. + uint8_t NF; +}; + +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const RVVIntrinsicRecord &RVVInstrRecord); + +LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); } // end namespace RISCV } // end namespace clang |