clang 23.0.0git
CIRGenBuiltinRISCV.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
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 contains code to emit RISC-V Builtin calls as CIR or a function call
10// to be later resolved.
11//
12//===----------------------------------------------------------------------===//
13
14#include "CIRGenFunction.h"
16
17using namespace clang;
18using namespace clang::CIRGen;
19
20std::optional<mlir::Value>
21CIRGenFunction::emitRISCVBuiltinExpr(unsigned builtinID, const CallExpr *e) {
22 if (builtinID == Builtin::BI__builtin_cpu_supports ||
23 builtinID == Builtin::BI__builtin_cpu_init ||
24 builtinID == Builtin::BI__builtin_cpu_is) {
25 cgm.errorNYI(e->getSourceRange(),
26 std::string("unimplemented RISC-V builtin call: ") +
27 getContext().BuiltinInfo.getName(builtinID));
28 return mlir::Value{};
29 }
30
31 StringRef intrinsicName;
32 mlir::Type returnType = convertType(e->getType());
34
35 // `iceArguments` is a bitmap indicating whether the argument at the i-th bit
36 // is required to be a constant integer expression.
37 unsigned iceArguments = 0;
39 getContext().GetBuiltinType(builtinID, error, &iceArguments);
40 assert(error == ASTContext::GE_None && "Should not codegen an error");
41 for (auto [idx, arg] : llvm::enumerate(e->arguments()))
42 ops.push_back(emitScalarOrConstFoldImmArg(iceArguments, idx, arg));
43
44 switch (builtinID) {
45 default:
46 llvm_unreachable("unexpected builtin ID");
47
48 // Zbb
49 case RISCV::BI__builtin_riscv_orc_b_32:
50 case RISCV::BI__builtin_riscv_orc_b_64: {
51 intrinsicName = "riscv.orc.b";
52 break;
53 }
54
55 // Zbc
56 case RISCV::BI__builtin_riscv_clmul_32:
57 case RISCV::BI__builtin_riscv_clmul_64: {
58 intrinsicName = "clmul";
59 break;
60 }
61 case RISCV::BI__builtin_riscv_clmulh_32:
62 case RISCV::BI__builtin_riscv_clmulh_64: {
63 intrinsicName = "riscv.clmulh";
64 break;
65 }
66 case RISCV::BI__builtin_riscv_clmulr_32:
67 case RISCV::BI__builtin_riscv_clmulr_64: {
68 intrinsicName = "riscv.clmulr";
69 break;
70 }
71
72 // Zbkx
73 case RISCV::BI__builtin_riscv_xperm4_32:
74 case RISCV::BI__builtin_riscv_xperm4_64: {
75 intrinsicName = "riscv.xperm4";
76 break;
77 }
78 case RISCV::BI__builtin_riscv_xperm8_32:
79 case RISCV::BI__builtin_riscv_xperm8_64: {
80 intrinsicName = "riscv.xperm8";
81 break;
82 }
83 // Zbkb
84 case RISCV::BI__builtin_riscv_brev8_32:
85 case RISCV::BI__builtin_riscv_brev8_64: {
86 intrinsicName = "riscv.brev8";
87 break;
88 }
89 case RISCV::BI__builtin_riscv_zip_32: {
90 intrinsicName = "riscv.zip";
91 break;
92 }
93 case RISCV::BI__builtin_riscv_unzip_32: {
94 intrinsicName = "riscv.unzip";
95 break;
96 }
97 // Zknh
98 case RISCV::BI__builtin_riscv_sha256sig0: {
99 intrinsicName = "riscv.sha256sig0";
100 break;
101 }
102 case RISCV::BI__builtin_riscv_sha256sig1: {
103 intrinsicName = "riscv.sha256sig1";
104 break;
105 }
106 case RISCV::BI__builtin_riscv_sha256sum0: {
107 intrinsicName = "riscv.sha256sum0";
108 break;
109 }
110 case RISCV::BI__builtin_riscv_sha256sum1: {
111 intrinsicName = "riscv.sha256sum1";
112 break;
113 }
114 // Zksed
115 case RISCV::BI__builtin_riscv_sm4ks: {
116 intrinsicName = "riscv.sm4ks";
117 break;
118 }
119 case RISCV::BI__builtin_riscv_sm4ed: {
120 intrinsicName = "riscv.sm4ed";
121 break;
122 }
123 // Zksh
124 case RISCV::BI__builtin_riscv_sm3p0: {
125 intrinsicName = "riscv.sm3p0";
126 break;
127 }
128 case RISCV::BI__builtin_riscv_sm3p1: {
129 intrinsicName = "riscv.sm3p1";
130 break;
131 }
132 // Zbb
133 case RISCV::BI__builtin_riscv_clz_32:
134 case RISCV::BI__builtin_riscv_clz_64: {
135 mlir::Location loc = getLoc(e->getSourceRange());
136 auto op = cir::BitClzOp::create(builder, loc, ops[0],
137 /*poison_zero=*/false);
138 mlir::Value result = op.getResult();
139 if (result.getType() != returnType)
140 result = builder.createIntCast(result, returnType);
141 return result;
142 }
143 case RISCV::BI__builtin_riscv_ctz_32:
144 case RISCV::BI__builtin_riscv_ctz_64: {
145 mlir::Location loc = getLoc(e->getSourceRange());
146 auto op = cir::BitCtzOp::create(builder, loc, ops[0],
147 /*poison_zero=*/false);
148 mlir::Value result = op.getResult();
149 if (result.getType() != returnType)
150 result = builder.createIntCast(result, returnType);
151 return result;
152 }
153
154 // Zihintntl
155 case RISCV::BI__builtin_riscv_ntl_load:
156 case RISCV::BI__builtin_riscv_ntl_store: {
157 cgm.errorNYI(e->getSourceRange(),
158 std::string("unimplemented RISC-V builtin call: ") +
159 getContext().BuiltinInfo.getName(builtinID));
160 return mlir::Value{};
161 }
162
163 // Zihintpause
164 case RISCV::BI__builtin_riscv_pause: {
165 intrinsicName = "riscv.pause";
166 returnType = builder.getVoidTy();
167 break;
168 }
169
170 // XCValu
171 case RISCV::BI__builtin_riscv_cv_alu_addN: {
172 intrinsicName = "riscv.cv.alu.addN";
173 break;
174 }
175 case RISCV::BI__builtin_riscv_cv_alu_addRN: {
176 intrinsicName = "riscv.cv.alu.addRN";
177 break;
178 }
179 case RISCV::BI__builtin_riscv_cv_alu_adduN: {
180 intrinsicName = "riscv.cv.alu.adduN";
181 break;
182 }
183 case RISCV::BI__builtin_riscv_cv_alu_adduRN: {
184 intrinsicName = "riscv.cv.alu.adduRN";
185 break;
186 }
187 case RISCV::BI__builtin_riscv_cv_alu_clip: {
188 intrinsicName = "riscv.cv.alu.clip";
189 break;
190 }
191 case RISCV::BI__builtin_riscv_cv_alu_clipu: {
192 intrinsicName = "riscv.cv.alu.clipu";
193 break;
194 }
195 case RISCV::BI__builtin_riscv_cv_alu_extbs: {
196 mlir::Value result = builder.createIntCast(ops[0], builder.getSInt8Ty());
197 return builder.createIntCast(result, returnType);
198 }
199 case RISCV::BI__builtin_riscv_cv_alu_extbz: {
200 mlir::Value result = builder.createIntCast(ops[0], builder.getUInt8Ty());
201 return builder.createIntCast(result, returnType);
202 }
203 case RISCV::BI__builtin_riscv_cv_alu_exths: {
204 mlir::Value result = builder.createIntCast(ops[0], builder.getSInt16Ty());
205 return builder.createIntCast(result, returnType);
206 }
207 case RISCV::BI__builtin_riscv_cv_alu_exthz: {
208 mlir::Value result = builder.createIntCast(ops[0], builder.getUInt16Ty());
209 return builder.createIntCast(result, returnType);
210 }
211 case RISCV::BI__builtin_riscv_cv_alu_sle: {
212 mlir::Location loc = getLoc(e->getSourceRange());
213 mlir::Value result =
214 builder.createCompare(loc, cir::CmpOpKind::le, ops[0], ops[1]);
215 return builder.createBoolToInt(result, returnType);
216 }
217 case RISCV::BI__builtin_riscv_cv_alu_sleu: {
218 mlir::Location loc = getLoc(e->getSourceRange());
219 mlir::Value result =
220 builder.createCompare(loc, cir::CmpOpKind::le, ops[0], ops[1]);
221 return builder.createBoolToInt(result, returnType);
222 }
223 case RISCV::BI__builtin_riscv_cv_alu_subN: {
224 intrinsicName = "riscv.cv.alu.subN";
225 break;
226 }
227 case RISCV::BI__builtin_riscv_cv_alu_subRN: {
228 intrinsicName = "riscv.cv.alu.subRN";
229 break;
230 }
231 case RISCV::BI__builtin_riscv_cv_alu_subuN: {
232 intrinsicName = "riscv.cv.alu.subuN";
233 break;
234 }
235 case RISCV::BI__builtin_riscv_cv_alu_subuRN: {
236 intrinsicName = "riscv.cv.alu.subuRN";
237 break;
238 }
239 // XAndesPerf
240 case RISCV::BI__builtin_riscv_nds_ffb_32:
241 case RISCV::BI__builtin_riscv_nds_ffb_64:
242 case RISCV::BI__builtin_riscv_nds_ffzmism_32:
243 case RISCV::BI__builtin_riscv_nds_ffzmism_64:
244 case RISCV::BI__builtin_riscv_nds_ffmism_32:
245 case RISCV::BI__builtin_riscv_nds_ffmism_64:
246 case RISCV::BI__builtin_riscv_nds_flmism_32:
247 case RISCV::BI__builtin_riscv_nds_flmism_64:
248 // XAndesBFHCvt
249 case RISCV::BI__builtin_riscv_nds_fcvt_s_bf16:
250 case RISCV::BI__builtin_riscv_nds_fcvt_bf16_s: {
251 cgm.errorNYI(e->getSourceRange(),
252 std::string("unimplemented RISC-V builtin call: ") +
253 getContext().BuiltinInfo.getName(builtinID));
254 return mlir::Value{};
255 }
256
257 // TODO: Handle vector builtins in tablegen.
258 }
259
260 mlir::Location loc = getLoc(e->getSourceRange());
261 return builder.emitIntrinsicCallOp(loc, intrinsicName, returnType, ops);
262}
Enumerates target-specific builtins in their own namespaces within namespace clang.
QualType GetBuiltinType(unsigned ID, GetBuiltinTypeError &Error, unsigned *IntegerConstantArgs=nullptr) const
Return the type for the specified builtin.
@ GE_None
No error.
mlir::Type convertType(clang::QualType t)
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
std::optional< mlir::Value > emitRISCVBuiltinExpr(unsigned builtinID, const CallExpr *expr)
clang::ASTContext & getContext() const
mlir::Value emitScalarOrConstFoldImmArg(unsigned iceArguments, unsigned idx, const Expr *argExpr)
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2949
arg_range arguments()
Definition Expr.h:3201
QualType getType() const
Definition Expr.h:144
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:343
The JSON file list parser is used to communicate input to InstallAPI.