clang 23.0.0git
CIRBaseBuilder.h
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#ifndef LLVM_CLANG_CIR_DIALECT_BUILDER_CIRBASEBUILDER_H
10#define LLVM_CLANG_CIR_DIALECT_BUILDER_CIRBASEBUILDER_H
11
12#include "clang/AST/CharUnits.h"
18#include "llvm/ADT/STLForwardCompat.h"
19#include "llvm/IR/FPEnv.h"
20#include "llvm/Support/ErrorHandling.h"
21
22#include "mlir/IR/Builders.h"
23#include "mlir/IR/BuiltinAttributes.h"
24#include "mlir/IR/Location.h"
25#include "mlir/IR/OperationSupport.h"
26#include "mlir/IR/Types.h"
27
28namespace cir {
29
30enum class OverflowBehavior {
31 None = 0,
32 NoSignedWrap = 1 << 0,
34 Saturated = 1 << 2,
35};
36
38 return static_cast<OverflowBehavior>(llvm::to_underlying(a) |
39 llvm::to_underlying(b));
40}
41
43 return static_cast<OverflowBehavior>(llvm::to_underlying(a) &
44 llvm::to_underlying(b));
45}
46
49 a = a | b;
50 return a;
51}
52
55 a = a & b;
56 return a;
57}
58
59class CIRBaseBuilderTy : public mlir::OpBuilder {
60
61public:
62 CIRBaseBuilderTy(mlir::MLIRContext &mlirContext)
63 : mlir::OpBuilder(&mlirContext) {}
64 CIRBaseBuilderTy(mlir::OpBuilder &builder) : mlir::OpBuilder(builder) {}
65
66 mlir::Value getConstAPInt(mlir::Location loc, mlir::Type typ,
67 const llvm::APInt &val) {
68 return cir::ConstantOp::create(*this, loc, cir::IntAttr::get(typ, val));
69 }
70
71 cir::ConstantOp getConstant(mlir::Location loc, mlir::TypedAttr attr) {
72 return cir::ConstantOp::create(*this, loc, attr);
73 }
74
75 cir::ConstantOp getConstantInt(mlir::Location loc, mlir::Type ty,
76 int64_t value) {
77 return getConstant(loc, cir::IntAttr::get(ty, value));
78 }
79
80 mlir::Value getSignedInt(mlir::Location loc, int64_t val, unsigned numBits) {
81 auto type = cir::IntType::get(getContext(), numBits, /*isSigned=*/true);
82 return getConstAPInt(loc, type,
83 llvm::APInt(numBits, val, /*isSigned=*/true));
84 }
85
86 mlir::Value getUnsignedInt(mlir::Location loc, uint64_t val,
87 unsigned numBits) {
88 auto type = cir::IntType::get(getContext(), numBits, /*isSigned=*/false);
89 return getConstAPInt(loc, type, llvm::APInt(numBits, val));
90 }
91
92 // Creates constant null value for integral type ty.
93 cir::ConstantOp getNullValue(mlir::Type ty, mlir::Location loc) {
94 return getConstant(loc, getZeroInitAttr(ty));
95 }
96
97 mlir::TypedAttr getConstNullPtrAttr(mlir::Type t) {
98 assert(mlir::isa<cir::PointerType>(t) && "expected cir.ptr");
99 return getConstPtrAttr(t, 0);
100 }
101
102 mlir::TypedAttr getNullDataMemberAttr(cir::DataMemberType ty) {
103 return cir::DataMemberAttr::get(ty);
104 }
105
106 mlir::TypedAttr getZeroInitAttr(mlir::Type ty) {
107 if (mlir::isa<cir::IntType>(ty))
108 return cir::IntAttr::get(ty, 0);
109 if (cir::isAnyFloatingPointType(ty))
110 return cir::FPAttr::getZero(ty);
111 if (auto complexType = mlir::dyn_cast<cir::ComplexType>(ty))
112 return cir::ZeroAttr::get(complexType);
113 if (auto arrTy = mlir::dyn_cast<cir::ArrayType>(ty))
114 return cir::ZeroAttr::get(arrTy);
115 if (auto vecTy = mlir::dyn_cast<cir::VectorType>(ty))
116 return cir::ZeroAttr::get(vecTy);
117 if (auto ptrTy = mlir::dyn_cast<cir::PointerType>(ty))
118 return getConstNullPtrAttr(ptrTy);
119 if (auto recordTy = mlir::dyn_cast<cir::RecordType>(ty))
120 return cir::ZeroAttr::get(recordTy);
121 if (auto dataMemberTy = mlir::dyn_cast<cir::DataMemberType>(ty))
122 return getNullDataMemberAttr(dataMemberTy);
123 if (mlir::isa<cir::BoolType>(ty)) {
124 return getFalseAttr();
125 }
126 llvm_unreachable("Zero initializer for given type is NYI");
127 }
128
129 cir::ConstantOp getBool(bool state, mlir::Location loc) {
130 return cir::ConstantOp::create(*this, loc, getCIRBoolAttr(state));
131 }
132 cir::ConstantOp getFalse(mlir::Location loc) { return getBool(false, loc); }
133 cir::ConstantOp getTrue(mlir::Location loc) { return getBool(true, loc); }
134
135 cir::BoolType getBoolTy() { return cir::BoolType::get(getContext()); }
136 cir::VoidType getVoidTy() { return cir::VoidType::get(getContext()); }
137
138 cir::IntType getUIntNTy(int n) {
139 return cir::IntType::get(getContext(), n, false);
140 }
141
142 static unsigned getCIRIntOrFloatBitWidth(mlir::Type eltTy) {
143 if (auto intType = mlir::dyn_cast<cir::IntTypeInterface>(eltTy))
144 return intType.getWidth();
145 if (auto floatType = mlir::dyn_cast<cir::FPTypeInterface>(eltTy))
146 return floatType.getWidth();
147
148 llvm_unreachable("Unsupported type in getCIRIntOrFloatBitWidth");
149 }
150 cir::IntType getSIntNTy(int n) {
151 return cir::IntType::get(getContext(), n, true);
152 }
153
154 cir::PointerType getPointerTo(mlir::Type ty) {
155 return cir::PointerType::get(ty);
156 }
157
158 cir::PointerType getPointerTo(mlir::Type ty,
159 mlir::ptr::MemorySpaceAttrInterface as) {
160 return cir::PointerType::get(ty, as);
161 }
162
163 cir::PointerType getPointerTo(mlir::Type ty, clang::LangAS langAS) {
164 if (langAS == clang::LangAS::Default)
165 return getPointerTo(ty);
166
167 mlir::ptr::MemorySpaceAttrInterface addrSpaceAttr =
168 cir::toCIRAddressSpaceAttr(*getContext(), langAS);
169 return getPointerTo(ty, addrSpaceAttr);
170 }
171
173 return getPointerTo(cir::VoidType::get(getContext()), langAS);
174 }
175
176 cir::PointerType getVoidPtrTy(mlir::ptr::MemorySpaceAttrInterface as) {
177 return getPointerTo(cir::VoidType::get(getContext()), as);
178 }
179
180 cir::MethodAttr getMethodAttr(cir::MethodType ty, cir::FuncOp methodFuncOp) {
181 auto methodFuncSymbolRef = mlir::FlatSymbolRefAttr::get(methodFuncOp);
182 return cir::MethodAttr::get(ty, methodFuncSymbolRef);
183 }
184
185 cir::MethodAttr getNullMethodAttr(cir::MethodType ty) {
186 return cir::MethodAttr::get(ty);
187 }
188
189 cir::BoolAttr getCIRBoolAttr(bool state) {
190 return cir::BoolAttr::get(getContext(), state);
191 }
192
193 cir::BoolAttr getTrueAttr() { return getCIRBoolAttr(true); }
194 cir::BoolAttr getFalseAttr() { return getCIRBoolAttr(false); }
195
196 mlir::Value createComplexCreate(mlir::Location loc, mlir::Value real,
197 mlir::Value imag) {
198 auto resultComplexTy = cir::ComplexType::get(real.getType());
199 return cir::ComplexCreateOp::create(*this, loc, resultComplexTy, real,
200 imag);
201 }
202
203 mlir::Value createComplexReal(mlir::Location loc, mlir::Value operand) {
204 auto resultType = operand.getType();
205 if (auto complexResultType = mlir::dyn_cast<cir::ComplexType>(resultType))
206 resultType = complexResultType.getElementType();
207 return cir::ComplexRealOp::create(*this, loc, resultType, operand);
208 }
209
210 mlir::Value createComplexImag(mlir::Location loc, mlir::Value operand) {
211 auto resultType = operand.getType();
212 if (auto complexResultType = mlir::dyn_cast<cir::ComplexType>(resultType))
213 resultType = complexResultType.getElementType();
214 return cir::ComplexImagOp::create(*this, loc, resultType, operand);
215 }
216
217 cir::LoadOp createLoad(mlir::Location loc, mlir::Value ptr,
218 bool isVolatile = false, uint64_t alignment = 0) {
219 mlir::IntegerAttr alignmentAttr = getAlignmentAttr(alignment);
220 return cir::LoadOp::create(*this, loc, ptr, /*isDeref=*/false, isVolatile,
221 alignmentAttr, cir::SyncScopeKindAttr{},
222 cir::MemOrderAttr{});
223 }
224
225 mlir::Value createAlignedLoad(mlir::Location loc, mlir::Value ptr,
226 uint64_t alignment) {
227 return createLoad(loc, ptr, /*isVolatile=*/false, alignment);
228 }
229
230 mlir::Value createNot(mlir::Value value) {
231 return cir::UnaryOp::create(*this, value.getLoc(), value.getType(),
232 cir::UnaryOpKind::Not, value);
233 }
234
235 /// Create a do-while operation.
236 cir::DoWhileOp createDoWhile(
237 mlir::Location loc,
238 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> condBuilder,
239 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> bodyBuilder) {
240 return cir::DoWhileOp::create(*this, loc, condBuilder, bodyBuilder);
241 }
242
243 /// Create a while operation.
244 cir::WhileOp createWhile(
245 mlir::Location loc,
246 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> condBuilder,
247 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> bodyBuilder) {
248 return cir::WhileOp::create(*this, loc, condBuilder, bodyBuilder);
249 }
250
251 /// Create a for operation.
252 cir::ForOp createFor(
253 mlir::Location loc,
254 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> condBuilder,
255 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> bodyBuilder,
256 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> stepBuilder) {
257 return cir::ForOp::create(*this, loc, condBuilder, bodyBuilder,
258 stepBuilder);
259 }
260
261 /// Create a break operation.
262 cir::BreakOp createBreak(mlir::Location loc) {
263 return cir::BreakOp::create(*this, loc);
264 }
265
266 /// Create a continue operation.
267 cir::ContinueOp createContinue(mlir::Location loc) {
268 return cir::ContinueOp::create(*this, loc);
269 }
270
271 mlir::Value createUnaryOp(mlir::Location loc, cir::UnaryOpKind kind,
272 mlir::Value operand) {
273 return cir::UnaryOp::create(*this, loc, kind, operand);
274 }
275
276 mlir::TypedAttr getConstPtrAttr(mlir::Type type, int64_t value) {
277 return cir::ConstPtrAttr::get(type, getI64IntegerAttr(value));
278 }
279
280 mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType,
281 mlir::Type type, llvm::StringRef name,
282 mlir::IntegerAttr alignment,
283 mlir::Value dynAllocSize) {
284 return cir::AllocaOp::create(*this, loc, addrType, type, name, alignment,
285 dynAllocSize);
286 }
287
288 mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType,
289 mlir::Type type, llvm::StringRef name,
290 clang::CharUnits alignment,
291 mlir::Value dynAllocSize) {
292 mlir::IntegerAttr alignmentAttr = getAlignmentAttr(alignment);
293 return createAlloca(loc, addrType, type, name, alignmentAttr, dynAllocSize);
294 }
295
296 mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType,
297 mlir::Type type, llvm::StringRef name,
298 mlir::IntegerAttr alignment) {
299 return cir::AllocaOp::create(*this, loc, addrType, type, name, alignment);
300 }
301
302 mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType,
303 mlir::Type type, llvm::StringRef name,
304 clang::CharUnits alignment) {
305 mlir::IntegerAttr alignmentAttr = getAlignmentAttr(alignment);
306 return createAlloca(loc, addrType, type, name, alignmentAttr);
307 }
308
309 /// Get constant address of a global variable as an MLIR attribute.
310 /// This wrapper infers the attribute type through the global op.
311 cir::GlobalViewAttr getGlobalViewAttr(cir::GlobalOp globalOp,
312 mlir::ArrayAttr indices = {}) {
313 cir::PointerType type = getPointerTo(globalOp.getSymType());
314 return getGlobalViewAttr(type, globalOp, indices);
315 }
316
317 /// Get constant address of a global variable as an MLIR attribute.
318 cir::GlobalViewAttr getGlobalViewAttr(cir::PointerType type,
319 cir::GlobalOp globalOp,
320 mlir::ArrayAttr indices = {}) {
321 auto symbol = mlir::FlatSymbolRefAttr::get(globalOp.getSymNameAttr());
322 return cir::GlobalViewAttr::get(type, symbol, indices);
323 }
324
325 mlir::Value createGetGlobal(mlir::Location loc, cir::GlobalOp global,
326 bool threadLocal = false) {
328 return cir::GetGlobalOp::create(*this, loc,
329 getPointerTo(global.getSymType()),
330 global.getSymNameAttr(), threadLocal);
331 }
332
333 mlir::Value createGetGlobal(cir::GlobalOp global, bool threadLocal = false) {
334 return createGetGlobal(global.getLoc(), global, threadLocal);
335 }
336
337 /// Create a copy with inferred length.
338 cir::CopyOp createCopy(mlir::Value dst, mlir::Value src,
339 bool isVolatile = false) {
340 return cir::CopyOp::create(*this, dst.getLoc(), dst, src, isVolatile);
341 }
342
343 cir::StoreOp createStore(mlir::Location loc, mlir::Value val, mlir::Value dst,
344 bool isVolatile = false,
345 mlir::IntegerAttr align = {},
346 cir::SyncScopeKindAttr scope = {},
347 cir::MemOrderAttr order = {}) {
348 return cir::StoreOp::create(*this, loc, val, dst, isVolatile, align, scope,
349 order);
350 }
351
352 /// Emit a load from an boolean flag variable.
353 cir::LoadOp createFlagLoad(mlir::Location loc, mlir::Value addr) {
354 mlir::Type boolTy = getBoolTy();
355 if (boolTy != mlir::cast<cir::PointerType>(addr.getType()).getPointee())
356 addr = createPtrBitcast(addr, boolTy);
357 return createLoad(loc, addr, /*isVolatile=*/false, /*alignment=*/1);
358 }
359
360 cir::StoreOp createFlagStore(mlir::Location loc, bool val, mlir::Value dst) {
361 mlir::Value flag = getBool(val, loc);
362 return CIRBaseBuilderTy::createStore(loc, flag, dst);
363 }
364
365 [[nodiscard]] cir::GlobalOp createGlobal(mlir::ModuleOp mlirModule,
366 mlir::Location loc,
367 mlir::StringRef name,
368 mlir::Type type, bool isConstant,
369 cir::GlobalLinkageKind linkage) {
370 mlir::OpBuilder::InsertionGuard guard(*this);
371 setInsertionPointToStart(mlirModule.getBody());
372 return cir::GlobalOp::create(*this, loc, name, type, isConstant, linkage);
373 }
374
375 cir::GetMemberOp createGetMember(mlir::Location loc, mlir::Type resultTy,
376 mlir::Value base, llvm::StringRef name,
377 unsigned index) {
378 return cir::GetMemberOp::create(*this, loc, resultTy, base, name, index);
379 }
380
381 mlir::Value createDummyValue(mlir::Location loc, mlir::Type type,
382 clang::CharUnits alignment) {
383 mlir::IntegerAttr alignmentAttr = getAlignmentAttr(alignment);
384 auto addr = createAlloca(loc, getPointerTo(type), type, {}, alignmentAttr);
385 return cir::LoadOp::create(*this, loc, addr, /*isDeref=*/false,
386 /*isVolatile=*/false, alignmentAttr,
387 /*sync_scope=*/{}, /*mem_order=*/{});
388 }
389
390 cir::PtrStrideOp createPtrStride(mlir::Location loc, mlir::Value base,
391 mlir::Value stride) {
392 return cir::PtrStrideOp::create(*this, loc, base.getType(), base, stride);
393 }
394
395 //===--------------------------------------------------------------------===//
396 // Call operators
397 //===--------------------------------------------------------------------===//
398
399 cir::CallOp createCallOp(mlir::Location loc, mlir::SymbolRefAttr callee,
400 mlir::Type returnType, mlir::ValueRange operands,
404 auto op = cir::CallOp::create(*this, loc, callee, returnType, operands);
405 op->setAttrs(attrs);
406
407 if (!argAttrs.empty()) {
408 llvm::SmallVector<mlir::Attribute> argDictAttrs;
409 argDictAttrs.reserve(argAttrs.size());
410
411 llvm::transform(
412 argAttrs, std::back_inserter(argDictAttrs),
413 [this](llvm::ArrayRef<mlir::NamedAttribute> singleArgAttrs) {
414 return mlir::DictionaryAttr::get(getContext(), singleArgAttrs);
415 });
416
417 op.setArgAttrsAttr(mlir::ArrayAttr::get(getContext(), argDictAttrs));
418 }
419
420 if (!resAttrs.empty()) {
421 auto resultDictAttr = mlir::DictionaryAttr::get(getContext(), resAttrs);
422 op.setResAttrsAttr(mlir::ArrayAttr::get(getContext(), resultDictAttr));
423 }
424 return op;
425 }
426
427 cir::CallOp createCallOp(mlir::Location loc, cir::FuncOp callee,
428 mlir::ValueRange operands,
432 return createCallOp(loc, mlir::SymbolRefAttr::get(callee),
433 callee.getFunctionType().getReturnType(), operands,
434 attrs, argAttrs, resAttrs);
435 }
436
437 cir::CallOp
438 createIndirectCallOp(mlir::Location loc, mlir::Value indirectTarget,
439 cir::FuncType funcType, mlir::ValueRange operands,
443 llvm::SmallVector<mlir::Value> resOperands{indirectTarget};
444 resOperands.append(operands.begin(), operands.end());
445
446 return createCallOp(loc, mlir::SymbolRefAttr(), funcType.getReturnType(),
447 resOperands, attrs, argAttrs, resAttrs);
448 }
449
450 cir::CallOp createCallOp(mlir::Location loc, mlir::SymbolRefAttr callee,
451 mlir::ValueRange operands = mlir::ValueRange(),
455 return createCallOp(loc, callee, cir::VoidType(), operands, attrs, argAttrs,
456 resAttrs);
457 }
458
459 //===--------------------------------------------------------------------===//
460 // Cast/Conversion Operators
461 //===--------------------------------------------------------------------===//
462
463 mlir::Value createCast(mlir::Location loc, cir::CastKind kind,
464 mlir::Value src, mlir::Type newTy) {
465 if (newTy == src.getType())
466 return src;
467 return cir::CastOp::create(*this, loc, newTy, kind, src);
468 }
469
470 mlir::Value createCast(cir::CastKind kind, mlir::Value src,
471 mlir::Type newTy) {
472 if (newTy == src.getType())
473 return src;
474 return createCast(src.getLoc(), kind, src, newTy);
475 }
476
477 mlir::Value createIntCast(mlir::Value src, mlir::Type newTy) {
478 return createCast(cir::CastKind::integral, src, newTy);
479 }
480
481 mlir::Value createIntToPtr(mlir::Value src, mlir::Type newTy) {
482 return createCast(cir::CastKind::int_to_ptr, src, newTy);
483 }
484
485 mlir::Value createPtrToInt(mlir::Value src, mlir::Type newTy) {
486 return createCast(cir::CastKind::ptr_to_int, src, newTy);
487 }
488
489 mlir::Value createPtrToBoolCast(mlir::Value v) {
490 return createCast(cir::CastKind::ptr_to_bool, v, getBoolTy());
491 }
492
493 mlir::Value createBoolToInt(mlir::Value src, mlir::Type newTy) {
494 return createCast(cir::CastKind::bool_to_int, src, newTy);
495 }
496
497 mlir::Value createBitcast(mlir::Value src, mlir::Type newTy) {
498 return createCast(cir::CastKind::bitcast, src, newTy);
499 }
500
501 mlir::Value createBitcast(mlir::Location loc, mlir::Value src,
502 mlir::Type newTy) {
503 return createCast(loc, cir::CastKind::bitcast, src, newTy);
504 }
505
506 mlir::Value createPtrBitcast(mlir::Value src, mlir::Type newPointeeTy) {
507 assert(mlir::isa<cir::PointerType>(src.getType()) && "expected ptr src");
508 return createBitcast(src, getPointerTo(newPointeeTy));
509 }
510
511 mlir::Value createPtrIsNull(mlir::Value ptr) {
512 mlir::Value nullPtr = getNullPtr(ptr.getType(), ptr.getLoc());
513 return createCompare(ptr.getLoc(), cir::CmpOpKind::eq, ptr, nullPtr);
514 }
515
516 mlir::Value createAddrSpaceCast(mlir::Location loc, mlir::Value src,
517 mlir::Type newTy) {
518 return createCast(loc, cir::CastKind::address_space, src, newTy);
519 }
520
521 mlir::Value createAddrSpaceCast(mlir::Value src, mlir::Type newTy) {
522 return createAddrSpaceCast(src.getLoc(), src, newTy);
523 }
524
525 //===--------------------------------------------------------------------===//
526 // Other Instructions
527 //===--------------------------------------------------------------------===//
528
529 mlir::Value createExtractElement(mlir::Location loc, mlir::Value vec,
530 uint64_t idx) {
531 mlir::Value idxVal =
532 getConstAPInt(loc, getUIntNTy(64), llvm::APInt(64, idx));
533 return cir::VecExtractOp::create(*this, loc, vec, idxVal);
534 }
535
536 mlir::Value createInsertElement(mlir::Location loc, mlir::Value vec,
537 mlir::Value newElt, uint64_t idx) {
538 mlir::Value idxVal =
539 getConstAPInt(loc, getUIntNTy(64), llvm::APInt(64, idx));
540 return cir::VecInsertOp::create(*this, loc, vec, newElt, idxVal);
541 }
542
543 //===--------------------------------------------------------------------===//
544 // Binary Operators
545 //===--------------------------------------------------------------------===//
546
547 mlir::Value createBinop(mlir::Location loc, mlir::Value lhs,
548 cir::BinOpKind kind, mlir::Value rhs) {
549 return cir::BinOp::create(*this, loc, lhs.getType(), kind, lhs, rhs);
550 }
551
552 mlir::Value createLowBitsSet(mlir::Location loc, unsigned size,
553 unsigned bits) {
554 llvm::APInt val = llvm::APInt::getLowBitsSet(size, bits);
555 auto type = cir::IntType::get(getContext(), size, /*isSigned=*/false);
556 return getConstAPInt(loc, type, val);
557 }
558
559 mlir::Value createAnd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
560 return createBinop(loc, lhs, cir::BinOpKind::And, rhs);
561 }
562
563 mlir::Value createOr(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
564 return createBinop(loc, lhs, cir::BinOpKind::Or, rhs);
565 }
566
567 mlir::Value createSelect(mlir::Location loc, mlir::Value condition,
568 mlir::Value trueValue, mlir::Value falseValue) {
569 assert(trueValue.getType() == falseValue.getType() &&
570 "trueValue and falseValue should have the same type");
571 return cir::SelectOp::create(*this, loc, trueValue.getType(), condition,
572 trueValue, falseValue);
573 }
574
575 mlir::Value createLogicalAnd(mlir::Location loc, mlir::Value lhs,
576 mlir::Value rhs) {
577 return createSelect(loc, lhs, rhs, getBool(false, loc));
578 }
579
580 mlir::Value createLogicalOr(mlir::Location loc, mlir::Value lhs,
581 mlir::Value rhs) {
582 return createSelect(loc, lhs, getBool(true, loc), rhs);
583 }
584
585 mlir::Value createMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs,
587 auto op = cir::BinOp::create(*this, loc, lhs.getType(), cir::BinOpKind::Mul,
588 lhs, rhs);
589 op.setNoUnsignedWrap(
590 llvm::to_underlying(ob & OverflowBehavior::NoUnsignedWrap));
591 op.setNoSignedWrap(
592 llvm::to_underlying(ob & OverflowBehavior::NoSignedWrap));
593 return op;
594 }
595 mlir::Value createNSWMul(mlir::Location loc, mlir::Value lhs,
596 mlir::Value rhs) {
597 return createMul(loc, lhs, rhs, OverflowBehavior::NoSignedWrap);
598 }
599 mlir::Value createNUWAMul(mlir::Location loc, mlir::Value lhs,
600 mlir::Value rhs) {
601 return createMul(loc, lhs, rhs, OverflowBehavior::NoUnsignedWrap);
602 }
603
604 mlir::Value createSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs,
606 auto op = cir::BinOp::create(*this, loc, lhs.getType(), cir::BinOpKind::Sub,
607 lhs, rhs);
608 op.setNoUnsignedWrap(
609 llvm::to_underlying(ob & OverflowBehavior::NoUnsignedWrap));
610 op.setNoSignedWrap(
611 llvm::to_underlying(ob & OverflowBehavior::NoSignedWrap));
612 op.setSaturated(llvm::to_underlying(ob & OverflowBehavior::Saturated));
613 return op;
614 }
615
616 mlir::Value createNSWSub(mlir::Location loc, mlir::Value lhs,
617 mlir::Value rhs) {
618 return createSub(loc, lhs, rhs, OverflowBehavior::NoSignedWrap);
619 }
620
621 mlir::Value createNUWSub(mlir::Location loc, mlir::Value lhs,
622 mlir::Value rhs) {
623 return createSub(loc, lhs, rhs, OverflowBehavior::NoUnsignedWrap);
624 }
625
626 mlir::Value createAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs,
628 auto op = cir::BinOp::create(*this, loc, lhs.getType(), cir::BinOpKind::Add,
629 lhs, rhs);
630 op.setNoUnsignedWrap(
631 llvm::to_underlying(ob & OverflowBehavior::NoUnsignedWrap));
632 op.setNoSignedWrap(
633 llvm::to_underlying(ob & OverflowBehavior::NoSignedWrap));
634 op.setSaturated(llvm::to_underlying(ob & OverflowBehavior::Saturated));
635 return op;
636 }
637
638 mlir::Value createNSWAdd(mlir::Location loc, mlir::Value lhs,
639 mlir::Value rhs) {
640 return createAdd(loc, lhs, rhs, OverflowBehavior::NoSignedWrap);
641 }
642
643 mlir::Value createNUWAdd(mlir::Location loc, mlir::Value lhs,
644 mlir::Value rhs) {
645 return createAdd(loc, lhs, rhs, OverflowBehavior::NoUnsignedWrap);
646 }
647
648 cir::CmpOp createCompare(mlir::Location loc, cir::CmpOpKind kind,
649 mlir::Value lhs, mlir::Value rhs) {
650 return cir::CmpOp::create(*this, loc, kind, lhs, rhs);
651 }
652
653 cir::VecCmpOp createVecCompare(mlir::Location loc, cir::CmpOpKind kind,
654 mlir::Value lhs, mlir::Value rhs) {
655 VectorType vecCast = mlir::cast<VectorType>(lhs.getType());
656 IntType integralTy =
657 getSIntNTy(getCIRIntOrFloatBitWidth(vecCast.getElementType()));
658 VectorType integralVecTy =
659 cir::VectorType::get(integralTy, vecCast.getSize());
660 return cir::VecCmpOp::create(*this, loc, integralVecTy, kind, lhs, rhs);
661 }
662
663 mlir::Value createIsNaN(mlir::Location loc, mlir::Value operand) {
664 return createCompare(loc, cir::CmpOpKind::ne, operand, operand);
665 }
666
667 mlir::Value createShift(mlir::Location loc, mlir::Value lhs, mlir::Value rhs,
668 bool isShiftLeft) {
669 return cir::ShiftOp::create(*this, loc, lhs.getType(), lhs, rhs,
670 isShiftLeft);
671 }
672
673 mlir::Value createShift(mlir::Location loc, mlir::Value lhs,
674 const llvm::APInt &rhs, bool isShiftLeft) {
675 return createShift(loc, lhs, getConstAPInt(loc, lhs.getType(), rhs),
676 isShiftLeft);
677 }
678
679 mlir::Value createShift(mlir::Location loc, mlir::Value lhs, unsigned bits,
680 bool isShiftLeft) {
681 auto width = mlir::dyn_cast<cir::IntType>(lhs.getType()).getWidth();
682 auto shift = llvm::APInt(width, bits);
683 return createShift(loc, lhs, shift, isShiftLeft);
684 }
685
686 mlir::Value createShiftLeft(mlir::Location loc, mlir::Value lhs,
687 unsigned bits) {
688 return createShift(loc, lhs, bits, true);
689 }
690
691 mlir::Value createShiftRight(mlir::Location loc, mlir::Value lhs,
692 unsigned bits) {
693 return createShift(loc, lhs, bits, false);
694 }
695
696 mlir::Value createShiftLeft(mlir::Location loc, mlir::Value lhs,
697 mlir::Value rhs) {
698 return createShift(loc, lhs, rhs, true);
699 }
700
701 mlir::Value createShiftRight(mlir::Location loc, mlir::Value lhs,
702 mlir::Value rhs) {
703 return createShift(loc, lhs, rhs, false);
704 }
705
706 //
707 // Block handling helpers
708 // ----------------------
709 //
710 static OpBuilder::InsertPoint getBestAllocaInsertPoint(mlir::Block *block) {
711 auto last =
712 std::find_if(block->rbegin(), block->rend(), [](mlir::Operation &op) {
713 return mlir::isa<cir::AllocaOp, cir::LabelOp>(&op);
714 });
715
716 if (last != block->rend())
717 return OpBuilder::InsertPoint(block, ++mlir::Block::iterator(&*last));
718 return OpBuilder::InsertPoint(block, block->begin());
719 };
720
721 //
722 // Alignment and size helpers
723 //
724
725 // Note that mlir::IntegerType is used instead of cir::IntType here because we
726 // don't need sign information for these to be useful, so keep it simple.
727
728 // For 0 alignment, any overload of `getAlignmentAttr` returns an empty
729 // attribute.
730 mlir::IntegerAttr getAlignmentAttr(clang::CharUnits alignment) {
731 return getAlignmentAttr(alignment.getQuantity());
732 }
733
734 mlir::IntegerAttr getAlignmentAttr(llvm::Align alignment) {
735 return getAlignmentAttr(alignment.value());
736 }
737
738 mlir::IntegerAttr getAlignmentAttr(int64_t alignment) {
739 return alignment ? getI64IntegerAttr(alignment) : mlir::IntegerAttr();
740 }
741
742 mlir::IntegerAttr getSizeFromCharUnits(clang::CharUnits size) {
743 return getI64IntegerAttr(size.getQuantity());
744 }
745
746 // Creates constant nullptr for pointer type ty.
747 cir::ConstantOp getNullPtr(mlir::Type ty, mlir::Location loc) {
749 return cir::ConstantOp::create(*this, loc, getConstPtrAttr(ty, 0));
750 }
751
752 /// Create a loop condition.
753 cir::ConditionOp createCondition(mlir::Value condition) {
754 return cir::ConditionOp::create(*this, condition.getLoc(), condition);
755 }
756
757 /// Create a yield operation.
758 cir::YieldOp createYield(mlir::Location loc, mlir::ValueRange value = {}) {
759 return cir::YieldOp::create(*this, loc, value);
760 }
761
763 mlir::Value callee;
764 mlir::Value adjustedThis;
765 };
766
767 GetMethodResults createGetMethod(mlir::Location loc, mlir::Value method,
768 mlir::Value objectPtr) {
769 // Build the callee function type.
770 auto methodFuncTy =
771 mlir::cast<cir::MethodType>(method.getType()).getMemberFuncTy();
772 auto methodFuncInputTypes = methodFuncTy.getInputs();
773
774 auto objectPtrTy = mlir::cast<cir::PointerType>(objectPtr.getType());
775 mlir::Type adjustedThisTy = getVoidPtrTy(objectPtrTy.getAddrSpace());
776
777 llvm::SmallVector<mlir::Type> calleeFuncInputTypes{adjustedThisTy};
778 calleeFuncInputTypes.insert(calleeFuncInputTypes.end(),
779 methodFuncInputTypes.begin(),
780 methodFuncInputTypes.end());
781 cir::FuncType calleeFuncTy =
782 methodFuncTy.clone(calleeFuncInputTypes, methodFuncTy.getReturnType());
783 // TODO(cir): consider the address space of the callee.
785 cir::PointerType calleeTy = getPointerTo(calleeFuncTy);
786
787 auto op = cir::GetMethodOp::create(*this, loc, calleeTy, adjustedThisTy,
788 method, objectPtr);
789 return {op.getCallee(), op.getAdjustedThis()};
790 }
791};
792
793} // namespace cir
794
795#endif
Provides definitions for the various language-specific address spaces.
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a an optional score condition
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
__device__ __2f16 b
mlir::Value createNSWSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::ConstantOp getBool(bool state, mlir::Location loc)
mlir::Value createShift(mlir::Location loc, mlir::Value lhs, unsigned bits, bool isShiftLeft)
cir::StoreOp createFlagStore(mlir::Location loc, bool val, mlir::Value dst)
cir::WhileOp createWhile(mlir::Location loc, llvm::function_ref< void(mlir::OpBuilder &, mlir::Location)> condBuilder, llvm::function_ref< void(mlir::OpBuilder &, mlir::Location)> bodyBuilder)
Create a while operation.
cir::BreakOp createBreak(mlir::Location loc)
Create a break operation.
mlir::TypedAttr getConstNullPtrAttr(mlir::Type t)
cir::PointerType getVoidPtrTy(mlir::ptr::MemorySpaceAttrInterface as)
mlir::IntegerAttr getAlignmentAttr(int64_t alignment)
mlir::Value createShift(mlir::Location loc, mlir::Value lhs, const llvm::APInt &rhs, bool isShiftLeft)
mlir::Value getConstAPInt(mlir::Location loc, mlir::Type typ, const llvm::APInt &val)
cir::GlobalViewAttr getGlobalViewAttr(cir::PointerType type, cir::GlobalOp globalOp, mlir::ArrayAttr indices={})
Get constant address of a global variable as an MLIR attribute.
mlir::Value createCast(cir::CastKind kind, mlir::Value src, mlir::Type newTy)
mlir::Value createLogicalOr(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createShift(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, bool isShiftLeft)
mlir::Value createSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, OverflowBehavior ob=OverflowBehavior::None)
cir::ConditionOp createCondition(mlir::Value condition)
Create a loop condition.
mlir::Value createLowBitsSet(mlir::Location loc, unsigned size, unsigned bits)
mlir::Value createNSWAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createGetGlobal(cir::GlobalOp global, bool threadLocal=false)
cir::GlobalViewAttr getGlobalViewAttr(cir::GlobalOp globalOp, mlir::ArrayAttr indices={})
Get constant address of a global variable as an MLIR attribute.
cir::MethodAttr getMethodAttr(cir::MethodType ty, cir::FuncOp methodFuncOp)
cir::VoidType getVoidTy()
cir::ConstantOp getNullValue(mlir::Type ty, mlir::Location loc)
cir::BoolAttr getCIRBoolAttr(bool state)
mlir::Value createBoolToInt(mlir::Value src, mlir::Type newTy)
cir::ConstantOp getConstant(mlir::Location loc, mlir::TypedAttr attr)
cir::MethodAttr getNullMethodAttr(cir::MethodType ty)
mlir::Value createNUWAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createOr(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createPtrIsNull(mlir::Value ptr)
mlir::Value createShiftLeft(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createCast(mlir::Location loc, cir::CastKind kind, mlir::Value src, mlir::Type newTy)
mlir::IntegerAttr getSizeFromCharUnits(clang::CharUnits size)
cir::PtrStrideOp createPtrStride(mlir::Location loc, mlir::Value base, mlir::Value stride)
mlir::Value createIntToPtr(mlir::Value src, mlir::Type newTy)
cir::ForOp createFor(mlir::Location loc, llvm::function_ref< void(mlir::OpBuilder &, mlir::Location)> condBuilder, llvm::function_ref< void(mlir::OpBuilder &, mlir::Location)> bodyBuilder, llvm::function_ref< void(mlir::OpBuilder &, mlir::Location)> stepBuilder)
Create a for operation.
static OpBuilder::InsertPoint getBestAllocaInsertPoint(mlir::Block *block)
mlir::Value createPtrToInt(mlir::Value src, mlir::Type newTy)
mlir::Value createNUWSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::ConstantOp getFalse(mlir::Location loc)
cir::CallOp createCallOp(mlir::Location loc, mlir::SymbolRefAttr callee, mlir::ValueRange operands=mlir::ValueRange(), llvm::ArrayRef< mlir::NamedAttribute > attrs={}, llvm::ArrayRef< mlir::NamedAttrList > argAttrs={}, llvm::ArrayRef< mlir::NamedAttribute > resAttrs={})
mlir::Value createAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, OverflowBehavior ob=OverflowBehavior::None)
cir::GetMemberOp createGetMember(mlir::Location loc, mlir::Type resultTy, mlir::Value base, llvm::StringRef name, unsigned index)
cir::PointerType getPointerTo(mlir::Type ty)
mlir::Value createNot(mlir::Value value)
mlir::Value createComplexImag(mlir::Location loc, mlir::Value operand)
cir::ConstantOp getTrue(mlir::Location loc)
mlir::Value createNSWMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::ConstantOp getNullPtr(mlir::Type ty, mlir::Location loc)
cir::IntType getUIntNTy(int n)
cir::DoWhileOp createDoWhile(mlir::Location loc, llvm::function_ref< void(mlir::OpBuilder &, mlir::Location)> condBuilder, llvm::function_ref< void(mlir::OpBuilder &, mlir::Location)> bodyBuilder)
Create a do-while operation.
mlir::Value createNUWAMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::CopyOp createCopy(mlir::Value dst, mlir::Value src, bool isVolatile=false)
Create a copy with inferred length.
mlir::Value createPtrBitcast(mlir::Value src, mlir::Type newPointeeTy)
mlir::Value createShiftLeft(mlir::Location loc, mlir::Value lhs, unsigned bits)
mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType, mlir::Type type, llvm::StringRef name, clang::CharUnits alignment, mlir::Value dynAllocSize)
mlir::Value getSignedInt(mlir::Location loc, int64_t val, unsigned numBits)
mlir::Value createAnd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::PointerType getPointerTo(mlir::Type ty, clang::LangAS langAS)
mlir::Value createExtractElement(mlir::Location loc, mlir::Value vec, uint64_t idx)
cir::VecCmpOp createVecCompare(mlir::Location loc, cir::CmpOpKind kind, mlir::Value lhs, mlir::Value rhs)
mlir::Value createIntCast(mlir::Value src, mlir::Type newTy)
mlir::Value createInsertElement(mlir::Location loc, mlir::Value vec, mlir::Value newElt, uint64_t idx)
mlir::Value createBitcast(mlir::Value src, mlir::Type newTy)
CIRBaseBuilderTy(mlir::MLIRContext &mlirContext)
mlir::Value createBitcast(mlir::Location loc, mlir::Value src, mlir::Type newTy)
mlir::TypedAttr getNullDataMemberAttr(cir::DataMemberType ty)
cir::GlobalOp createGlobal(mlir::ModuleOp mlirModule, mlir::Location loc, mlir::StringRef name, mlir::Type type, bool isConstant, cir::GlobalLinkageKind linkage)
mlir::Value createGetGlobal(mlir::Location loc, cir::GlobalOp global, bool threadLocal=false)
cir::CmpOp createCompare(mlir::Location loc, cir::CmpOpKind kind, mlir::Value lhs, mlir::Value rhs)
mlir::IntegerAttr getAlignmentAttr(clang::CharUnits alignment)
mlir::Value createBinop(mlir::Location loc, mlir::Value lhs, cir::BinOpKind kind, mlir::Value rhs)
mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType, mlir::Type type, llvm::StringRef name, mlir::IntegerAttr alignment)
mlir::Value createSelect(mlir::Location loc, mlir::Value condition, mlir::Value trueValue, mlir::Value falseValue)
cir::ContinueOp createContinue(mlir::Location loc)
Create a continue operation.
mlir::Value createMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, OverflowBehavior ob=OverflowBehavior::None)
cir::PointerType getPointerTo(mlir::Type ty, mlir::ptr::MemorySpaceAttrInterface as)
mlir::TypedAttr getZeroInitAttr(mlir::Type ty)
cir::LoadOp createLoad(mlir::Location loc, mlir::Value ptr, bool isVolatile=false, uint64_t alignment=0)
mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType, mlir::Type type, llvm::StringRef name, clang::CharUnits alignment)
CIRBaseBuilderTy(mlir::OpBuilder &builder)
static unsigned getCIRIntOrFloatBitWidth(mlir::Type eltTy)
cir::CallOp createIndirectCallOp(mlir::Location loc, mlir::Value indirectTarget, cir::FuncType funcType, mlir::ValueRange operands, llvm::ArrayRef< mlir::NamedAttribute > attrs={}, llvm::ArrayRef< mlir::NamedAttrList > argAttrs={}, llvm::ArrayRef< mlir::NamedAttribute > resAttrs={})
cir::ConstantOp getConstantInt(mlir::Location loc, mlir::Type ty, int64_t value)
mlir::Value createComplexCreate(mlir::Location loc, mlir::Value real, mlir::Value imag)
mlir::Value createAddrSpaceCast(mlir::Value src, mlir::Type newTy)
mlir::Value createPtrToBoolCast(mlir::Value v)
cir::BoolAttr getTrueAttr()
cir::PointerType getVoidPtrTy(clang::LangAS langAS=clang::LangAS::Default)
mlir::Value createShiftRight(mlir::Location loc, mlir::Value lhs, unsigned bits)
mlir::Value createIsNaN(mlir::Location loc, mlir::Value operand)
cir::IntType getSIntNTy(int n)
mlir::Value createAlignedLoad(mlir::Location loc, mlir::Value ptr, uint64_t alignment)
mlir::TypedAttr getConstPtrAttr(mlir::Type type, int64_t value)
mlir::Value createAddrSpaceCast(mlir::Location loc, mlir::Value src, mlir::Type newTy)
cir::CallOp createCallOp(mlir::Location loc, mlir::SymbolRefAttr callee, mlir::Type returnType, mlir::ValueRange operands, llvm::ArrayRef< mlir::NamedAttribute > attrs={}, llvm::ArrayRef< mlir::NamedAttrList > argAttrs={}, llvm::ArrayRef< mlir::NamedAttribute > resAttrs={})
mlir::Value createDummyValue(mlir::Location loc, mlir::Type type, clang::CharUnits alignment)
cir::BoolAttr getFalseAttr()
mlir::Value createShiftRight(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::StoreOp createStore(mlir::Location loc, mlir::Value val, mlir::Value dst, bool isVolatile=false, mlir::IntegerAttr align={}, cir::SyncScopeKindAttr scope={}, cir::MemOrderAttr order={})
cir::CallOp createCallOp(mlir::Location loc, cir::FuncOp callee, mlir::ValueRange operands, llvm::ArrayRef< mlir::NamedAttribute > attrs={}, llvm::ArrayRef< mlir::NamedAttrList > argAttrs={}, llvm::ArrayRef< mlir::NamedAttribute > resAttrs={})
cir::YieldOp createYield(mlir::Location loc, mlir::ValueRange value={})
Create a yield operation.
mlir::Value createLogicalAnd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createUnaryOp(mlir::Location loc, cir::UnaryOpKind kind, mlir::Value operand)
mlir::IntegerAttr getAlignmentAttr(llvm::Align alignment)
cir::LoadOp createFlagLoad(mlir::Location loc, mlir::Value addr)
Emit a load from an boolean flag variable.
mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType, mlir::Type type, llvm::StringRef name, mlir::IntegerAttr alignment, mlir::Value dynAllocSize)
cir::BoolType getBoolTy()
mlir::Value getUnsignedInt(mlir::Location loc, uint64_t val, unsigned numBits)
GetMethodResults createGetMethod(mlir::Location loc, mlir::Value method, mlir::Value objectPtr)
mlir::Value createComplexReal(mlir::Location loc, mlir::Value operand)
CharUnits - This is an opaque type for sizes expressed in character units.
Definition CharUnits.h:38
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Definition CharUnits.h:185
constexpr OverflowBehavior operator|(OverflowBehavior a, OverflowBehavior b)
constexpr OverflowBehavior operator&(OverflowBehavior a, OverflowBehavior b)
constexpr OverflowBehavior & operator|=(OverflowBehavior &a, OverflowBehavior b)
constexpr OverflowBehavior & operator&=(OverflowBehavior &a, OverflowBehavior b)
mlir::ptr::MemorySpaceAttrInterface toCIRAddressSpaceAttr(mlir::MLIRContext &ctx, clang::LangAS langAS)
Convert an AST LangAS to the appropriate CIR address space attribute interface.
OverflowBehavior
LangAS
Defines the address space values used by the address space qualifier of QualType.
static bool addressSpace()
static bool targetCodeGenInfoGetNullPointer()