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::PointerType getPointerTo(mlir::Type ty) {
131 return cir::PointerType::get(ty);
132 }
133
134 cir::PointerType getPointerTo(mlir::Type ty, cir::TargetAddressSpaceAttr as) {
135 return cir::PointerType::get(ty, as);
136 }
137
138 cir::PointerType getPointerTo(mlir::Type ty, clang::LangAS langAS) {
139 if (langAS == clang::LangAS::Default) // Default address space.
140 return getPointerTo(ty);
141
142 if (clang::isTargetAddressSpace(langAS)) {
143 unsigned addrSpace = clang::toTargetAddressSpace(langAS);
144 auto asAttr = cir::TargetAddressSpaceAttr::get(
145 getContext(), getUI32IntegerAttr(addrSpace));
146 return getPointerTo(ty, asAttr);
147 }
148
149 llvm_unreachable("language-specific address spaces NYI");
150 }
151
153 return getPointerTo(cir::VoidType::get(getContext()), langAS);
154 }
155
156 cir::PointerType getVoidPtrTy(cir::TargetAddressSpaceAttr as) {
157 return getPointerTo(cir::VoidType::get(getContext()), as);
158 }
159
160 cir::BoolAttr getCIRBoolAttr(bool state) {
161 return cir::BoolAttr::get(getContext(), state);
162 }
163
164 cir::BoolAttr getTrueAttr() { return getCIRBoolAttr(true); }
165 cir::BoolAttr getFalseAttr() { return getCIRBoolAttr(false); }
166
167 mlir::Value createComplexCreate(mlir::Location loc, mlir::Value real,
168 mlir::Value imag) {
169 auto resultComplexTy = cir::ComplexType::get(real.getType());
170 return cir::ComplexCreateOp::create(*this, loc, resultComplexTy, real,
171 imag);
172 }
173
174 mlir::Value createComplexReal(mlir::Location loc, mlir::Value operand) {
175 auto resultType = operand.getType();
176 if (auto complexResultType = mlir::dyn_cast<cir::ComplexType>(resultType))
177 resultType = complexResultType.getElementType();
178 return cir::ComplexRealOp::create(*this, loc, resultType, operand);
179 }
180
181 mlir::Value createComplexImag(mlir::Location loc, mlir::Value operand) {
182 auto resultType = operand.getType();
183 if (auto complexResultType = mlir::dyn_cast<cir::ComplexType>(resultType))
184 resultType = complexResultType.getElementType();
185 return cir::ComplexImagOp::create(*this, loc, resultType, operand);
186 }
187
188 cir::LoadOp createLoad(mlir::Location loc, mlir::Value ptr,
189 bool isVolatile = false, uint64_t alignment = 0) {
190 mlir::IntegerAttr alignmentAttr = getAlignmentAttr(alignment);
191 return cir::LoadOp::create(*this, loc, ptr, /*isDeref=*/false, isVolatile,
192 alignmentAttr, cir::MemOrderAttr{});
193 }
194
195 mlir::Value createAlignedLoad(mlir::Location loc, mlir::Value ptr,
196 uint64_t alignment) {
197 return createLoad(loc, ptr, /*isVolatile=*/false, alignment);
198 }
199
200 mlir::Value createNot(mlir::Value value) {
201 return cir::UnaryOp::create(*this, value.getLoc(), value.getType(),
202 cir::UnaryOpKind::Not, value);
203 }
204
205 /// Create a do-while operation.
206 cir::DoWhileOp createDoWhile(
207 mlir::Location loc,
208 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> condBuilder,
209 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> bodyBuilder) {
210 return cir::DoWhileOp::create(*this, loc, condBuilder, bodyBuilder);
211 }
212
213 /// Create a while operation.
214 cir::WhileOp createWhile(
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::WhileOp::create(*this, loc, condBuilder, bodyBuilder);
219 }
220
221 /// Create a for operation.
222 cir::ForOp createFor(
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 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> stepBuilder) {
227 return cir::ForOp::create(*this, loc, condBuilder, bodyBuilder,
228 stepBuilder);
229 }
230
231 /// Create a break operation.
232 cir::BreakOp createBreak(mlir::Location loc) {
233 return cir::BreakOp::create(*this, loc);
234 }
235
236 /// Create a continue operation.
237 cir::ContinueOp createContinue(mlir::Location loc) {
238 return cir::ContinueOp::create(*this, loc);
239 }
240
241 mlir::Value createUnaryOp(mlir::Location loc, cir::UnaryOpKind kind,
242 mlir::Value operand) {
243 return cir::UnaryOp::create(*this, loc, kind, operand);
244 }
245
246 mlir::TypedAttr getConstPtrAttr(mlir::Type type, int64_t value) {
247 return cir::ConstPtrAttr::get(type, getI64IntegerAttr(value));
248 }
249
250 mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType,
251 mlir::Type type, llvm::StringRef name,
252 mlir::IntegerAttr alignment,
253 mlir::Value dynAllocSize) {
254 return cir::AllocaOp::create(*this, loc, addrType, type, name, alignment,
255 dynAllocSize);
256 }
257
258 mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType,
259 mlir::Type type, llvm::StringRef name,
260 clang::CharUnits alignment,
261 mlir::Value dynAllocSize) {
262 mlir::IntegerAttr alignmentAttr = getAlignmentAttr(alignment);
263 return createAlloca(loc, addrType, type, name, alignmentAttr, dynAllocSize);
264 }
265
266 mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType,
267 mlir::Type type, llvm::StringRef name,
268 mlir::IntegerAttr alignment) {
269 return cir::AllocaOp::create(*this, loc, addrType, type, name, alignment);
270 }
271
272 mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType,
273 mlir::Type type, llvm::StringRef name,
274 clang::CharUnits alignment) {
275 mlir::IntegerAttr alignmentAttr = getAlignmentAttr(alignment);
276 return createAlloca(loc, addrType, type, name, alignmentAttr);
277 }
278
279 /// Get constant address of a global variable as an MLIR attribute.
280 /// This wrapper infers the attribute type through the global op.
281 cir::GlobalViewAttr getGlobalViewAttr(cir::GlobalOp globalOp,
282 mlir::ArrayAttr indices = {}) {
283 cir::PointerType type = getPointerTo(globalOp.getSymType());
284 return getGlobalViewAttr(type, globalOp, indices);
285 }
286
287 /// Get constant address of a global variable as an MLIR attribute.
288 cir::GlobalViewAttr getGlobalViewAttr(cir::PointerType type,
289 cir::GlobalOp globalOp,
290 mlir::ArrayAttr indices = {}) {
291 auto symbol = mlir::FlatSymbolRefAttr::get(globalOp.getSymNameAttr());
292 return cir::GlobalViewAttr::get(type, symbol, indices);
293 }
294
295 mlir::Value createGetGlobal(mlir::Location loc, cir::GlobalOp global) {
297 return cir::GetGlobalOp::create(
298 *this, loc, getPointerTo(global.getSymType()), global.getSymName());
299 }
300
301 mlir::Value createGetGlobal(cir::GlobalOp global) {
302 return createGetGlobal(global.getLoc(), global);
303 }
304
305 /// Create a copy with inferred length.
306 cir::CopyOp createCopy(mlir::Value dst, mlir::Value src) {
307 return cir::CopyOp::create(*this, dst.getLoc(), dst, src);
308 }
309
310 cir::StoreOp createStore(mlir::Location loc, mlir::Value val, mlir::Value dst,
311 bool isVolatile = false,
312 mlir::IntegerAttr align = {},
313 cir::MemOrderAttr order = {}) {
314 return cir::StoreOp::create(*this, loc, val, dst, isVolatile, align, order);
315 }
316
317 [[nodiscard]] cir::GlobalOp createGlobal(mlir::ModuleOp mlirModule,
318 mlir::Location loc,
319 mlir::StringRef name,
320 mlir::Type type, bool isConstant,
321 cir::GlobalLinkageKind linkage) {
322 mlir::OpBuilder::InsertionGuard guard(*this);
323 setInsertionPointToStart(mlirModule.getBody());
324 return cir::GlobalOp::create(*this, loc, name, type, isConstant, linkage);
325 }
326
327 cir::GetMemberOp createGetMember(mlir::Location loc, mlir::Type resultTy,
328 mlir::Value base, llvm::StringRef name,
329 unsigned index) {
330 return cir::GetMemberOp::create(*this, loc, resultTy, base, name, index);
331 }
332
333 mlir::Value createDummyValue(mlir::Location loc, mlir::Type type,
334 clang::CharUnits alignment) {
335 mlir::IntegerAttr alignmentAttr = getAlignmentAttr(alignment);
336 auto addr = createAlloca(loc, getPointerTo(type), type, {}, alignmentAttr);
337 return cir::LoadOp::create(*this, loc, addr, /*isDeref=*/false,
338 /*isVolatile=*/false, alignmentAttr,
339 /*mem_order=*/{});
340 }
341
342 cir::PtrStrideOp createPtrStride(mlir::Location loc, mlir::Value base,
343 mlir::Value stride) {
344 return cir::PtrStrideOp::create(*this, loc, base.getType(), base, stride);
345 }
346
347 //===--------------------------------------------------------------------===//
348 // Call operators
349 //===--------------------------------------------------------------------===//
350
351 cir::CallOp createCallOp(mlir::Location loc, mlir::SymbolRefAttr callee,
352 mlir::Type returnType, mlir::ValueRange operands,
354 auto op = cir::CallOp::create(*this, loc, callee, returnType, operands);
355 op->setAttrs(attrs);
356 return op;
357 }
358
359 cir::CallOp createCallOp(mlir::Location loc, cir::FuncOp callee,
360 mlir::ValueRange operands,
362 return createCallOp(loc, mlir::SymbolRefAttr::get(callee),
363 callee.getFunctionType().getReturnType(), operands,
364 attrs);
365 }
366
367 cir::CallOp
368 createIndirectCallOp(mlir::Location loc, mlir::Value indirectTarget,
369 cir::FuncType funcType, mlir::ValueRange operands,
371 llvm::SmallVector<mlir::Value> resOperands{indirectTarget};
372 resOperands.append(operands.begin(), operands.end());
373 return createCallOp(loc, mlir::SymbolRefAttr(), funcType.getReturnType(),
374 resOperands, attrs);
375 }
376
377 cir::CallOp createCallOp(mlir::Location loc, mlir::SymbolRefAttr callee,
378 mlir::ValueRange operands = mlir::ValueRange(),
380 return createCallOp(loc, callee, cir::VoidType(), operands, attrs);
381 }
382
383 cir::CallOp createTryCallOp(
384 mlir::Location loc, mlir::SymbolRefAttr callee = mlir::SymbolRefAttr(),
385 mlir::Type returnType = cir::VoidType(),
386 mlir::ValueRange operands = mlir::ValueRange(),
387 [[maybe_unused]] cir::SideEffect sideEffect = cir::SideEffect::All) {
390 return createCallOp(loc, callee, returnType, operands);
391 }
392
393 cir::CallOp createTryCallOp(
394 mlir::Location loc, cir::FuncOp callee, mlir::ValueRange operands,
395 [[maybe_unused]] cir::SideEffect sideEffect = cir::SideEffect::All) {
398 return createTryCallOp(loc, mlir::SymbolRefAttr::get(callee),
399 callee.getFunctionType().getReturnType(), operands);
400 }
401
402 //===--------------------------------------------------------------------===//
403 // Cast/Conversion Operators
404 //===--------------------------------------------------------------------===//
405
406 mlir::Value createCast(mlir::Location loc, cir::CastKind kind,
407 mlir::Value src, mlir::Type newTy) {
408 if (newTy == src.getType())
409 return src;
410 return cir::CastOp::create(*this, loc, newTy, kind, src);
411 }
412
413 mlir::Value createCast(cir::CastKind kind, mlir::Value src,
414 mlir::Type newTy) {
415 if (newTy == src.getType())
416 return src;
417 return createCast(src.getLoc(), kind, src, newTy);
418 }
419
420 mlir::Value createIntCast(mlir::Value src, mlir::Type newTy) {
421 return createCast(cir::CastKind::integral, src, newTy);
422 }
423
424 mlir::Value createIntToPtr(mlir::Value src, mlir::Type newTy) {
425 return createCast(cir::CastKind::int_to_ptr, src, newTy);
426 }
427
428 mlir::Value createPtrToInt(mlir::Value src, mlir::Type newTy) {
429 return createCast(cir::CastKind::ptr_to_int, src, newTy);
430 }
431
432 mlir::Value createPtrToBoolCast(mlir::Value v) {
433 return createCast(cir::CastKind::ptr_to_bool, v, getBoolTy());
434 }
435
436 mlir::Value createBoolToInt(mlir::Value src, mlir::Type newTy) {
437 return createCast(cir::CastKind::bool_to_int, src, newTy);
438 }
439
440 mlir::Value createBitcast(mlir::Value src, mlir::Type newTy) {
441 return createCast(cir::CastKind::bitcast, src, newTy);
442 }
443
444 mlir::Value createBitcast(mlir::Location loc, mlir::Value src,
445 mlir::Type newTy) {
446 return createCast(loc, cir::CastKind::bitcast, src, newTy);
447 }
448
449 mlir::Value createPtrBitcast(mlir::Value src, mlir::Type newPointeeTy) {
450 assert(mlir::isa<cir::PointerType>(src.getType()) && "expected ptr src");
451 return createBitcast(src, getPointerTo(newPointeeTy));
452 }
453
454 //===--------------------------------------------------------------------===//
455 // Binary Operators
456 //===--------------------------------------------------------------------===//
457
458 mlir::Value createBinop(mlir::Location loc, mlir::Value lhs,
459 cir::BinOpKind kind, mlir::Value rhs) {
460 return cir::BinOp::create(*this, loc, lhs.getType(), kind, lhs, rhs);
461 }
462
463 mlir::Value createLowBitsSet(mlir::Location loc, unsigned size,
464 unsigned bits) {
465 llvm::APInt val = llvm::APInt::getLowBitsSet(size, bits);
466 auto type = cir::IntType::get(getContext(), size, /*isSigned=*/false);
467 return getConstAPInt(loc, type, val);
468 }
469
470 mlir::Value createAnd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
471 return createBinop(loc, lhs, cir::BinOpKind::And, rhs);
472 }
473
474 mlir::Value createOr(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
475 return createBinop(loc, lhs, cir::BinOpKind::Or, rhs);
476 }
477
478 mlir::Value createSelect(mlir::Location loc, mlir::Value condition,
479 mlir::Value trueValue, mlir::Value falseValue) {
480 assert(trueValue.getType() == falseValue.getType() &&
481 "trueValue and falseValue should have the same type");
482 return cir::SelectOp::create(*this, loc, trueValue.getType(), condition,
483 trueValue, falseValue);
484 }
485
486 mlir::Value createLogicalAnd(mlir::Location loc, mlir::Value lhs,
487 mlir::Value rhs) {
488 return createSelect(loc, lhs, rhs, getBool(false, loc));
489 }
490
491 mlir::Value createLogicalOr(mlir::Location loc, mlir::Value lhs,
492 mlir::Value rhs) {
493 return createSelect(loc, lhs, getBool(true, loc), rhs);
494 }
495
496 mlir::Value createMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs,
498 auto op = cir::BinOp::create(*this, loc, lhs.getType(), cir::BinOpKind::Mul,
499 lhs, rhs);
500 op.setNoUnsignedWrap(
501 llvm::to_underlying(ob & OverflowBehavior::NoUnsignedWrap));
502 op.setNoSignedWrap(
503 llvm::to_underlying(ob & OverflowBehavior::NoSignedWrap));
504 return op;
505 }
506 mlir::Value createNSWMul(mlir::Location loc, mlir::Value lhs,
507 mlir::Value rhs) {
508 return createMul(loc, lhs, rhs, OverflowBehavior::NoSignedWrap);
509 }
510 mlir::Value createNUWAMul(mlir::Location loc, mlir::Value lhs,
511 mlir::Value rhs) {
512 return createMul(loc, lhs, rhs, OverflowBehavior::NoUnsignedWrap);
513 }
514
515 mlir::Value createSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs,
517 auto op = cir::BinOp::create(*this, loc, lhs.getType(), cir::BinOpKind::Sub,
518 lhs, rhs);
519 op.setNoUnsignedWrap(
520 llvm::to_underlying(ob & OverflowBehavior::NoUnsignedWrap));
521 op.setNoSignedWrap(
522 llvm::to_underlying(ob & OverflowBehavior::NoSignedWrap));
523 op.setSaturated(llvm::to_underlying(ob & OverflowBehavior::Saturated));
524 return op;
525 }
526
527 mlir::Value createNSWSub(mlir::Location loc, mlir::Value lhs,
528 mlir::Value rhs) {
529 return createSub(loc, lhs, rhs, OverflowBehavior::NoSignedWrap);
530 }
531
532 mlir::Value createNUWSub(mlir::Location loc, mlir::Value lhs,
533 mlir::Value rhs) {
534 return createSub(loc, lhs, rhs, OverflowBehavior::NoUnsignedWrap);
535 }
536
537 mlir::Value createAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs,
539 auto op = cir::BinOp::create(*this, loc, lhs.getType(), cir::BinOpKind::Add,
540 lhs, rhs);
541 op.setNoUnsignedWrap(
542 llvm::to_underlying(ob & OverflowBehavior::NoUnsignedWrap));
543 op.setNoSignedWrap(
544 llvm::to_underlying(ob & OverflowBehavior::NoSignedWrap));
545 op.setSaturated(llvm::to_underlying(ob & OverflowBehavior::Saturated));
546 return op;
547 }
548
549 mlir::Value createNSWAdd(mlir::Location loc, mlir::Value lhs,
550 mlir::Value rhs) {
551 return createAdd(loc, lhs, rhs, OverflowBehavior::NoSignedWrap);
552 }
553
554 mlir::Value createNUWAdd(mlir::Location loc, mlir::Value lhs,
555 mlir::Value rhs) {
556 return createAdd(loc, lhs, rhs, OverflowBehavior::NoUnsignedWrap);
557 }
558
559 cir::CmpOp createCompare(mlir::Location loc, cir::CmpOpKind kind,
560 mlir::Value lhs, mlir::Value rhs) {
561 return cir::CmpOp::create(*this, loc, getBoolTy(), kind, lhs, rhs);
562 }
563
564 mlir::Value createIsNaN(mlir::Location loc, mlir::Value operand) {
565 return createCompare(loc, cir::CmpOpKind::ne, operand, operand);
566 }
567
568 mlir::Value createShift(mlir::Location loc, mlir::Value lhs, mlir::Value rhs,
569 bool isShiftLeft) {
570 return cir::ShiftOp::create(*this, loc, lhs.getType(), lhs, rhs,
571 isShiftLeft);
572 }
573
574 mlir::Value createShift(mlir::Location loc, mlir::Value lhs,
575 const llvm::APInt &rhs, bool isShiftLeft) {
576 return createShift(loc, lhs, getConstAPInt(loc, lhs.getType(), rhs),
577 isShiftLeft);
578 }
579
580 mlir::Value createShift(mlir::Location loc, mlir::Value lhs, unsigned bits,
581 bool isShiftLeft) {
582 auto width = mlir::dyn_cast<cir::IntType>(lhs.getType()).getWidth();
583 auto shift = llvm::APInt(width, bits);
584 return createShift(loc, lhs, shift, isShiftLeft);
585 }
586
587 mlir::Value createShiftLeft(mlir::Location loc, mlir::Value lhs,
588 unsigned bits) {
589 return createShift(loc, lhs, bits, true);
590 }
591
592 mlir::Value createShiftRight(mlir::Location loc, mlir::Value lhs,
593 unsigned bits) {
594 return createShift(loc, lhs, bits, false);
595 }
596
597 mlir::Value createShiftLeft(mlir::Location loc, mlir::Value lhs,
598 mlir::Value rhs) {
599 return createShift(loc, lhs, rhs, true);
600 }
601
602 mlir::Value createShiftRight(mlir::Location loc, mlir::Value lhs,
603 mlir::Value rhs) {
604 return createShift(loc, lhs, rhs, false);
605 }
606
607 //
608 // Block handling helpers
609 // ----------------------
610 //
611 static OpBuilder::InsertPoint getBestAllocaInsertPoint(mlir::Block *block) {
612 auto last =
613 std::find_if(block->rbegin(), block->rend(), [](mlir::Operation &op) {
614 return mlir::isa<cir::AllocaOp, cir::LabelOp>(&op);
615 });
616
617 if (last != block->rend())
618 return OpBuilder::InsertPoint(block, ++mlir::Block::iterator(&*last));
619 return OpBuilder::InsertPoint(block, block->begin());
620 };
621
622 //
623 // Alignment and size helpers
624 //
625
626 // Note that mlir::IntegerType is used instead of cir::IntType here because we
627 // don't need sign information for these to be useful, so keep it simple.
628
629 // For 0 alignment, any overload of `getAlignmentAttr` returns an empty
630 // attribute.
631 mlir::IntegerAttr getAlignmentAttr(clang::CharUnits alignment) {
632 return getAlignmentAttr(alignment.getQuantity());
633 }
634
635 mlir::IntegerAttr getAlignmentAttr(llvm::Align alignment) {
636 return getAlignmentAttr(alignment.value());
637 }
638
639 mlir::IntegerAttr getAlignmentAttr(int64_t alignment) {
640 return alignment ? getI64IntegerAttr(alignment) : mlir::IntegerAttr();
641 }
642
643 mlir::IntegerAttr getSizeFromCharUnits(clang::CharUnits size) {
644 return getI64IntegerAttr(size.getQuantity());
645 }
646
647 /// Create a loop condition.
648 cir::ConditionOp createCondition(mlir::Value condition) {
649 return cir::ConditionOp::create(*this, condition.getLoc(), condition);
650 }
651
652 /// Create a yield operation.
653 cir::YieldOp createYield(mlir::Location loc, mlir::ValueRange value = {}) {
654 return cir::YieldOp::create(*this, loc, value);
655 }
656};
657
658} // namespace cir
659
660#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 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)
mlir::Value createGetGlobal(cir::GlobalOp global)
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::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)
cir::CopyOp createCopy(mlir::Value dst, mlir::Value src)
Create a copy with inferred length.
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)
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 opCallSideEffect()
static bool opCallCallConv()