1 //===-- RISCVTargetParser - Parser for target features ----------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements a target parser to recognise hardware features 10 // for RISC-V CPUs. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_TARGETPARSER_RISCVTARGETPARSER_H 15 #define LLVM_TARGETPARSER_RISCVTARGETPARSER_H 16 17 #include "llvm/ADT/StringRef.h" 18 #include "llvm/Support/MathExtras.h" 19 #include "llvm/Support/raw_ostream.h" 20 21 namespace llvm { 22 23 class Triple; 24 25 namespace RISCV { 26 27 namespace RISCVExtensionBitmaskTable { 28 struct RISCVExtensionBitmask { 29 const char *Name; 30 unsigned GroupID; 31 unsigned BitPosition; 32 }; 33 } // namespace RISCVExtensionBitmaskTable 34 35 // We use 64 bits as the known part in the scalable vector types. 36 static constexpr unsigned RVVBitsPerBlock = 64; 37 38 void getFeaturesForCPU(StringRef CPU, 39 SmallVectorImpl<std::string> &EnabledFeatures, 40 bool NeedPlus = false); 41 bool parseCPU(StringRef CPU, bool IsRV64); 42 bool parseTuneCPU(StringRef CPU, bool IsRV64); 43 StringRef getMArchFromMcpu(StringRef CPU); 44 void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values, bool IsRV64); 45 void fillValidTuneCPUArchList(SmallVectorImpl<StringRef> &Values, bool IsRV64); 46 bool hasFastScalarUnalignedAccess(StringRef CPU); 47 bool hasFastVectorUnalignedAccess(StringRef CPU); 48 49 } // namespace RISCV 50 51 namespace RISCVII { 52 enum VLMUL : uint8_t { 53 LMUL_1 = 0, 54 LMUL_2, 55 LMUL_4, 56 LMUL_8, 57 LMUL_RESERVED, 58 LMUL_F8, 59 LMUL_F4, 60 LMUL_F2 61 }; 62 63 enum { 64 TAIL_UNDISTURBED_MASK_UNDISTURBED = 0, 65 TAIL_AGNOSTIC = 1, 66 MASK_AGNOSTIC = 2, 67 }; 68 } // namespace RISCVII 69 70 namespace RISCVVType { 71 // Is this a SEW value that can be encoded into the VTYPE format. 72 inline static bool isValidSEW(unsigned SEW) { 73 return isPowerOf2_32(SEW) && SEW >= 8 && SEW <= 64; 74 } 75 76 // Is this a LMUL value that can be encoded into the VTYPE format. 77 inline static bool isValidLMUL(unsigned LMUL, bool Fractional) { 78 return isPowerOf2_32(LMUL) && LMUL <= 8 && (!Fractional || LMUL != 1); 79 } 80 81 unsigned encodeVTYPE(RISCVII::VLMUL VLMUL, unsigned SEW, bool TailAgnostic, 82 bool MaskAgnostic); 83 84 inline static RISCVII::VLMUL getVLMUL(unsigned VType) { 85 unsigned VLMUL = VType & 0x7; 86 return static_cast<RISCVII::VLMUL>(VLMUL); 87 } 88 89 // Decode VLMUL into 1,2,4,8 and fractional indicator. 90 std::pair<unsigned, bool> decodeVLMUL(RISCVII::VLMUL VLMUL); 91 92 inline static RISCVII::VLMUL encodeLMUL(unsigned LMUL, bool Fractional) { 93 assert(isValidLMUL(LMUL, Fractional) && "Unsupported LMUL"); 94 unsigned LmulLog2 = Log2_32(LMUL); 95 return static_cast<RISCVII::VLMUL>(Fractional ? 8 - LmulLog2 : LmulLog2); 96 } 97 98 inline static unsigned decodeVSEW(unsigned VSEW) { 99 assert(VSEW < 8 && "Unexpected VSEW value"); 100 return 1 << (VSEW + 3); 101 } 102 103 inline static unsigned encodeSEW(unsigned SEW) { 104 assert(isValidSEW(SEW) && "Unexpected SEW value"); 105 return Log2_32(SEW) - 3; 106 } 107 108 inline static unsigned getSEW(unsigned VType) { 109 unsigned VSEW = (VType >> 3) & 0x7; 110 return decodeVSEW(VSEW); 111 } 112 113 inline static bool isTailAgnostic(unsigned VType) { return VType & 0x40; } 114 115 inline static bool isMaskAgnostic(unsigned VType) { return VType & 0x80; } 116 117 void printVType(unsigned VType, raw_ostream &OS); 118 119 unsigned getSEWLMULRatio(unsigned SEW, RISCVII::VLMUL VLMul); 120 121 std::optional<RISCVII::VLMUL> 122 getSameRatioLMUL(unsigned SEW, RISCVII::VLMUL VLMUL, unsigned EEW); 123 } // namespace RISCVVType 124 125 } // namespace llvm 126 127 #endif 128