27 CharUnits atomicAlign;
30 bool useLibCall =
true;
35 AtomicInfo(CIRGenFunction &cgf, LValue &lvalue, mlir::Location loc)
36 : cgf(cgf), loc(loc) {
37 assert(!lvalue.isGlobalReg());
38 ASTContext &ctx = cgf.getContext();
39 if (lvalue.isSimple()) {
40 atomicTy = lvalue.getType();
41 if (
auto *ty = atomicTy->getAs<AtomicType>())
42 valueTy = ty->getValueType();
45 evaluationKind = cgf.getEvaluationKind(valueTy);
48 TypeInfo atomicTypeInfo = ctx.
getTypeInfo(atomicTy);
51 valueSizeInBits = valueTypeInfo.
Width;
52 atomicSizeInBits = atomicTypeInfo.
Width;
53 assert(valueSizeInBits <= atomicSizeInBits);
54 assert(valueAlignInBits <= atomicAlignInBits);
58 if (lvalue.getAlignment().isZero())
59 lvalue.setAlignment(atomicAlign);
61 this->lvalue = lvalue;
64 cgf.cgm.errorNYI(loc,
"AtomicInfo: non-simple lvalue");
67 atomicSizeInBits, ctx.
toBits(lvalue.getAlignment()));
70 QualType getValueType()
const {
return valueTy; }
71 QualType getAtomicType()
const {
return atomicTy; }
72 CharUnits getAtomicAlignment()
const {
return atomicAlign; }
74 mlir::Value getAtomicPointer()
const {
75 if (lvalue.isSimple())
76 return lvalue.getPointer();
80 bool shouldUseLibCall()
const {
return useLibCall; }
81 const LValue &getAtomicLValue()
const {
return lvalue; }
82 Address getAtomicAddress()
const {
84 if (lvalue.isSimple()) {
85 elemTy = lvalue.getAddress().getElementType();
88 cgf.cgm.errorNYI(loc,
"AtomicInfo::getAtomicAddress: non-simple lvalue");
90 return Address(getAtomicPointer(), elemTy, getAtomicAlignment());
99 bool hasPadding()
const {
return (valueSizeInBits != atomicSizeInBits); }
101 bool emitMemSetZeroIfNecessary()
const;
103 mlir::Value getScalarRValValueOrNull(RValue rvalue)
const;
107 Address castToAtomicIntPointer(Address addr)
const;
112 Address convertToAtomicIntPointer(Address addr, mlir::Location loc)
const;
115 RValue convertAtomicTempToRValue(Address addr, AggValueSlot resultSlot,
116 SourceLocation loc,
bool asValue)
const;
119 mlir::Value convertRValueToInt(RValue rvalue, mlir::Location loc,
120 bool cmpxchg =
false)
const;
122 RValue convertToValueOrAtomic(mlir::Value intVal, AggValueSlot resultSlot,
123 SourceLocation loc,
bool asValue,
124 bool cmpxchg =
false)
const;
127 void emitCopyIntoMemory(RValue rvalue)
const;
130 LValue projectValue()
const {
131 assert(lvalue.isSimple());
132 Address addr = getAtomicAddress();
134 addr = cgf.getBuilder().createGetMember(loc, addr,
"value",
138 return LValue::makeAddr(addr, getValueType(), lvalue.getBaseInfo());
143 RValue emitAtomicLoad(AggValueSlot resultSlot, SourceLocation loc,
144 bool asValue, cir::MemOrder order,
bool isVolatile);
147 Address materializeRValue(RValue rvalue, mlir::Location loc)
const;
150 Address createTempAlloca()
const;
153 bool requiresMemSetZero(mlir::Type ty)
const;
156 mlir::Value emitAtomicLoadOp(cir::MemOrder order,
bool isVolatile,
157 bool cmpxchg =
false);
173 uint64_t expectedSize) {
180bool AtomicInfo::requiresMemSetZero(mlir::Type ty)
const {
186 switch (getEvaluationKind()) {
193 mlir::cast<cir::ComplexType>(ty).getElementType(),
194 atomicSizeInBits / 2);
199 llvm_unreachable(
"bad evaluation kind");
202Address AtomicInfo::convertToAtomicIntPointer(Address addr,
203 mlir::Location loc)
const {
206 if (sourceSizeInBits != atomicSizeInBits) {
209 Address tmp = createTempAlloca();
221 std::min(atomicSizeInBits, sourceSizeInBits) / 8));
225 return castToAtomicIntPointer(addr);
228RValue AtomicInfo::convertAtomicTempToRValue(Address addr,
229 AggValueSlot resultSlot,
231 bool asValue)
const {
232 if (lvalue.isSimple()) {
239 "AtomicInfo::convertAtomicTempToRValue: hasPadding");
249 loc,
"AtomicInfo::convertAtomicTempToRValue: lvalue is not simple");
253RValue AtomicInfo::emitAtomicLoad(AggValueSlot resultSlot, SourceLocation loc,
254 bool asValue, cir::MemOrder order,
257 if (shouldUseLibCall()) {
259 cgf.
cgm.
errorNYI(loc,
"emitAtomicLoad: emit atomic lib call");
264 mlir::Value loadOp = emitAtomicLoadOp(order, isVolatile);
272 return convertToValueOrAtomic(loadOp, resultSlot, loc, asValue);
275Address AtomicInfo::createTempAlloca()
const {
278 QualType tmpTy = (lvalue.isBitField() && valueSizeInBits > atomicSizeInBits)
282 cgf.
createMemTemp(tmpTy, getAtomicAlignment(), loc,
"atomic-temp");
285 if (lvalue.isBitField()) {
286 cgf.
cgm.
errorNYI(loc,
"AtomicInfo::createTempAlloca: bitfield lvalue");
292mlir::Value AtomicInfo::getScalarRValValueOrNull(RValue rvalue)
const {
293 if (rvalue.
isScalar() && (!hasPadding() || !lvalue.isSimple()))
298Address AtomicInfo::castToAtomicIntPointer(Address addr)
const {
301 if (intTy && intTy.getWidth() == atomicSizeInBits)
307bool AtomicInfo::emitMemSetZeroIfNecessary()
const {
308 assert(lvalue.isSimple());
309 Address addr = lvalue.getAddress();
329 if (cir::isAnyFloatingPointType(valueTy))
334mlir::Value AtomicInfo::emitAtomicLoadOp(cir::MemOrder order,
bool isVolatile,
336 Address addr = getAtomicAddress();
338 addr = castToAtomicIntPointer(addr);
342 op.setMemOrder(order);
348mlir::Value AtomicInfo::convertRValueToInt(RValue rvalue, mlir::Location loc,
349 bool cmpxchg)
const {
352 if (mlir::Value value = getScalarRValValueOrNull(rvalue)) {
357 loc,
"AtomicInfo::convertRValueToInt: cast scalar rvalue to int");
363 Address addr = materializeRValue(rvalue, loc);
366 addr = castToAtomicIntPointer(addr);
371RValue AtomicInfo::convertToValueOrAtomic(mlir::Value intVal,
372 AggValueSlot resultSlot,
373 SourceLocation loc,
bool asValue,
374 bool cmpxchg)
const {
376 assert((mlir::isa<cir::IntType, cir::PointerType, cir::FPTypeInterface>(
377 intVal.getType())) &&
378 "Expected integer, pointer or floating point value when converting "
381 !lvalue.isBitField() || lvalue.getBitFieldInfo().size == valueSizeInBits;
383 ((isWholeValue && !hasPadding()) || !asValue)) {
385 : getAtomicAddress().getElementType();
387 assert((!mlir::isa<cir::IntType>(valTy) || intVal.getType() == valTy) &&
388 "Different integer types.");
392 cgf.
cgm.
errorNYI(
"convertToValueOrAtomic: convert through bitcast");
399 bool tempIsVolatile =
false;
405 temp = createTempAlloca();
409 Address castTemp = castToAtomicIntPointer(temp);
412 return convertAtomicTempToRValue(temp, resultSlot, loc, asValue);
417void AtomicInfo::emitCopyIntoMemory(RValue rvalue)
const {
418 assert(lvalue.isSimple());
424 cgf.
cgm.
errorNYI(
"copying aggregate into atomic lvalue");
431 emitMemSetZeroIfNecessary();
434 LValue tempLValue = projectValue();
447Address AtomicInfo::materializeRValue(RValue rvalue, mlir::Location loc)
const {
454 LValue tempLV = cgf.
makeAddrLValue(createTempAlloca(), getAtomicType());
455 AtomicInfo atomics(cgf, tempLV, loc);
457 atomics.emitCopyIntoMemory(rvalue);
458 return tempLV.getAddress();
462 mlir::ArrayAttr valuesAttr = builder.getArrayAttr({});
463 mlir::OpBuilder::InsertPoint insertPoint;
464 cir::CaseOp::create(builder, loc, valuesAttr, cir::CaseOpKind::Default,
466 builder.restoreInsertionPoint(insertPoint);
472 mlir::Type orderType,
475 for (cir::MemOrder order : orders)
476 orderAttrs.push_back(cir::IntAttr::get(orderType,
static_cast<int>(order)));
477 mlir::ArrayAttr ordersAttr = builder.getArrayAttr(orderAttrs);
479 mlir::OpBuilder::InsertPoint insertPoint;
480 cir::CaseOp::create(builder, loc, ordersAttr, cir::CaseOpKind::Anyof,
482 builder.restoreInsertionPoint(insertPoint);
488 cir::MemOrder successOrder,
489 cir::MemOrder failureOrder,
490 cir::SyncScopeKind scope) {
494 mlir::Value expected = builder.
createLoad(loc, val1);
495 mlir::Value desired = builder.
createLoad(loc, val2);
497 auto cmpxchg = cir::AtomicCmpXchgOp::create(
506 cmpxchg.setWeak(isWeak);
508 mlir::Value failed = builder.
createNot(cmpxchg.getSuccess());
509 cir::IfOp::create(builder, loc, failed,
false,
510 [&](mlir::OpBuilder &, mlir::Location) {
511 auto ptrTy = mlir::cast<cir::PointerType>(
530 Expr *failureOrderExpr, uint64_t size,
531 cir::MemOrder successOrder,
532 cir::SyncScopeKind scope) {
535 uint64_t failureOrderInt = failureOrderEval.
Val.
getInt().getZExtValue();
537 cir::MemOrder failureOrder;
539 failureOrder = cir::MemOrder::Relaxed;
541 switch ((cir::MemOrder)failureOrderInt) {
542 case cir::MemOrder::Relaxed:
545 case cir::MemOrder::Release:
546 case cir::MemOrder::AcquireRelease:
547 failureOrder = cir::MemOrder::Relaxed;
549 case cir::MemOrder::Consume:
550 case cir::MemOrder::Acquire:
551 failureOrder = cir::MemOrder::Acquire;
553 case cir::MemOrder::SequentiallyConsistent:
554 failureOrder = cir::MemOrder::SequentiallyConsistent;
564 failureOrder, scope);
572 mlir::Value failureOrderVal = cgf.
emitScalarExpr(failureOrderExpr);
574 cir::SwitchOp::create(
576 [&](mlir::OpBuilder &b, mlir::Location loc, mlir::OperationState &os) {
577 mlir::Block *switchBlock = cgf.getBuilder().getBlock();
589 emitDefaultCaseLabel(cgf.getBuilder(), atomicLoc);
590 emitAtomicCmpXchg(cgf, e, isWeak, dest, ptr, val1, val2, size,
591 successOrder, cir::MemOrder::Relaxed, scope);
592 cgf.getBuilder().createBreak(atomicLoc);
593 cgf.getBuilder().setInsertionPointToEnd(switchBlock);
597 emitMemOrderCaseLabel(cgf.getBuilder(), loc, failureOrderVal.getType(),
598 {cir::MemOrder::Consume, cir::MemOrder::Acquire});
600 successOrder, cir::MemOrder::Acquire, scope);
602 cgf.
getBuilder().setInsertionPointToEnd(switchBlock);
606 {cir::MemOrder::SequentiallyConsistent});
608 successOrder, cir::MemOrder::SequentiallyConsistent,
611 cgf.
getBuilder().setInsertionPointToEnd(switchBlock);
623 uint64_t size, cir::MemOrder successOrder, cir::SyncScopeKind scope) {
635 [&](mlir::OpBuilder &b, mlir::Location loc) {
636 emitAtomicCmpXchgFailureSet(cgf, e, true, dest, ptr, val1,
637 val2, failureOrderExpr, size, successOrder,
639 cgf.getBuilder().createYield(atomicLoc);
641 [&](mlir::OpBuilder &b, mlir::Location loc) {
642 emitAtomicCmpXchgFailureSet(cgf, e, false, dest, ptr, val1,
643 val2, failureOrderExpr, size, successOrder,
645 cgf.getBuilder().createYield(atomicLoc);
651 Expr *isWeakExpr,
Expr *failureOrderExpr, int64_t size,
652 cir::MemOrder order, cir::SyncScopeKind scope) {
654 llvm::StringRef opName;
657 mlir::Location loc = cgf.
getLoc(
expr->getSourceRange());
658 auto orderAttr = cir::MemOrderAttr::get(builder.getContext(), order);
659 auto scopeAttr = cir::SyncScopeKindAttr::get(builder.getContext(), scope);
660 cir::AtomicFetchKindAttr fetchAttr;
661 bool fetchFirst =
true;
663 auto handleFetchOp = [&](cir::AtomicFetchKind
kind) {
664 opName = cir::AtomicFetchOp::getOperationName();
665 fetchAttr = cir::AtomicFetchKindAttr::get(builder.getContext(),
kind);
668 switch (
expr->getOp()) {
669 case AtomicExpr::AO__c11_atomic_init:
670 llvm_unreachable(
"already handled!");
672 case AtomicExpr::AO__c11_atomic_compare_exchange_strong:
674 val2, failureOrderExpr, size, order, scope);
677 case AtomicExpr::AO__c11_atomic_compare_exchange_weak:
679 val2, failureOrderExpr, size, order, scope);
682 case AtomicExpr::AO__atomic_compare_exchange:
683 case AtomicExpr::AO__atomic_compare_exchange_n:
684 case AtomicExpr::AO__scoped_atomic_compare_exchange:
685 case AtomicExpr::AO__scoped_atomic_compare_exchange_n: {
689 failureOrderExpr, size, order, scope);
692 val1, val2, failureOrderExpr, size,
698 case AtomicExpr::AO__c11_atomic_load:
699 case AtomicExpr::AO__atomic_load_n:
700 case AtomicExpr::AO__atomic_load:
701 case AtomicExpr::AO__scoped_atomic_load_n:
702 case AtomicExpr::AO__scoped_atomic_load: {
706 load->setAttr(
"mem_order", orderAttr);
707 load->setAttr(
"sync_scope", scopeAttr);
709 builder.
createStore(loc, load->getResult(0), dest);
713 case AtomicExpr::AO__c11_atomic_store:
714 case AtomicExpr::AO__atomic_store_n:
715 case AtomicExpr::AO__atomic_store:
716 case AtomicExpr::AO__scoped_atomic_store:
717 case AtomicExpr::AO__scoped_atomic_store_n: {
718 cir::LoadOp loadVal1 = builder.
createLoad(loc, val1);
724 mlir::IntegerAttr{}, scopeAttr, orderAttr);
728 case AtomicExpr::AO__c11_atomic_exchange:
729 case AtomicExpr::AO__atomic_exchange_n:
730 case AtomicExpr::AO__atomic_exchange:
731 case AtomicExpr::AO__scoped_atomic_exchange_n:
732 case AtomicExpr::AO__scoped_atomic_exchange:
733 opName = cir::AtomicXchgOp::getOperationName();
736 case AtomicExpr::AO__atomic_add_fetch:
737 case AtomicExpr::AO__scoped_atomic_add_fetch:
740 case AtomicExpr::AO__c11_atomic_fetch_add:
741 case AtomicExpr::AO__atomic_fetch_add:
742 case AtomicExpr::AO__scoped_atomic_fetch_add:
743 handleFetchOp(cir::AtomicFetchKind::Add);
746 case AtomicExpr::AO__atomic_sub_fetch:
747 case AtomicExpr::AO__scoped_atomic_sub_fetch:
750 case AtomicExpr::AO__c11_atomic_fetch_sub:
751 case AtomicExpr::AO__atomic_fetch_sub:
752 case AtomicExpr::AO__scoped_atomic_fetch_sub:
753 handleFetchOp(cir::AtomicFetchKind::Sub);
756 case AtomicExpr::AO__atomic_min_fetch:
757 case AtomicExpr::AO__scoped_atomic_min_fetch:
760 case AtomicExpr::AO__c11_atomic_fetch_min:
761 case AtomicExpr::AO__atomic_fetch_min:
762 case AtomicExpr::AO__scoped_atomic_fetch_min:
763 handleFetchOp(cir::AtomicFetchKind::Min);
766 case AtomicExpr::AO__atomic_fetch_fminimum:
767 case AtomicExpr::AO__scoped_atomic_fetch_fminimum:
768 assert(
expr->getValueType()->isFloatingType() &&
769 "fminimum operations only support floating-point types");
770 handleFetchOp(cir::AtomicFetchKind::Minimum);
773 case AtomicExpr::AO__atomic_fetch_fminimum_num:
774 case AtomicExpr::AO__scoped_atomic_fetch_fminimum_num:
775 assert(
expr->getValueType()->isFloatingType() &&
776 "fminimum_num operations only support floating-point types");
777 handleFetchOp(cir::AtomicFetchKind::MinimumNum);
780 case AtomicExpr::AO__atomic_max_fetch:
781 case AtomicExpr::AO__scoped_atomic_max_fetch:
784 case AtomicExpr::AO__c11_atomic_fetch_max:
785 case AtomicExpr::AO__atomic_fetch_max:
786 case AtomicExpr::AO__scoped_atomic_fetch_max:
787 handleFetchOp(cir::AtomicFetchKind::Max);
790 case AtomicExpr::AO__atomic_fetch_fmaximum:
791 case AtomicExpr::AO__scoped_atomic_fetch_fmaximum:
792 assert(
expr->getValueType()->isFloatingType() &&
793 "fmaximum operations only support floating-point types");
794 handleFetchOp(cir::AtomicFetchKind::Maximum);
797 case AtomicExpr::AO__atomic_fetch_fmaximum_num:
798 case AtomicExpr::AO__scoped_atomic_fetch_fmaximum_num:
799 assert(
expr->getValueType()->isFloatingType() &&
800 "fmaximum_num operations only support floating-point types");
801 handleFetchOp(cir::AtomicFetchKind::MaximumNum);
804 case AtomicExpr::AO__atomic_and_fetch:
805 case AtomicExpr::AO__scoped_atomic_and_fetch:
808 case AtomicExpr::AO__c11_atomic_fetch_and:
809 case AtomicExpr::AO__atomic_fetch_and:
810 case AtomicExpr::AO__scoped_atomic_fetch_and:
811 handleFetchOp(cir::AtomicFetchKind::And);
814 case AtomicExpr::AO__atomic_or_fetch:
815 case AtomicExpr::AO__scoped_atomic_or_fetch:
818 case AtomicExpr::AO__c11_atomic_fetch_or:
819 case AtomicExpr::AO__atomic_fetch_or:
820 case AtomicExpr::AO__scoped_atomic_fetch_or:
821 handleFetchOp(cir::AtomicFetchKind::Or);
824 case AtomicExpr::AO__atomic_xor_fetch:
825 case AtomicExpr::AO__scoped_atomic_xor_fetch:
828 case AtomicExpr::AO__c11_atomic_fetch_xor:
829 case AtomicExpr::AO__atomic_fetch_xor:
830 case AtomicExpr::AO__scoped_atomic_fetch_xor:
831 handleFetchOp(cir::AtomicFetchKind::Xor);
834 case AtomicExpr::AO__atomic_nand_fetch:
835 case AtomicExpr::AO__scoped_atomic_nand_fetch:
838 case AtomicExpr::AO__c11_atomic_fetch_nand:
839 case AtomicExpr::AO__atomic_fetch_nand:
840 case AtomicExpr::AO__scoped_atomic_fetch_nand:
841 handleFetchOp(cir::AtomicFetchKind::Nand);
844 case AtomicExpr::AO__atomic_test_and_set: {
845 auto op = cir::AtomicTestAndSetOp::create(
853 case AtomicExpr::AO__atomic_clear: {
854 cir::AtomicClearOp::create(
861 case AtomicExpr::AO__atomic_fetch_uinc:
862 case AtomicExpr::AO__scoped_atomic_fetch_uinc:
863 handleFetchOp(cir::AtomicFetchKind::UIncWrap);
866 case AtomicExpr::AO__atomic_fetch_udec:
867 case AtomicExpr::AO__scoped_atomic_fetch_udec:
868 handleFetchOp(cir::AtomicFetchKind::UDecWrap);
871 case AtomicExpr::AO__opencl_atomic_init:
873 case AtomicExpr::AO__hip_atomic_compare_exchange_strong:
874 case AtomicExpr::AO__opencl_atomic_compare_exchange_strong:
876 case AtomicExpr::AO__opencl_atomic_compare_exchange_weak:
877 case AtomicExpr::AO__hip_atomic_compare_exchange_weak:
879 case AtomicExpr::AO__opencl_atomic_load:
880 case AtomicExpr::AO__hip_atomic_load:
882 case AtomicExpr::AO__opencl_atomic_store:
883 case AtomicExpr::AO__hip_atomic_store:
885 case AtomicExpr::AO__hip_atomic_exchange:
886 case AtomicExpr::AO__opencl_atomic_exchange:
888 case AtomicExpr::AO__hip_atomic_fetch_add:
889 case AtomicExpr::AO__opencl_atomic_fetch_add:
891 case AtomicExpr::AO__hip_atomic_fetch_sub:
892 case AtomicExpr::AO__opencl_atomic_fetch_sub:
894 case AtomicExpr::AO__hip_atomic_fetch_min:
895 case AtomicExpr::AO__opencl_atomic_fetch_min:
897 case AtomicExpr::AO__hip_atomic_fetch_max:
898 case AtomicExpr::AO__opencl_atomic_fetch_max:
900 case AtomicExpr::AO__hip_atomic_fetch_and:
901 case AtomicExpr::AO__opencl_atomic_fetch_and:
903 case AtomicExpr::AO__hip_atomic_fetch_or:
904 case AtomicExpr::AO__opencl_atomic_fetch_or:
906 case AtomicExpr::AO__hip_atomic_fetch_xor:
907 case AtomicExpr::AO__opencl_atomic_fetch_xor:
913 assert(!opName.empty() &&
"expected operation name to build");
914 mlir::Value loadVal1 = builder.
createLoad(loc, val1);
918 mlir::Operation *rmwOp = builder.create(loc, builder.getStringAttr(opName),
919 atomicOperands, atomicResTys);
922 rmwOp->setAttr(
"binop", fetchAttr);
923 rmwOp->setAttr(
"mem_order", orderAttr);
924 rmwOp->setAttr(
"sync_scope", scopeAttr);
925 if (
expr->isVolatile())
926 rmwOp->setAttr(
"is_volatile", builder.getUnitAttr());
927 if (fetchFirst && opName == cir::AtomicFetchOp::getOperationName())
928 rmwOp->setAttr(
"fetch_first", builder.getUnitAttr());
930 mlir::Value result = rmwOp->getResult(0);
941 return cir::SyncScopeKind::SingleThread;
943 return cir::SyncScopeKind::System;
945 return cir::SyncScopeKind::Device;
947 return cir::SyncScopeKind::Workgroup;
949 return cir::SyncScopeKind::Wavefront;
951 return cir::SyncScopeKind::Cluster;
954 return cir::SyncScopeKind::HIPSingleThread;
956 return cir::SyncScopeKind::HIPSystem;
958 return cir::SyncScopeKind::HIPAgent;
960 return cir::SyncScopeKind::HIPWorkgroup;
962 return cir::SyncScopeKind::HIPWavefront;
964 return cir::SyncScopeKind::HIPCluster;
967 return cir::SyncScopeKind::OpenCLWorkGroup;
969 return cir::SyncScopeKind::OpenCLDevice;
971 return cir::SyncScopeKind::OpenCLAllSVMDevices;
973 return cir::SyncScopeKind::OpenCLSubGroup;
976 llvm_unreachable(
"unhandled sync scope");
981 Expr *isWeakExpr,
Expr *failureOrderExpr, int64_t size,
983 const std::optional<Expr::EvalResult> &scopeConst,
984 mlir::Value scopeValue) {
985 std::unique_ptr<AtomicScopeModel> scopeModel =
expr->getScopeModel();
988 emitAtomicOp(cgf,
expr, dest, ptr, val1, val2, isWeakExpr, failureOrderExpr,
989 size, order, cir::SyncScopeKind::System);
993 if (scopeConst.has_value()) {
995 cgf,
expr->getScope()->getSourceRange(),
996 scopeModel->map(scopeConst->Val.getInt().getZExtValue()));
997 emitAtomicOp(cgf,
expr, dest, ptr, val1, val2, isWeakExpr, failureOrderExpr,
998 size, order, mappedScope);
1005 mlir::Location loc = cgf.
getLoc(
expr->getSourceRange());
1007 unsigned fallback = scopeModel->getFallBackValue();
1009 cir::SwitchOp::create(
1010 builder, loc, scopeValue,
1011 [&](mlir::OpBuilder &, mlir::Location loc, mlir::OperationState &) {
1012 mlir::Block *switchBlock = builder.getBlock();
1016 cgf,
expr->getScope()->getSourceRange(), scopeModel->map(fallback));
1019 failureOrderExpr, size, order, fallbackScope);
1021 builder.setInsertionPointToEnd(switchBlock);
1024 for (
unsigned scope : allScopes) {
1025 if (scope == fallback)
1029 cgf,
expr->getScope()->getSourceRange(), scopeModel->map(scope));
1031 mlir::ArrayAttr casesAttr = builder.getArrayAttr(
1032 {cir::IntAttr::get(scopeValue.getType(), scope)});
1033 mlir::OpBuilder::InsertPoint insertPoint;
1034 cir::CaseOp::create(builder, loc, casesAttr, cir::CaseOpKind::Equal,
1037 builder.restoreInsertionPoint(insertPoint);
1039 failureOrderExpr, size, order, cirScope);
1041 builder.setInsertionPointToEnd(switchBlock);
1048static std::optional<cir::MemOrder>
1058 if (oriOrder == cir::MemOrder::Consume ||
1059 oriOrder == cir::MemOrder::Acquire ||
1060 oriOrder == cir::MemOrder::AcquireRelease)
1061 return std::nullopt;
1062 }
else if (isLoad) {
1063 if (oriOrder == cir::MemOrder::Release ||
1064 oriOrder == cir::MemOrder::AcquireRelease)
1065 return std::nullopt;
1066 }
else if (isFence) {
1067 if (oriOrder == cir::MemOrder::Relaxed)
1068 return std::nullopt;
1072 if (oriOrder == cir::MemOrder::Consume)
1073 return cir::MemOrder::Acquire;
1078 CIRGenFunction &cgf, mlir::Value order,
bool isStore,
bool isLoad,
1079 bool isFence, llvm::function_ref<
void(cir::MemOrder)> emitAtomicOpFn) {
1087 cir::SwitchOp::create(
1088 builder, order.getLoc(), order,
1089 [&](mlir::OpBuilder &, mlir::Location loc, mlir::OperationState &) {
1090 mlir::Block *switchBlock = builder.getBlock();
1092 auto emitMemOrderCase = [&](llvm::ArrayRef<cir::MemOrder> caseOrders) {
1094 for (int i = 1, e = caseOrders.size(); i < e; i++)
1095 assert((getEffectiveAtomicMemOrder(caseOrders[i - 1], isStore,
1097 getEffectiveAtomicMemOrder(caseOrders[i], isStore, isLoad,
1099 "Effective memory order must be same!");
1101 if (caseOrders.empty()) {
1102 emitDefaultCaseLabel(builder, loc);
1106 emitAtomicOpFn(cir::MemOrder::Relaxed);
1107 } else if (std::optional<cir::MemOrder> actualOrder =
1108 getEffectiveAtomicMemOrder(caseOrders[0], isStore,
1111 if (!isFence && actualOrder == cir::MemOrder::Relaxed)
1116 emitMemOrderCaseLabel(builder, loc, order.getType(), caseOrders);
1117 emitAtomicOpFn(actualOrder.value());
1122 builder.createBreak(loc);
1123 builder.setInsertionPointToEnd(switchBlock);
1126 emitMemOrderCase( {});
1127 emitMemOrderCase({cir::MemOrder::Relaxed});
1128 emitMemOrderCase({cir::MemOrder::Consume, cir::MemOrder::Acquire});
1129 emitMemOrderCase({cir::MemOrder::Release});
1130 emitMemOrderCase({cir::MemOrder::AcquireRelease});
1131 emitMemOrderCase({cir::MemOrder::SequentiallyConsistent});
1138 const Expr *memOrder,
bool isStore,
bool isLoad,
bool isFence,
1139 llvm::function_ref<
void(cir::MemOrder)> emitAtomicOpFn) {
1143 uint64_t constOrder = eval.
Val.
getInt().getZExtValue();
1148 cir::MemOrder oriOrder =
static_cast<cir::MemOrder
>(constOrder);
1149 if (std::optional<cir::MemOrder> actualOrder =
1151 emitAtomicOpFn(actualOrder.value());
1168 mlir::NamedAttrList fnAttrs;
1178 Address val1, uint64_t atomicTySize,
1191 auto castToGenericAddrSpace = [&](mlir::Value v,
QualType pt) {
1196 cgf.
cgm.
errorNYI(loc,
"emitLibCallForAtomicExpr: openCL");
1204 llvm::StringRef calleeName;
1206 bool hasRetTy =
false;
1207 switch (e->
getOp()) {
1208 case AtomicExpr::AO__c11_atomic_init:
1209 case AtomicExpr::AO__opencl_atomic_init:
1210 llvm_unreachable(
"Already handled!");
1217 case AtomicExpr::AO__atomic_compare_exchange:
1218 case AtomicExpr::AO__atomic_compare_exchange_n:
1219 case AtomicExpr::AO__c11_atomic_compare_exchange_weak:
1220 case AtomicExpr::AO__c11_atomic_compare_exchange_strong:
1221 case AtomicExpr::AO__hip_atomic_compare_exchange_weak:
1222 case AtomicExpr::AO__hip_atomic_compare_exchange_strong:
1223 case AtomicExpr::AO__opencl_atomic_compare_exchange_weak:
1224 case AtomicExpr::AO__opencl_atomic_compare_exchange_strong:
1225 case AtomicExpr::AO__scoped_atomic_compare_exchange:
1226 case AtomicExpr::AO__scoped_atomic_compare_exchange_n:
1228 loc,
"emitLibCallForAtomicExpr: atomic compare-and-exchange NYI");
1233 case AtomicExpr::AO__atomic_exchange:
1234 case AtomicExpr::AO__atomic_exchange_n:
1235 case AtomicExpr::AO__c11_atomic_exchange:
1236 case AtomicExpr::AO__hip_atomic_exchange:
1237 case AtomicExpr::AO__opencl_atomic_exchange:
1238 case AtomicExpr::AO__scoped_atomic_exchange:
1239 case AtomicExpr::AO__scoped_atomic_exchange_n:
1240 cgf.
cgm.
errorNYI(loc,
"emitLibCallForAtomicExpr: atomic exchange NYI");
1244 case AtomicExpr::AO__atomic_store:
1245 case AtomicExpr::AO__atomic_store_n:
1246 case AtomicExpr::AO__c11_atomic_store:
1247 case AtomicExpr::AO__scoped_atomic_store:
1248 case AtomicExpr::AO__scoped_atomic_store_n: {
1249 calleeName =
"__atomic_store";
1258 case AtomicExpr::AO__hip_atomic_store:
1259 case AtomicExpr::AO__opencl_atomic_store:
1261 "emitLibCallForAtomicExpr: atomic store for hip/opencl");
1265 case AtomicExpr::AO__atomic_load:
1266 case AtomicExpr::AO__atomic_load_n:
1267 case AtomicExpr::AO__c11_atomic_load:
1268 case AtomicExpr::AO__scoped_atomic_load:
1269 case AtomicExpr::AO__scoped_atomic_load_n: {
1270 calleeName =
"__atomic_load";
1274 case AtomicExpr::AO__hip_atomic_load:
1275 case AtomicExpr::AO__opencl_atomic_load:
1277 "emitLibCallForAtomicExpr: atomic load for hip/opencl");
1280 case AtomicExpr::AO__atomic_fetch_fmaximum:
1281 case AtomicExpr::AO__atomic_fetch_fmaximum_num:
1282 case AtomicExpr::AO__atomic_fetch_fminimum:
1283 case AtomicExpr::AO__atomic_fetch_fminimum_num:
1284 case AtomicExpr::AO__scoped_atomic_fetch_fmaximum:
1285 case AtomicExpr::AO__scoped_atomic_fetch_fmaximum_num:
1286 case AtomicExpr::AO__scoped_atomic_fetch_fminimum:
1287 case AtomicExpr::AO__scoped_atomic_fetch_fminimum_num:
1289 loc,
"emitLibCallForAtomicExpr: atomic fetch fmaximum/fminimum");
1292 case AtomicExpr::AO__atomic_add_fetch:
1293 case AtomicExpr::AO__scoped_atomic_add_fetch:
1294 case AtomicExpr::AO__atomic_fetch_add:
1295 case AtomicExpr::AO__c11_atomic_fetch_add:
1296 case AtomicExpr::AO__hip_atomic_fetch_add:
1297 case AtomicExpr::AO__opencl_atomic_fetch_add:
1298 case AtomicExpr::AO__scoped_atomic_fetch_add:
1299 case AtomicExpr::AO__atomic_and_fetch:
1300 case AtomicExpr::AO__scoped_atomic_and_fetch:
1301 case AtomicExpr::AO__atomic_fetch_and:
1302 case AtomicExpr::AO__c11_atomic_fetch_and:
1303 case AtomicExpr::AO__hip_atomic_fetch_and:
1304 case AtomicExpr::AO__opencl_atomic_fetch_and:
1305 case AtomicExpr::AO__scoped_atomic_fetch_and:
1306 case AtomicExpr::AO__atomic_or_fetch:
1307 case AtomicExpr::AO__scoped_atomic_or_fetch:
1308 case AtomicExpr::AO__atomic_fetch_or:
1309 case AtomicExpr::AO__c11_atomic_fetch_or:
1310 case AtomicExpr::AO__hip_atomic_fetch_or:
1311 case AtomicExpr::AO__opencl_atomic_fetch_or:
1312 case AtomicExpr::AO__scoped_atomic_fetch_or:
1313 case AtomicExpr::AO__atomic_sub_fetch:
1314 case AtomicExpr::AO__scoped_atomic_sub_fetch:
1315 case AtomicExpr::AO__atomic_fetch_sub:
1316 case AtomicExpr::AO__c11_atomic_fetch_sub:
1317 case AtomicExpr::AO__hip_atomic_fetch_sub:
1318 case AtomicExpr::AO__opencl_atomic_fetch_sub:
1319 case AtomicExpr::AO__scoped_atomic_fetch_sub:
1320 case AtomicExpr::AO__atomic_xor_fetch:
1321 case AtomicExpr::AO__scoped_atomic_xor_fetch:
1322 case AtomicExpr::AO__atomic_fetch_xor:
1323 case AtomicExpr::AO__c11_atomic_fetch_xor:
1324 case AtomicExpr::AO__hip_atomic_fetch_xor:
1325 case AtomicExpr::AO__opencl_atomic_fetch_xor:
1326 case AtomicExpr::AO__scoped_atomic_fetch_xor:
1327 case AtomicExpr::AO__atomic_nand_fetch:
1328 case AtomicExpr::AO__atomic_fetch_nand:
1329 case AtomicExpr::AO__c11_atomic_fetch_nand:
1330 case AtomicExpr::AO__scoped_atomic_fetch_nand:
1331 case AtomicExpr::AO__scoped_atomic_nand_fetch:
1332 case AtomicExpr::AO__atomic_min_fetch:
1333 case AtomicExpr::AO__atomic_fetch_min:
1334 case AtomicExpr::AO__c11_atomic_fetch_min:
1335 case AtomicExpr::AO__hip_atomic_fetch_min:
1336 case AtomicExpr::AO__opencl_atomic_fetch_min:
1337 case AtomicExpr::AO__scoped_atomic_fetch_min:
1338 case AtomicExpr::AO__scoped_atomic_min_fetch:
1339 case AtomicExpr::AO__atomic_max_fetch:
1340 case AtomicExpr::AO__atomic_fetch_max:
1341 case AtomicExpr::AO__c11_atomic_fetch_max:
1342 case AtomicExpr::AO__hip_atomic_fetch_max:
1343 case AtomicExpr::AO__opencl_atomic_fetch_max:
1344 case AtomicExpr::AO__scoped_atomic_fetch_max:
1345 case AtomicExpr::AO__scoped_atomic_max_fetch:
1346 case AtomicExpr::AO__scoped_atomic_fetch_uinc:
1347 case AtomicExpr::AO__scoped_atomic_fetch_udec:
1348 case AtomicExpr::AO__atomic_test_and_set:
1349 case AtomicExpr::AO__atomic_clear:
1350 case AtomicExpr::AO__atomic_fetch_uinc:
1351 case AtomicExpr::AO__atomic_fetch_udec:
1352 llvm_unreachable(
"Integral atomic operations always become atomicrmw!");
1357 cgf.
cgm.
errorNYI(loc,
"emitLibCallForAtomicExpr: openCL");
1374 cgf.
cgm.
errorNYI(loc,
"emitLibCallForAtomicExpr: openCL");
1396 memTy = ty->getValueType();
1398 Expr *isWeakExpr =
nullptr;
1399 Expr *orderFailExpr =
nullptr;
1407 if (e->
getOp() == AtomicExpr::AO__c11_atomic_init) {
1419 std::optional<Expr::EvalResult> scopeConst;
1422 scopeConst.emplace(std::move(eval));
1424 switch (e->
getOp()) {
1429 case AtomicExpr::AO__c11_atomic_init:
1430 llvm_unreachable(
"already handled above with emitAtomicInit");
1432 case AtomicExpr::AO__atomic_load_n:
1433 case AtomicExpr::AO__scoped_atomic_load_n:
1434 case AtomicExpr::AO__c11_atomic_load:
1435 case AtomicExpr::AO__atomic_test_and_set:
1436 case AtomicExpr::AO__atomic_clear:
1439 case AtomicExpr::AO__atomic_load:
1440 case AtomicExpr::AO__scoped_atomic_load:
1444 case AtomicExpr::AO__atomic_store:
1445 case AtomicExpr::AO__scoped_atomic_store:
1449 case AtomicExpr::AO__atomic_exchange:
1450 case AtomicExpr::AO__scoped_atomic_exchange:
1455 case AtomicExpr::AO__atomic_compare_exchange:
1456 case AtomicExpr::AO__atomic_compare_exchange_n:
1457 case AtomicExpr::AO__c11_atomic_compare_exchange_weak:
1458 case AtomicExpr::AO__c11_atomic_compare_exchange_strong:
1459 case AtomicExpr::AO__scoped_atomic_compare_exchange:
1460 case AtomicExpr::AO__scoped_atomic_compare_exchange_n:
1462 if (e->
getOp() == AtomicExpr::AO__atomic_compare_exchange ||
1463 e->
getOp() == AtomicExpr::AO__scoped_atomic_compare_exchange)
1468 if (e->
getOp() == AtomicExpr::AO__atomic_compare_exchange_n ||
1469 e->
getOp() == AtomicExpr::AO__atomic_compare_exchange ||
1470 e->
getOp() == AtomicExpr::AO__scoped_atomic_compare_exchange_n ||
1471 e->
getOp() == AtomicExpr::AO__scoped_atomic_compare_exchange)
1475 case AtomicExpr::AO__c11_atomic_fetch_add:
1476 case AtomicExpr::AO__c11_atomic_fetch_sub:
1487 mlir::Value scale = builder.getConstInt(loc, val1Scalar.getType(),
1489 val1Scalar = builder.createMul(loc, val1Scalar, scale);
1495 case AtomicExpr::AO__atomic_fetch_add:
1496 case AtomicExpr::AO__atomic_fetch_sub:
1497 case AtomicExpr::AO__atomic_add_fetch:
1498 case AtomicExpr::AO__atomic_sub_fetch:
1508 case AtomicExpr::AO__atomic_fetch_max:
1509 case AtomicExpr::AO__atomic_fetch_min:
1510 case AtomicExpr::AO__atomic_max_fetch:
1511 case AtomicExpr::AO__atomic_min_fetch:
1512 case AtomicExpr::AO__c11_atomic_fetch_max:
1513 case AtomicExpr::AO__c11_atomic_fetch_min:
1514 case AtomicExpr::AO__scoped_atomic_fetch_add:
1515 case AtomicExpr::AO__scoped_atomic_fetch_max:
1516 case AtomicExpr::AO__scoped_atomic_fetch_min:
1517 case AtomicExpr::AO__scoped_atomic_fetch_sub:
1518 case AtomicExpr::AO__scoped_atomic_fetch_fminimum:
1519 case AtomicExpr::AO__scoped_atomic_fetch_fmaximum:
1520 case AtomicExpr::AO__scoped_atomic_fetch_fminimum_num:
1521 case AtomicExpr::AO__scoped_atomic_fetch_fmaximum_num:
1522 case AtomicExpr::AO__scoped_atomic_add_fetch:
1523 case AtomicExpr::AO__scoped_atomic_max_fetch:
1524 case AtomicExpr::AO__scoped_atomic_min_fetch:
1525 case AtomicExpr::AO__scoped_atomic_sub_fetch:
1528 case AtomicExpr::AO__atomic_fetch_and:
1529 case AtomicExpr::AO__atomic_fetch_nand:
1530 case AtomicExpr::AO__atomic_fetch_or:
1531 case AtomicExpr::AO__atomic_fetch_xor:
1532 case AtomicExpr::AO__atomic_and_fetch:
1533 case AtomicExpr::AO__atomic_nand_fetch:
1534 case AtomicExpr::AO__atomic_or_fetch:
1535 case AtomicExpr::AO__atomic_xor_fetch:
1536 case AtomicExpr::AO__atomic_exchange_n:
1537 case AtomicExpr::AO__atomic_store_n:
1538 case AtomicExpr::AO__c11_atomic_fetch_and:
1539 case AtomicExpr::AO__c11_atomic_fetch_nand:
1540 case AtomicExpr::AO__c11_atomic_fetch_or:
1541 case AtomicExpr::AO__c11_atomic_fetch_xor:
1542 case AtomicExpr::AO__c11_atomic_exchange:
1543 case AtomicExpr::AO__c11_atomic_store:
1544 case AtomicExpr::AO__scoped_atomic_fetch_and:
1545 case AtomicExpr::AO__scoped_atomic_fetch_nand:
1546 case AtomicExpr::AO__scoped_atomic_fetch_or:
1547 case AtomicExpr::AO__scoped_atomic_fetch_xor:
1548 case AtomicExpr::AO__scoped_atomic_and_fetch:
1549 case AtomicExpr::AO__scoped_atomic_nand_fetch:
1550 case AtomicExpr::AO__scoped_atomic_or_fetch:
1551 case AtomicExpr::AO__scoped_atomic_xor_fetch:
1552 case AtomicExpr::AO__scoped_atomic_store_n:
1553 case AtomicExpr::AO__scoped_atomic_exchange_n:
1554 case AtomicExpr::AO__atomic_fetch_uinc:
1555 case AtomicExpr::AO__atomic_fetch_udec:
1556 case AtomicExpr::AO__scoped_atomic_fetch_uinc:
1557 case AtomicExpr::AO__scoped_atomic_fetch_udec:
1558 case AtomicExpr::AO__atomic_fetch_fminimum:
1559 case AtomicExpr::AO__atomic_fetch_fmaximum:
1560 case AtomicExpr::AO__atomic_fetch_fminimum_num:
1561 case AtomicExpr::AO__atomic_fetch_fmaximum_num:
1568 bool shouldCastToIntPtrTy =
1576 AtomicInfo atomics(*
this, atomicValue, loc);
1578 if (shouldCastToIntPtrTy) {
1579 ptr = atomics.castToAtomicIntPointer(ptr);
1581 val1 = atomics.convertToAtomicIntPointer(val1, loc);
1583 val2 = atomics.convertToAtomicIntPointer(val2, loc);
1586 if (shouldCastToIntPtrTy)
1587 dest = atomics.castToAtomicIntPointer(dest);
1590 }
else if (e->
getOp() == AtomicExpr::AO__atomic_test_and_set) {
1593 dest = atomics.createTempAlloca();
1594 if (shouldCastToIntPtrTy)
1595 dest = atomics.castToAtomicIntPointer(dest);
1598 bool powerOf2Size = (size & (size - 1)) == 0;
1599 bool useLibCall = !powerOf2Size || (size > 16);
1613 bool isStore = e->
getOp() == AtomicExpr::AO__c11_atomic_store ||
1614 e->
getOp() == AtomicExpr::AO__opencl_atomic_store ||
1615 e->
getOp() == AtomicExpr::AO__hip_atomic_store ||
1616 e->
getOp() == AtomicExpr::AO__atomic_store ||
1617 e->
getOp() == AtomicExpr::AO__atomic_store_n ||
1618 e->
getOp() == AtomicExpr::AO__scoped_atomic_store ||
1619 e->
getOp() == AtomicExpr::AO__scoped_atomic_store_n ||
1620 e->
getOp() == AtomicExpr::AO__atomic_clear;
1621 bool isLoad = e->
getOp() == AtomicExpr::AO__c11_atomic_load ||
1622 e->
getOp() == AtomicExpr::AO__opencl_atomic_load ||
1623 e->
getOp() == AtomicExpr::AO__hip_atomic_load ||
1624 e->
getOp() == AtomicExpr::AO__atomic_load ||
1625 e->
getOp() == AtomicExpr::AO__atomic_load_n ||
1626 e->
getOp() == AtomicExpr::AO__scoped_atomic_load ||
1627 e->
getOp() == AtomicExpr::AO__scoped_atomic_load_n;
1629 auto emitAtomicOpCallBackFn = [&](cir::MemOrder memOrder) {
1630 emitAtomicOp(*
this, e, dest, ptr, val1, val2, isWeakExpr, orderFailExpr,
1631 size, memOrder, scopeConst, scope);
1634 emitAtomicOpCallBackFn);
1647 return emitAtomicLoad(lvalue, loc, cir::MemOrder::SequentiallyConsistent,
1654 cir::MemOrder order,
bool isVolatile,
1656 AtomicInfo info(*
this, lvalue,
getLoc(loc));
1657 return info.emitAtomicLoad(slot, loc,
true, order, isVolatile);
1662 auto order = cir::MemOrder::SequentiallyConsistent;
1675 cir::MemOrder order,
bool isVolatile,
1679 mlir::Location loc = dest.
getPointer().getLoc();
1684 AtomicInfo atomics(*
this, dest, loc);
1685 LValue lvalue = atomics.getAtomicLValue();
1690 atomics.emitCopyIntoMemory(rvalue);
1695 if (atomics.shouldUseLibCall()) {
1697 cgm.errorNYI(loc,
"emitAtomicStore: atomic store with library call");
1702 mlir::Value valueToStore = atomics.convertRValueToInt(rvalue, loc);
1705 Address addr = atomics.getAtomicAddress();
1706 if (mlir::Value value = atomics.getScalarRValValueOrNull(rvalue)) {
1708 addr = atomics.castToAtomicIntPointer(addr);
1713 cir::StoreOp store = builder.createStore(loc, valueToStore, addr);
1718 store.setMemOrder(order);
1723 store.setIsVolatile(
true);
1729 cgm.errorNYI(loc,
"emitAtomicStore: non-simple atomic lvalue");
1736 switch (atomics.getEvaluationKind()) {
1752 bool zeroed =
false;
1754 zeroed = atomics.emitMemSetZeroIfNecessary();
1755 dest = atomics.projectValue();
1770 llvm_unreachable(
"bad evaluation kind");
static bool shouldCastToInt(mlir::Type valueTy, bool cmpxchg)
Return true if.
static RValue emitLibCallForAtomicExpr(CIRGenFunction &cgf, AtomicExpr *e, Address atomicPtr, Address dest, Address val1, uint64_t atomicTySize, QualType resultTy)
static Address emitValToTemp(CIRGenFunction &cgf, Expr *e)
static void emitAtomicCmpXchgFailureSetCheckWeak(CIRGenFunction &cgf, AtomicExpr *e, Expr *isWeakExpr, Address dest, Address ptr, Address val1, Address val2, Expr *failureOrderExpr, uint64_t size, cir::MemOrder successOrder, cir::SyncScopeKind scope)
static void emitAtomicCmpXchg(CIRGenFunction &cgf, AtomicExpr *e, bool isWeak, Address dest, Address ptr, Address val1, Address val2, uint64_t size, cir::MemOrder successOrder, cir::MemOrder failureOrder, cir::SyncScopeKind scope)
static void emitMemOrderCaseLabel(CIRGenBuilderTy &builder, mlir::Location loc, mlir::Type orderType, llvm::ArrayRef< cir::MemOrder > orders)
static cir::SyncScopeKind convertSyncScopeToCIR(CIRGenFunction &cgf, SourceRange range, clang::SyncScope scope)
static void emitAtomicExprWithDynamicMemOrder(CIRGenFunction &cgf, mlir::Value order, bool isStore, bool isLoad, bool isFence, llvm::function_ref< void(cir::MemOrder)> emitAtomicOpFn)
static void emitAtomicOp(CIRGenFunction &cgf, AtomicExpr *expr, Address dest, Address ptr, Address val1, Address val2, Expr *isWeakExpr, Expr *failureOrderExpr, int64_t size, cir::MemOrder order, cir::SyncScopeKind scope)
static void emitDefaultCaseLabel(CIRGenBuilderTy &builder, mlir::Location loc)
static bool isFullSizeType(CIRGenModule &cgm, mlir::Type ty, uint64_t expectedSize)
Does a store of the given IR type modify the full expected width?
static std::optional< cir::MemOrder > getEffectiveAtomicMemOrder(cir::MemOrder oriOrder, bool isStore, bool isLoad, bool isFence)
static void emitAtomicCmpXchgFailureSet(CIRGenFunction &cgf, AtomicExpr *e, bool isWeak, Address dest, Address ptr, Address val1, Address val2, Expr *failureOrderExpr, uint64_t size, cir::MemOrder successOrder, cir::SyncScopeKind scope)
static RValue emitAtomicLibCall(CIRGenFunction &cgf, llvm::StringRef funcName, QualType resultType, CallArgList &args)
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
cir::BreakOp createBreak(mlir::Location loc)
Create a break operation.
mlir::Value createPtrBitcast(mlir::Value src, mlir::Type newPointeeTy)
mlir::Value createNot(mlir::Location loc, mlir::Value value)
cir::YieldOp createYield(mlir::Location loc, mlir::ValueRange value={})
Create a yield operation.
cir::BoolType getBoolTy()
llvm::TypeSize getTypeSizeInBits(mlir::Type ty) const
llvm::TypeSize getTypeStoreSize(mlir::Type ty) const
Returns the maximum number of bytes that may be overwritten by storing the specified type.
TypeInfo getTypeInfo(const Type *T) const
Get the size and alignment of the specified complete type in bits.
int64_t toBits(CharUnits CharSize) const
Convert a size in characters to a size in bits.
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
const TargetInfo & getTargetInfo() const
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, __atomic_load,...
static std::unique_ptr< AtomicScopeModel > getScopeModel(AtomicOp Op)
Get atomic scope model for the atomic op code.
Expr * getOrderFail() const
Address withPointer(mlir::Value newPtr) const
Return address with different pointer, but same element type and alignment.
mlir::Value getPointer() const
mlir::Type getElementType() const
Address withElementType(CIRGenBuilderTy &builder, mlir::Type ElemTy) const
Return address with different element type, a bitcast pointer, and the same alignment.
clang::CharUnits getAlignment() const
mlir::Value emitRawPointer() const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
static AggValueSlot forLValue(const LValue &LV, IsDestructed_t isDestructed, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed)
Address getAddress() const
cir::MemCpyOp createMemCpy(mlir::Location loc, mlir::Value dst, mlir::Value src, mlir::Value len)
cir::LoadOp createLoad(mlir::Location loc, Address addr, bool isVolatile=false, bool isNontemporal=false)
cir::StoreOp createStore(mlir::Location loc, mlir::Value val, Address dst, bool isVolatile=false, bool isNontemporal=false, mlir::IntegerAttr align={}, cir::SyncScopeKindAttr scope={}, cir::MemOrderAttr order={})
cir::ConstantOp getConstInt(mlir::Location loc, llvm::APSInt intVal)
cir::MemSetOp createMemSet(mlir::Location loc, mlir::Value dst, mlir::Value val, mlir::Value len)
cir::IntType getUIntNTy(int n)
static CIRGenCallee forDirect(mlir::Operation *funcPtr, const CIRGenCalleeInfo &abstractInfo=CIRGenCalleeInfo())
RValue convertTempToRValue(Address addr, clang::QualType type, clang::SourceLocation loc)
Given the address of a temporary variable, produce an r-value of its type.
Address emitPointerWithAlignment(const clang::Expr *expr, LValueBaseInfo *baseInfo=nullptr)
Given an expression with a pointer type, emit the value and compute our best estimate of the alignmen...
mlir::Value emitComplexExpr(const Expr *e)
Emit the computation of the specified expression of complex type, returning the result.
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
void emitAnyExprToMem(const Expr *e, Address location, Qualifiers quals, bool isInitializer)
Emits the code necessary to evaluate an arbitrary expression into the given memory location.
RValue emitAtomicExpr(AtomicExpr *e)
RValue emitAtomicLoad(LValue lvalue, SourceLocation loc, AggValueSlot slot=AggValueSlot::ignored())
mlir::Type convertTypeForMem(QualType t)
void emitStoreOfScalar(mlir::Value value, Address addr, bool isVolatile, clang::QualType ty, LValueBaseInfo baseInfo, bool isInit=false, bool isNontemporal=false)
void emitStoreOfComplex(mlir::Location loc, mlir::Value v, LValue dest, bool isInit)
EmitStoreOfComplex - Store a complex number into the specified l-value.
RValue emitCall(const CIRGenFunctionInfo &funcInfo, const CIRGenCallee &callee, ReturnValueSlot returnValue, const CallArgList &args, cir::CIRCallOpInterface *callOp, mlir::Location loc)
void emitAtomicExprWithMemOrder(const Expr *memOrder, bool isStore, bool isLoad, bool isFence, llvm::function_ref< void(cir::MemOrder)> emitAtomicOp)
mlir::Value emitToMemory(mlir::Value value, clang::QualType ty)
Given a value and its clang type, returns the value casted to its memory representation.
mlir::Value emitScalarExpr(const clang::Expr *e, bool ignoreResultAssign=false)
Emit the computation of the specified expression of scalar type.
CIRGenBuilderTy & getBuilder()
mlir::MLIRContext & getMLIRContext()
void emitAtomicInit(Expr *init, LValue dest)
LValue makeAddrLValue(Address addr, QualType ty, AlignmentSource source=AlignmentSource::Type)
void emitAtomicStore(RValue rvalue, LValue dest, bool isInit)
clang::ASTContext & getContext() const
mlir::Value emitFromMemory(mlir::Value value, clang::QualType ty)
EmitFromMemory - Change a scalar value from its memory representation to its value representation.
Address createMemTemp(QualType t, mlir::Location loc, const Twine &name="tmp", Address *alloca=nullptr, mlir::OpBuilder::InsertPoint ip={})
Create a temporary memory object of the given type, with appropriate alignmen and cast it to the defa...
void emitAggExpr(const clang::Expr *e, AggValueSlot slot)
This class organizes the cross-function state that is used while generating CIR code.
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
cir::FuncOp createRuntimeFunction(cir::FuncType ty, llvm::StringRef name, mlir::NamedAttrList extraAttrs={}, bool isLocal=false, bool assumeConvergent=false)
const cir::CIRDataLayout getDataLayout() const
const CIRGenFunctionInfo & arrangeBuiltinFunctionCall(QualType resultType, const CallArgList &args)
A builtin function is a freestanding function using the default C conventions.
cir::FuncType getFunctionType(const CIRGenFunctionInfo &info)
Get the CIR function type for.
void add(RValue rvalue, clang::QualType type)
Address getAddress() const
clang::QualType getType() const
mlir::Value getPointer() const
bool isVolatileQualified() const
This trivial value class is used to represent the result of an expression that is evaluated.
Address getAggregateAddress() const
Return the value of the address of the aggregate.
static RValue get(mlir::Value v)
static RValue getAggregate(Address addr, bool isVolatile=false)
Convert an Address to an RValue.
mlir::Value getValue() const
Return the value of this scalar value.
mlir::Value getComplexValue() const
Return the value of this complex value.
Contains the address where the return value of a function can be stored, and whether the address is v...
CharUnits - This is an opaque type for sizes expressed in character units.
llvm::Align getAsAlign() const
getAsAlign - Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit b...
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
This represents one expression.
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsBooleanCondition - Return true if this is a constant which we can fold and convert to a boo...
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
A (possibly-)qualified type.
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Encodes a location in the source.
A trivial tuple used to represent a source range.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
virtual bool hasBuiltinAtomic(uint64_t AtomicSizeInBits, uint64_t AlignmentInBits) const
Returns true if the given target supports lock-free atomic operations at the specified width and alig...
bool isPointerType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isAtomicType() const
const T * getAs() const
Member-template getAs<specific type>'.
bool isValidCIRAtomicOrderingCABI(Int value)
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
@ Address
A pointer to a ValueDecl.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
SyncScope
Defines sync scope values used internally by clang.
static bool atomicInfoGetAtomicPointer()
static bool aggValueSlotGC()
static bool opLoadStoreAtomic()
static bool opLoadStoreTbaa()
static bool opFuncExtraAttrs()
static bool atomicUseLibCall()
static bool atomicOpenMP()
static bool atomicMicrosoftVolatile()
static bool atomicSyncScopeID()
static bool atomicInfoGetAtomicAddress()
EvalResult is a struct with detailed info about an evaluated expression.
APValue Val
Val - This is the value the expression can be folded to.