clang 22.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/Support/ErrorHandling.h"
20
21#include "mlir/IR/Builders.h"
22#include "mlir/IR/BuiltinAttributes.h"
23#include "mlir/IR/Location.h"
24#include "mlir/IR/Types.h"
25
26namespace cir {
27
28enum class OverflowBehavior {
29 None = 0,
30 NoSignedWrap = 1 << 0,
32 Saturated = 1 << 2,
33};
34
36 return static_cast<OverflowBehavior>(llvm::to_underlying(a) |
37 llvm::to_underlying(b));
38}
39
41 return static_cast<OverflowBehavior>(llvm::to_underlying(a) &
42 llvm::to_underlying(b));
43}
44
47 a = a | b;
48 return a;
49}
50
53 a = a & b;
54 return a;
55}
56
57class CIRBaseBuilderTy : public mlir::OpBuilder {
58
59public:
60 CIRBaseBuilderTy(mlir::MLIRContext &mlirContext)
61 : mlir::OpBuilder(&mlirContext) {}
62 CIRBaseBuilderTy(mlir::OpBuilder &builder) : mlir::OpBuilder(builder) {}
63
64 mlir::Value getConstAPInt(mlir::Location loc, mlir::Type typ,
65 const llvm::APInt &val) {
66 return cir::ConstantOp::create(*this, loc, cir::IntAttr::get(typ, val));
67 }
68
69 cir::ConstantOp getConstant(mlir::Location loc, mlir::TypedAttr attr) {
70 return cir::ConstantOp::create(*this, loc, attr);
71 }
72
73 cir::ConstantOp getConstantInt(mlir::Location loc, mlir::Type ty,
74 int64_t value) {
75 return getConstant(loc, cir::IntAttr::get(ty, value));
76 }
77
78 mlir::Value getSignedInt(mlir::Location loc, int64_t val, unsigned numBits) {
79 auto type = cir::IntType::get(getContext(), numBits, /*isSigned=*/true);
80 return getConstAPInt(loc, type,
81 llvm::APInt(numBits, val, /*isSigned=*/true));
82 }
83
84 mlir::Value getUnsignedInt(mlir::Location loc, uint64_t val,
85 unsigned numBits) {
86 auto type = cir::IntType::get(getContext(), numBits, /*isSigned=*/false);
87 return getConstAPInt(loc, type, llvm::APInt(numBits, val));
88 }
89
90 // Creates constant null value for integral type ty.
91 cir::ConstantOp getNullValue(mlir::Type ty, mlir::Location loc) {
92 return getConstant(loc, getZeroInitAttr(ty));
93 }
94
95 mlir::TypedAttr getConstNullPtrAttr(mlir::Type t) {
96 assert(mlir::isa<cir::PointerType>(t) && "expected cir.ptr");
97 return getConstPtrAttr(t, 0);
98 }
99
100 mlir::TypedAttr getZeroInitAttr(mlir::Type ty) {
101 if (mlir::isa<cir::IntType>(ty))
102 return cir::IntAttr::get(ty, 0);
103 if (cir::isAnyFloatingPointType(ty))
104 return cir::FPAttr::getZero(ty);
105 if (auto complexType = mlir::dyn_cast<cir::ComplexType>(ty))
106 return cir::ZeroAttr::get(complexType);
107 if (auto arrTy = mlir::dyn_cast<cir::ArrayType>(ty))
108 return cir::ZeroAttr::get(arrTy);
109 if (auto vecTy = mlir::dyn_cast<cir::VectorType>(ty))
110 return cir::ZeroAttr::get(vecTy);
111 if (auto ptrTy = mlir::dyn_cast<cir::PointerType>(ty))
112 return getConstNullPtrAttr(ptrTy);
113 if (auto recordTy = mlir::dyn_cast<cir::RecordType>(ty))
114 return cir::ZeroAttr::get(recordTy);
115 if (mlir::isa<cir::BoolType>(ty)) {
116 return getFalseAttr();
117 }
118 llvm_unreachable("Zero initializer for given type is NYI");
119 }
120
121 cir::ConstantOp getBool(bool state, mlir::Location loc) {
122 return cir::ConstantOp::create(*this, loc, getCIRBoolAttr(state));
123 }
124 cir::ConstantOp getFalse(mlir::Location loc) { return getBool(false, loc); }
125 cir::ConstantOp getTrue(mlir::Location loc) { return getBool(true, loc); }
126
127 cir::BoolType getBoolTy() { return cir::BoolType::get(getContext()); }
128 cir::VoidType getVoidTy() { return cir::VoidType::get(getContext()); }
129
130 cir::IntType getUIntNTy(int n) {
131 return cir::IntType::get(getContext(), n, false);
132 }
133
134 cir::IntType getSIntNTy(int n) {
135 return cir::IntType::get(getContext(), n, true);
136 }
137
138 cir::PointerType getPointerTo(mlir::Type ty) {
139 return cir::PointerType::get(ty);
140 }
141
142 cir::PointerType getPointerTo(mlir::Type ty, cir::TargetAddressSpaceAttr as) {
143 return cir::PointerType::get(ty, as);
144 }
145
146 cir::PointerType getPointerTo(mlir::Type ty, clang::LangAS langAS) {
147 if (langAS == clang::LangAS::Default) // Default address space.
148 return getPointerTo(ty);
149
150 if (clang::isTargetAddressSpace(langAS)) {
151 unsigned addrSpace = clang::toTargetAddressSpace(langAS);
152 auto asAttr = cir::TargetAddressSpaceAttr::get(
153 getContext(), getUI32IntegerAttr(addrSpace));
154 return getPointerTo(ty, asAttr);
155 }
156
157 llvm_unreachable("language-specific address spaces NYI");
158 }
159
161 return getPointerTo(cir::VoidType::get(getContext()), langAS);
162 }
163
164 cir::PointerType getVoidPtrTy(cir::TargetAddressSpaceAttr as) {
165 return getPointerTo(cir::VoidType::get(getContext()), as);
166 }
167
168 cir::BoolAttr getCIRBoolAttr(bool state) {
169 return cir::BoolAttr::get(getContext(), state);
170 }
171
172 cir::BoolAttr getTrueAttr() { return getCIRBoolAttr(true); }
173 cir::BoolAttr getFalseAttr() { return getCIRBoolAttr(false); }
174
175 mlir::Value createComplexCreate(mlir::Location loc, mlir::Value real,
176 mlir::Value imag) {
177 auto resultComplexTy = cir::ComplexType::get(real.getType());
178 return cir::ComplexCreateOp::create(*this, loc, resultComplexTy, real,
179 imag);
180 }
181
182 mlir::Value createComplexReal(mlir::Location loc, mlir::Value operand) {
183 auto resultType = operand.getType();
184 if (auto complexResultType = mlir::dyn_cast<cir::ComplexType>(resultType))
185 resultType = complexResultType.getElementType();
186 return cir::ComplexRealOp::create(*this, loc, resultType, operand);
187 }
188
189 mlir::Value createComplexImag(mlir::Location loc, mlir::Value operand) {
190 auto resultType = operand.getType();
191 if (auto complexResultType = mlir::dyn_cast<cir::ComplexType>(resultType))
192 resultType = complexResultType.getElementType();
193 return cir::ComplexImagOp::create(*this, loc, resultType, operand);
194 }
195
196 cir::LoadOp createLoad(mlir::Location loc, mlir::Value ptr,
197 bool isVolatile = false, uint64_t alignment = 0) {
198 mlir::IntegerAttr alignmentAttr = getAlignmentAttr(alignment);
199 return cir::LoadOp::create(*this, loc, ptr, /*isDeref=*/false, isVolatile,
200 alignmentAttr, cir::MemOrderAttr{});
201 }
202
203 mlir::Value createAlignedLoad(mlir::Location loc, mlir::Value ptr,
204 uint64_t alignment) {
205 return createLoad(loc, ptr, /*isVolatile=*/false, alignment);
206 }
207
208 mlir::Value createNot(mlir::Value value) {
209 return cir::UnaryOp::create(*this, value.getLoc(), value.getType(),
210 cir::UnaryOpKind::Not, value);
211 }
212
213 /// Create a do-while operation.
214 cir::DoWhileOp createDoWhile(
215 mlir::Location loc,
216 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> condBuilder,
217 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> bodyBuilder) {
218 return cir::DoWhileOp::create(*this, loc, condBuilder, bodyBuilder);
219 }
220
221 /// Create a while operation.
222 cir::WhileOp createWhile(
223 mlir::Location loc,
224 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> condBuilder,
225 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> bodyBuilder) {
226 return cir::WhileOp::create(*this, loc, condBuilder, bodyBuilder);
227 }
228
229 /// Create a for operation.
230 cir::ForOp createFor(
231 mlir::Location loc,
232 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> condBuilder,
233 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> bodyBuilder,
234 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> stepBuilder) {
235 return cir::ForOp::create(*this, loc, condBuilder, bodyBuilder,
236 stepBuilder);
237 }
238
239 /// Create a break operation.
240 cir::BreakOp createBreak(mlir::Location loc) {
241 return cir::BreakOp::create(*this, loc);
242 }
243
244 /// Create a continue operation.
245 cir::ContinueOp createContinue(mlir::Location loc) {
246 return cir::ContinueOp::create(*this, loc);
247 }
248
249 mlir::Value createUnaryOp(mlir::Location loc, cir::UnaryOpKind kind,
250 mlir::Value operand) {
251 return cir::UnaryOp::create(*this, loc, kind, operand);
252 }
253
254 mlir::TypedAttr getConstPtrAttr(mlir::Type type, int64_t value) {
255 return cir::ConstPtrAttr::get(type, getI64IntegerAttr(value));
256 }
257
258 mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType,
259 mlir::Type type, llvm::StringRef name,
260 mlir::IntegerAttr alignment,
261 mlir::Value dynAllocSize) {
262 return cir::AllocaOp::create(*this, loc, addrType, type, name, alignment,
263 dynAllocSize);
264 }
265
266 mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType,
267 mlir::Type type, llvm::StringRef name,
268 clang::CharUnits alignment,
269 mlir::Value dynAllocSize) {
270 mlir::IntegerAttr alignmentAttr = getAlignmentAttr(alignment);
271 return createAlloca(loc, addrType, type, name, alignmentAttr, dynAllocSize);
272 }
273
274 mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType,
275 mlir::Type type, llvm::StringRef name,
276 mlir::IntegerAttr alignment) {
277 return cir::AllocaOp::create(*this, loc, addrType, type, name, alignment);
278 }
279
280 mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType,
281 mlir::Type type, llvm::StringRef name,
282 clang::CharUnits alignment) {
283 mlir::IntegerAttr alignmentAttr = getAlignmentAttr(alignment);
284 return createAlloca(loc, addrType, type, name, alignmentAttr);
285 }
286
287 /// Get constant address of a global variable as an MLIR attribute.
288 /// This wrapper infers the attribute type through the global op.
289 cir::GlobalViewAttr getGlobalViewAttr(cir::GlobalOp globalOp,
290 mlir::ArrayAttr indices = {}) {
291 cir::PointerType type = getPointerTo(globalOp.getSymType());
292 return getGlobalViewAttr(type, globalOp, indices);
293 }
294
295 /// Get constant address of a global variable as an MLIR attribute.
296 cir::GlobalViewAttr getGlobalViewAttr(cir::PointerType type,
297 cir::GlobalOp globalOp,
298 mlir::ArrayAttr indices = {}) {
299 auto symbol = mlir::FlatSymbolRefAttr::get(globalOp.getSymNameAttr());
300 return cir::GlobalViewAttr::get(type, symbol, indices);
301 }
302
303 mlir::Value createGetGlobal(mlir::Location loc, cir::GlobalOp global) {
305 return cir::GetGlobalOp::create(
306 *this, loc, getPointerTo(global.getSymType()), global.getSymName());
307 }
308
309 mlir::Value createGetGlobal(cir::GlobalOp global) {
310 return createGetGlobal(global.getLoc(), global);
311 }
312
313 /// Create a copy with inferred length.
314 cir::CopyOp createCopy(mlir::Value dst, mlir::Value src,
315 bool isVolatile = false) {
316 return cir::CopyOp::create(*this, dst.getLoc(), dst, src, isVolatile);
317 }
318
319 cir::StoreOp createStore(mlir::Location loc, mlir::Value val, mlir::Value dst,
320 bool isVolatile = false,
321 mlir::IntegerAttr align = {},
322 cir::MemOrderAttr order = {}) {
323 return cir::StoreOp::create(*this, loc, val, dst, isVolatile, align, order);
324 }
325
326 [[nodiscard]] cir::GlobalOp createGlobal(mlir::ModuleOp mlirModule,
327 mlir::Location loc,
328 mlir::StringRef name,
329 mlir::Type type, bool isConstant,
330 cir::GlobalLinkageKind linkage) {
331 mlir::OpBuilder::InsertionGuard guard(*this);
332 setInsertionPointToStart(mlirModule.getBody());
333 return cir::GlobalOp::create(*this, loc, name, type, isConstant, linkage);
334 }
335
336 cir::GetMemberOp createGetMember(mlir::Location loc, mlir::Type resultTy,
337 mlir::Value base, llvm::StringRef name,
338 unsigned index) {
339 return cir::GetMemberOp::create(*this, loc, resultTy, base, name, index);
340 }
341
342 mlir::Value createDummyValue(mlir::Location loc, mlir::Type type,
343 clang::CharUnits alignment) {
344 mlir::IntegerAttr alignmentAttr = getAlignmentAttr(alignment);
345 auto addr = createAlloca(loc, getPointerTo(type), type, {}, alignmentAttr);
346 return cir::LoadOp::create(*this, loc, addr, /*isDeref=*/false,
347 /*isVolatile=*/false, alignmentAttr,
348 /*mem_order=*/{});
349 }
350
351 cir::PtrStrideOp createPtrStride(mlir::Location loc, mlir::Value base,
352 mlir::Value stride) {
353 return cir::PtrStrideOp::create(*this, loc, base.getType(), base, stride);
354 }
355
356 //===--------------------------------------------------------------------===//
357 // Call operators
358 //===--------------------------------------------------------------------===//
359
360 cir::CallOp createCallOp(mlir::Location loc, mlir::SymbolRefAttr callee,
361 mlir::Type returnType, mlir::ValueRange operands,
363 auto op = cir::CallOp::create(*this, loc, callee, returnType, operands);
364 op->setAttrs(attrs);
365 return op;
366 }
367
368 cir::CallOp createCallOp(mlir::Location loc, cir::FuncOp callee,
369 mlir::ValueRange operands,
371 return createCallOp(loc, mlir::SymbolRefAttr::get(callee),
372 callee.getFunctionType().getReturnType(), operands,
373 attrs);
374 }
375
376 cir::CallOp
377 createIndirectCallOp(mlir::Location loc, mlir::Value indirectTarget,
378 cir::FuncType funcType, mlir::ValueRange operands,
380 llvm::SmallVector<mlir::Value> resOperands{indirectTarget};
381 resOperands.append(operands.begin(), operands.end());
382 return createCallOp(loc, mlir::SymbolRefAttr(), funcType.getReturnType(),
383 resOperands, attrs);
384 }
385
386 cir::CallOp createCallOp(mlir::Location loc, mlir::SymbolRefAttr callee,
387 mlir::ValueRange operands = mlir::ValueRange(),
389 return createCallOp(loc, callee, cir::VoidType(), operands, attrs);
390 }
391
392 cir::CallOp createTryCallOp(
393 mlir::Location loc, mlir::SymbolRefAttr callee = mlir::SymbolRefAttr(),
394 mlir::Type returnType = cir::VoidType(),
395 mlir::ValueRange operands = mlir::ValueRange(),
396 [[maybe_unused]] cir::SideEffect sideEffect = cir::SideEffect::All) {
399 return createCallOp(loc, callee, returnType, operands);
400 }
401
402 cir::CallOp createTryCallOp(
403 mlir::Location loc, cir::FuncOp callee, mlir::ValueRange operands,
404 [[maybe_unused]] cir::SideEffect sideEffect = cir::SideEffect::All) {
407 return createTryCallOp(loc, mlir::SymbolRefAttr::get(callee),
408 callee.getFunctionType().getReturnType(), operands);
409 }
410
411 //===--------------------------------------------------------------------===//
412 // Cast/Conversion Operators
413 //===--------------------------------------------------------------------===//
414
415 mlir::Value createCast(mlir::Location loc, cir::CastKind kind,
416 mlir::Value src, mlir::Type newTy) {
417 if (newTy == src.getType())
418 return src;
419 return cir::CastOp::create(*this, loc, newTy, kind, src);
420 }
421
422 mlir::Value createCast(cir::CastKind kind, mlir::Value src,
423 mlir::Type newTy) {
424 if (newTy == src.getType())
425 return src;
426 return createCast(src.getLoc(), kind, src, newTy);
427 }
428
429 mlir::Value createIntCast(mlir::Value src, mlir::Type newTy) {
430 return createCast(cir::CastKind::integral, src, newTy);
431 }
432
433 mlir::Value createIntToPtr(mlir::Value src, mlir::Type newTy) {
434 return createCast(cir::CastKind::int_to_ptr, src, newTy);
435 }
436
437 mlir::Value createPtrToInt(mlir::Value src, mlir::Type newTy) {
438 return createCast(cir::CastKind::ptr_to_int, src, newTy);
439 }
440
441 mlir::Value createPtrToBoolCast(mlir::Value v) {
442 return createCast(cir::CastKind::ptr_to_bool, v, getBoolTy());
443 }
444
445 mlir::Value createBoolToInt(mlir::Value src, mlir::Type newTy) {
446 return createCast(cir::CastKind::bool_to_int, src, newTy);
447 }
448
449 mlir::Value createBitcast(mlir::Value src, mlir::Type newTy) {
450 return createCast(cir::CastKind::bitcast, src, newTy);
451 }
452
453 mlir::Value createBitcast(mlir::Location loc, mlir::Value src,
454 mlir::Type newTy) {
455 return createCast(loc, cir::CastKind::bitcast, src, newTy);
456 }
457
458 mlir::Value createPtrBitcast(mlir::Value src, mlir::Type newPointeeTy) {
459 assert(mlir::isa<cir::PointerType>(src.getType()) && "expected ptr src");
460 return createBitcast(src, getPointerTo(newPointeeTy));
461 }
462
463 mlir::Value createPtrIsNull(mlir::Value ptr) {
464 mlir::Value nullPtr = getNullPtr(ptr.getType(), ptr.getLoc());
465 return createCompare(ptr.getLoc(), cir::CmpOpKind::eq, ptr, nullPtr);
466 }
467
468 //===--------------------------------------------------------------------===//
469 // Binary Operators
470 //===--------------------------------------------------------------------===//
471
472 mlir::Value createBinop(mlir::Location loc, mlir::Value lhs,
473 cir::BinOpKind kind, mlir::Value rhs) {
474 return cir::BinOp::create(*this, loc, lhs.getType(), kind, lhs, rhs);
475 }
476
477 mlir::Value createLowBitsSet(mlir::Location loc, unsigned size,
478 unsigned bits) {
479 llvm::APInt val = llvm::APInt::getLowBitsSet(size, bits);
480 auto type = cir::IntType::get(getContext(), size, /*isSigned=*/false);
481 return getConstAPInt(loc, type, val);
482 }
483
484 mlir::Value createAnd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
485 return createBinop(loc, lhs, cir::BinOpKind::And, rhs);
486 }
487
488 mlir::Value createOr(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
489 return createBinop(loc, lhs, cir::BinOpKind::Or, rhs);
490 }
491
492 mlir::Value createSelect(mlir::Location loc, mlir::Value condition,
493 mlir::Value trueValue, mlir::Value falseValue) {
494 assert(trueValue.getType() == falseValue.getType() &&
495 "trueValue and falseValue should have the same type");
496 return cir::SelectOp::create(*this, loc, trueValue.getType(), condition,
497 trueValue, falseValue);
498 }
499
500 mlir::Value createLogicalAnd(mlir::Location loc, mlir::Value lhs,
501 mlir::Value rhs) {
502 return createSelect(loc, lhs, rhs, getBool(false, loc));
503 }
504
505 mlir::Value createLogicalOr(mlir::Location loc, mlir::Value lhs,
506 mlir::Value rhs) {
507 return createSelect(loc, lhs, getBool(true, loc), rhs);
508 }
509
510 mlir::Value createMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs,
512 auto op = cir::BinOp::create(*this, loc, lhs.getType(), cir::BinOpKind::Mul,
513 lhs, rhs);
514 op.setNoUnsignedWrap(
515 llvm::to_underlying(ob & OverflowBehavior::NoUnsignedWrap));
516 op.setNoSignedWrap(
517 llvm::to_underlying(ob & OverflowBehavior::NoSignedWrap));
518 return op;
519 }
520 mlir::Value createNSWMul(mlir::Location loc, mlir::Value lhs,
521 mlir::Value rhs) {
522 return createMul(loc, lhs, rhs, OverflowBehavior::NoSignedWrap);
523 }
524 mlir::Value createNUWAMul(mlir::Location loc, mlir::Value lhs,
525 mlir::Value rhs) {
526 return createMul(loc, lhs, rhs, OverflowBehavior::NoUnsignedWrap);
527 }
528
529 mlir::Value createSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs,
531 auto op = cir::BinOp::create(*this, loc, lhs.getType(), cir::BinOpKind::Sub,
532 lhs, rhs);
533 op.setNoUnsignedWrap(
534 llvm::to_underlying(ob & OverflowBehavior::NoUnsignedWrap));
535 op.setNoSignedWrap(
536 llvm::to_underlying(ob & OverflowBehavior::NoSignedWrap));
537 op.setSaturated(llvm::to_underlying(ob & OverflowBehavior::Saturated));
538 return op;
539 }
540
541 mlir::Value createNSWSub(mlir::Location loc, mlir::Value lhs,
542 mlir::Value rhs) {
543 return createSub(loc, lhs, rhs, OverflowBehavior::NoSignedWrap);
544 }
545
546 mlir::Value createNUWSub(mlir::Location loc, mlir::Value lhs,
547 mlir::Value rhs) {
548 return createSub(loc, lhs, rhs, OverflowBehavior::NoUnsignedWrap);
549 }
550
551 mlir::Value createAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs,
553 auto op = cir::BinOp::create(*this, loc, lhs.getType(), cir::BinOpKind::Add,
554 lhs, rhs);
555 op.setNoUnsignedWrap(
556 llvm::to_underlying(ob & OverflowBehavior::NoUnsignedWrap));
557 op.setNoSignedWrap(
558 llvm::to_underlying(ob & OverflowBehavior::NoSignedWrap));
559 op.setSaturated(llvm::to_underlying(ob & OverflowBehavior::Saturated));
560 return op;
561 }
562
563 mlir::Value createNSWAdd(mlir::Location loc, mlir::Value lhs,
564 mlir::Value rhs) {
565 return createAdd(loc, lhs, rhs, OverflowBehavior::NoSignedWrap);
566 }
567
568 mlir::Value createNUWAdd(mlir::Location loc, mlir::Value lhs,
569 mlir::Value rhs) {
570 return createAdd(loc, lhs, rhs, OverflowBehavior::NoUnsignedWrap);
571 }
572
573 cir::CmpOp createCompare(mlir::Location loc, cir::CmpOpKind kind,
574 mlir::Value lhs, mlir::Value rhs) {
575 return cir::CmpOp::create(*this, loc, getBoolTy(), kind, lhs, rhs);
576 }
577
578 mlir::Value createIsNaN(mlir::Location loc, mlir::Value operand) {
579 return createCompare(loc, cir::CmpOpKind::ne, operand, operand);
580 }
581
582 mlir::Value createShift(mlir::Location loc, mlir::Value lhs, mlir::Value rhs,
583 bool isShiftLeft) {
584 return cir::ShiftOp::create(*this, loc, lhs.getType(), lhs, rhs,
585 isShiftLeft);
586 }
587
588 mlir::Value createShift(mlir::Location loc, mlir::Value lhs,
589 const llvm::APInt &rhs, bool isShiftLeft) {
590 return createShift(loc, lhs, getConstAPInt(loc, lhs.getType(), rhs),
591 isShiftLeft);
592 }
593
594 mlir::Value createShift(mlir::Location loc, mlir::Value lhs, unsigned bits,
595 bool isShiftLeft) {
596 auto width = mlir::dyn_cast<cir::IntType>(lhs.getType()).getWidth();
597 auto shift = llvm::APInt(width, bits);
598 return createShift(loc, lhs, shift, isShiftLeft);
599 }
600
601 mlir::Value createShiftLeft(mlir::Location loc, mlir::Value lhs,
602 unsigned bits) {
603 return createShift(loc, lhs, bits, true);
604 }
605
606 mlir::Value createShiftRight(mlir::Location loc, mlir::Value lhs,
607 unsigned bits) {
608 return createShift(loc, lhs, bits, false);
609 }
610
611 mlir::Value createShiftLeft(mlir::Location loc, mlir::Value lhs,
612 mlir::Value rhs) {
613 return createShift(loc, lhs, rhs, true);
614 }
615
616 mlir::Value createShiftRight(mlir::Location loc, mlir::Value lhs,
617 mlir::Value rhs) {
618 return createShift(loc, lhs, rhs, false);
619 }
620
621 //
622 // Block handling helpers
623 // ----------------------
624 //
625 static OpBuilder::InsertPoint getBestAllocaInsertPoint(mlir::Block *block) {
626 auto last =
627 std::find_if(block->rbegin(), block->rend(), [](mlir::Operation &op) {
628 return mlir::isa<cir::AllocaOp, cir::LabelOp>(&op);
629 });
630
631 if (last != block->rend())
632 return OpBuilder::InsertPoint(block, ++mlir::Block::iterator(&*last));
633 return OpBuilder::InsertPoint(block, block->begin());
634 };
635
636 //
637 // Alignment and size helpers
638 //
639
640 // Note that mlir::IntegerType is used instead of cir::IntType here because we
641 // don't need sign information for these to be useful, so keep it simple.
642
643 // For 0 alignment, any overload of `getAlignmentAttr` returns an empty
644 // attribute.
645 mlir::IntegerAttr getAlignmentAttr(clang::CharUnits alignment) {
646 return getAlignmentAttr(alignment.getQuantity());
647 }
648
649 mlir::IntegerAttr getAlignmentAttr(llvm::Align alignment) {
650 return getAlignmentAttr(alignment.value());
651 }
652
653 mlir::IntegerAttr getAlignmentAttr(int64_t alignment) {
654 return alignment ? getI64IntegerAttr(alignment) : mlir::IntegerAttr();
655 }
656
657 mlir::IntegerAttr getSizeFromCharUnits(clang::CharUnits size) {
658 return getI64IntegerAttr(size.getQuantity());
659 }
660
661 // Creates constant nullptr for pointer type ty.
662 cir::ConstantOp getNullPtr(mlir::Type ty, mlir::Location loc) {
664 return cir::ConstantOp::create(*this, loc, getConstPtrAttr(ty, 0));
665 }
666
667 /// Create a loop condition.
668 cir::ConditionOp createCondition(mlir::Value condition) {
669 return cir::ConditionOp::create(*this, condition.getLoc(), condition);
670 }
671
672 /// Create a yield operation.
673 cir::YieldOp createYield(mlir::Location loc, mlir::ValueRange value = {}) {
674 return cir::YieldOp::create(*this, loc, value);
675 }
676};
677
678} // namespace cir
679
680#endif
Provides definitions for the various language-specific address spaces.
__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::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)
mlir::Value createGetGlobal(mlir::Location loc, cir::GlobalOp global)
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)
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)
cir::GlobalViewAttr getGlobalViewAttr(cir::GlobalOp globalOp, mlir::ArrayAttr indices={})
Get constant address of a global variable as an MLIR attribute.
cir::VoidType getVoidTy()
cir::CallOp createCallOp(mlir::Location loc, mlir::SymbolRefAttr callee, mlir::ValueRange operands=mlir::ValueRange(), llvm::ArrayRef< mlir::NamedAttribute > attrs={})
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)
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::CallOp createCallOp(mlir::Location loc, cir::FuncOp callee, mlir::ValueRange operands, llvm::ArrayRef< mlir::NamedAttribute > attrs={})
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)
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)
mlir::Value createGetGlobal(cir::GlobalOp global)
cir::IntType getUIntNTy(int n)
cir::PointerType getVoidPtrTy(cir::TargetAddressSpaceAttr as)
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.
cir::CallOp createCallOp(mlir::Location loc, mlir::SymbolRefAttr callee, mlir::Type returnType, mlir::ValueRange operands, llvm::ArrayRef< mlir::NamedAttribute > attrs={})
mlir::Value createPtrBitcast(mlir::Value src, mlir::Type newPointeeTy)
cir::CallOp createTryCallOp(mlir::Location loc, mlir::SymbolRefAttr callee=mlir::SymbolRefAttr(), mlir::Type returnType=cir::VoidType(), mlir::ValueRange operands=mlir::ValueRange(), cir::SideEffect sideEffect=cir::SideEffect::All)
mlir::Value createShiftLeft(mlir::Location loc, mlir::Value lhs, unsigned bits)
mlir::Value createSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, OverflowBehavior ob=OverflowBehavior::Saturated)
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 createIntCast(mlir::Value src, mlir::Type newTy)
cir::CallOp createTryCallOp(mlir::Location loc, cir::FuncOp callee, mlir::ValueRange operands, cir::SideEffect sideEffect=cir::SideEffect::All)
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)
cir::GlobalOp createGlobal(mlir::ModuleOp mlirModule, mlir::Location loc, mlir::StringRef name, mlir::Type type, bool isConstant, cir::GlobalLinkageKind linkage)
cir::StoreOp createStore(mlir::Location loc, mlir::Value val, mlir::Value dst, bool isVolatile=false, mlir::IntegerAttr align={}, cir::MemOrderAttr order={})
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)
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)
cir::CallOp createIndirectCallOp(mlir::Location loc, mlir::Value indirectTarget, cir::FuncType funcType, mlir::ValueRange operands, llvm::ArrayRef< mlir::NamedAttribute > attrs={})
CIRBaseBuilderTy(mlir::OpBuilder &builder)
cir::ConstantOp getConstantInt(mlir::Location loc, mlir::Type ty, int64_t value)
mlir::Value createComplexCreate(mlir::Location loc, mlir::Value real, mlir::Value imag)
cir::PointerType getPointerTo(mlir::Type ty, cir::TargetAddressSpaceAttr as)
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 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::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)
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)
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)
OverflowBehavior
bool isTargetAddressSpace(LangAS AS)
unsigned toTargetAddressSpace(LangAS AS)
LangAS
Defines the address space values used by the address space qualifier of QualType.
static bool addressSpace()
static bool targetCodeGenInfoGetNullPointer()
static bool opCallSideEffect()
static bool opCallCallConv()