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:
673 case AtomicExpr::AO__hip_atomic_compare_exchange_strong:
674 case AtomicExpr::AO__opencl_atomic_compare_exchange_strong:
676 val2, failureOrderExpr, size, order, scope);
679 case AtomicExpr::AO__c11_atomic_compare_exchange_weak:
680 case AtomicExpr::AO__hip_atomic_compare_exchange_weak:
681 case AtomicExpr::AO__opencl_atomic_compare_exchange_weak:
683 val2, failureOrderExpr, size, order, scope);
686 case AtomicExpr::AO__atomic_compare_exchange:
687 case AtomicExpr::AO__atomic_compare_exchange_n:
688 case AtomicExpr::AO__scoped_atomic_compare_exchange:
689 case AtomicExpr::AO__scoped_atomic_compare_exchange_n: {
693 failureOrderExpr, size, order, scope);
696 val1, val2, failureOrderExpr, size,
702 case AtomicExpr::AO__c11_atomic_load:
703 case AtomicExpr::AO__atomic_load_n:
704 case AtomicExpr::AO__atomic_load:
705 case AtomicExpr::AO__scoped_atomic_load_n:
706 case AtomicExpr::AO__scoped_atomic_load:
707 case AtomicExpr::AO__hip_atomic_load:
708 case AtomicExpr::AO__opencl_atomic_load: {
712 load->setAttr(
"mem_order", orderAttr);
713 load->setAttr(
"sync_scope", scopeAttr);
715 builder.
createStore(loc, load->getResult(0), dest);
719 case AtomicExpr::AO__c11_atomic_store:
720 case AtomicExpr::AO__atomic_store_n:
721 case AtomicExpr::AO__atomic_store:
722 case AtomicExpr::AO__scoped_atomic_store:
723 case AtomicExpr::AO__scoped_atomic_store_n:
724 case AtomicExpr::AO__hip_atomic_store:
725 case AtomicExpr::AO__opencl_atomic_store: {
726 cir::LoadOp loadVal1 = builder.
createLoad(loc, val1);
732 mlir::IntegerAttr{}, scopeAttr, orderAttr);
736 case AtomicExpr::AO__c11_atomic_exchange:
737 case AtomicExpr::AO__atomic_exchange_n:
738 case AtomicExpr::AO__atomic_exchange:
739 case AtomicExpr::AO__scoped_atomic_exchange_n:
740 case AtomicExpr::AO__scoped_atomic_exchange:
741 case AtomicExpr::AO__hip_atomic_exchange:
742 case AtomicExpr::AO__opencl_atomic_exchange:
743 opName = cir::AtomicXchgOp::getOperationName();
746 case AtomicExpr::AO__atomic_add_fetch:
747 case AtomicExpr::AO__scoped_atomic_add_fetch:
750 case AtomicExpr::AO__c11_atomic_fetch_add:
751 case AtomicExpr::AO__atomic_fetch_add:
752 case AtomicExpr::AO__scoped_atomic_fetch_add:
753 case AtomicExpr::AO__hip_atomic_fetch_add:
754 case AtomicExpr::AO__opencl_atomic_fetch_add:
755 handleFetchOp(cir::AtomicFetchKind::Add);
758 case AtomicExpr::AO__atomic_sub_fetch:
759 case AtomicExpr::AO__scoped_atomic_sub_fetch:
762 case AtomicExpr::AO__c11_atomic_fetch_sub:
763 case AtomicExpr::AO__atomic_fetch_sub:
764 case AtomicExpr::AO__scoped_atomic_fetch_sub:
765 case AtomicExpr::AO__hip_atomic_fetch_sub:
766 case AtomicExpr::AO__opencl_atomic_fetch_sub:
767 handleFetchOp(cir::AtomicFetchKind::Sub);
770 case AtomicExpr::AO__atomic_min_fetch:
771 case AtomicExpr::AO__scoped_atomic_min_fetch:
774 case AtomicExpr::AO__c11_atomic_fetch_min:
775 case AtomicExpr::AO__atomic_fetch_min:
776 case AtomicExpr::AO__scoped_atomic_fetch_min:
777 case AtomicExpr::AO__hip_atomic_fetch_min:
778 case AtomicExpr::AO__opencl_atomic_fetch_min:
779 handleFetchOp(cir::AtomicFetchKind::Min);
782 case AtomicExpr::AO__atomic_fetch_fminimum:
783 case AtomicExpr::AO__scoped_atomic_fetch_fminimum:
784 assert(
expr->getValueType()->isFloatingType() &&
785 "fminimum operations only support floating-point types");
786 handleFetchOp(cir::AtomicFetchKind::Minimum);
789 case AtomicExpr::AO__atomic_fetch_fminimum_num:
790 case AtomicExpr::AO__scoped_atomic_fetch_fminimum_num:
791 assert(
expr->getValueType()->isFloatingType() &&
792 "fminimum_num operations only support floating-point types");
793 handleFetchOp(cir::AtomicFetchKind::MinimumNum);
796 case AtomicExpr::AO__atomic_max_fetch:
797 case AtomicExpr::AO__scoped_atomic_max_fetch:
800 case AtomicExpr::AO__c11_atomic_fetch_max:
801 case AtomicExpr::AO__atomic_fetch_max:
802 case AtomicExpr::AO__scoped_atomic_fetch_max:
803 case AtomicExpr::AO__hip_atomic_fetch_max:
804 case AtomicExpr::AO__opencl_atomic_fetch_max:
805 handleFetchOp(cir::AtomicFetchKind::Max);
808 case AtomicExpr::AO__atomic_fetch_fmaximum:
809 case AtomicExpr::AO__scoped_atomic_fetch_fmaximum:
810 assert(
expr->getValueType()->isFloatingType() &&
811 "fmaximum operations only support floating-point types");
812 handleFetchOp(cir::AtomicFetchKind::Maximum);
815 case AtomicExpr::AO__atomic_fetch_fmaximum_num:
816 case AtomicExpr::AO__scoped_atomic_fetch_fmaximum_num:
817 assert(
expr->getValueType()->isFloatingType() &&
818 "fmaximum_num operations only support floating-point types");
819 handleFetchOp(cir::AtomicFetchKind::MaximumNum);
822 case AtomicExpr::AO__atomic_and_fetch:
823 case AtomicExpr::AO__scoped_atomic_and_fetch:
826 case AtomicExpr::AO__c11_atomic_fetch_and:
827 case AtomicExpr::AO__atomic_fetch_and:
828 case AtomicExpr::AO__scoped_atomic_fetch_and:
829 case AtomicExpr::AO__hip_atomic_fetch_and:
830 case AtomicExpr::AO__opencl_atomic_fetch_and:
831 handleFetchOp(cir::AtomicFetchKind::And);
834 case AtomicExpr::AO__atomic_or_fetch:
835 case AtomicExpr::AO__scoped_atomic_or_fetch:
838 case AtomicExpr::AO__c11_atomic_fetch_or:
839 case AtomicExpr::AO__atomic_fetch_or:
840 case AtomicExpr::AO__scoped_atomic_fetch_or:
841 case AtomicExpr::AO__hip_atomic_fetch_or:
842 case AtomicExpr::AO__opencl_atomic_fetch_or:
843 handleFetchOp(cir::AtomicFetchKind::Or);
846 case AtomicExpr::AO__atomic_xor_fetch:
847 case AtomicExpr::AO__scoped_atomic_xor_fetch:
850 case AtomicExpr::AO__c11_atomic_fetch_xor:
851 case AtomicExpr::AO__atomic_fetch_xor:
852 case AtomicExpr::AO__scoped_atomic_fetch_xor:
853 case AtomicExpr::AO__hip_atomic_fetch_xor:
854 case AtomicExpr::AO__opencl_atomic_fetch_xor:
855 handleFetchOp(cir::AtomicFetchKind::Xor);
858 case AtomicExpr::AO__atomic_nand_fetch:
859 case AtomicExpr::AO__scoped_atomic_nand_fetch:
862 case AtomicExpr::AO__c11_atomic_fetch_nand:
863 case AtomicExpr::AO__atomic_fetch_nand:
864 case AtomicExpr::AO__scoped_atomic_fetch_nand:
865 handleFetchOp(cir::AtomicFetchKind::Nand);
868 case AtomicExpr::AO__atomic_test_and_set: {
869 auto op = cir::AtomicTestAndSetOp::create(
877 case AtomicExpr::AO__atomic_clear: {
878 cir::AtomicClearOp::create(
885 case AtomicExpr::AO__atomic_fetch_uinc:
886 case AtomicExpr::AO__scoped_atomic_fetch_uinc:
887 handleFetchOp(cir::AtomicFetchKind::UIncWrap);
890 case AtomicExpr::AO__atomic_fetch_udec:
891 case AtomicExpr::AO__scoped_atomic_fetch_udec:
892 handleFetchOp(cir::AtomicFetchKind::UDecWrap);
895 case AtomicExpr::AO__opencl_atomic_init:
900 assert(!opName.empty() &&
"expected operation name to build");
901 mlir::Value loadVal1 = builder.
createLoad(loc, val1);
905 mlir::Operation *rmwOp = builder.create(loc, builder.getStringAttr(opName),
906 atomicOperands, atomicResTys);
909 rmwOp->setAttr(
"binop", fetchAttr);
910 rmwOp->setAttr(
"mem_order", orderAttr);
911 rmwOp->setAttr(
"sync_scope", scopeAttr);
912 if (
expr->isVolatile())
913 rmwOp->setAttr(
"is_volatile", builder.getUnitAttr());
914 if (fetchFirst && opName == cir::AtomicFetchOp::getOperationName())
915 rmwOp->setAttr(
"fetch_first", builder.getUnitAttr());
917 mlir::Value result = rmwOp->getResult(0);
928 return cir::SyncScopeKind::SingleThread;
930 return cir::SyncScopeKind::System;
932 return cir::SyncScopeKind::Device;
934 return cir::SyncScopeKind::Workgroup;
936 return cir::SyncScopeKind::Wavefront;
938 return cir::SyncScopeKind::Cluster;
941 return cir::SyncScopeKind::HIPSingleThread;
943 return cir::SyncScopeKind::HIPSystem;
945 return cir::SyncScopeKind::HIPAgent;
947 return cir::SyncScopeKind::HIPWorkgroup;
949 return cir::SyncScopeKind::HIPWavefront;
951 return cir::SyncScopeKind::HIPCluster;
954 return cir::SyncScopeKind::OpenCLWorkGroup;
956 return cir::SyncScopeKind::OpenCLDevice;
958 return cir::SyncScopeKind::OpenCLAllSVMDevices;
960 return cir::SyncScopeKind::OpenCLSubGroup;
963 llvm_unreachable(
"unhandled sync scope");
968 Expr *isWeakExpr,
Expr *failureOrderExpr, int64_t size,
970 const std::optional<Expr::EvalResult> &scopeConst,
971 mlir::Value scopeValue) {
972 std::unique_ptr<AtomicScopeModel> scopeModel =
expr->getScopeModel();
975 emitAtomicOp(cgf,
expr, dest, ptr, val1, val2, isWeakExpr, failureOrderExpr,
976 size, order, cir::SyncScopeKind::System);
980 if (scopeConst.has_value()) {
982 cgf,
expr->getScope()->getSourceRange(),
983 scopeModel->map(scopeConst->Val.getInt().getZExtValue()));
984 emitAtomicOp(cgf,
expr, dest, ptr, val1, val2, isWeakExpr, failureOrderExpr,
985 size, order, mappedScope);
992 mlir::Location loc = cgf.
getLoc(
expr->getSourceRange());
994 unsigned fallback = scopeModel->getFallBackValue();
996 cir::SwitchOp::create(
997 builder, loc, scopeValue,
998 [&](mlir::OpBuilder &, mlir::Location loc, mlir::OperationState &) {
999 mlir::Block *switchBlock = builder.getBlock();
1003 cgf,
expr->getScope()->getSourceRange(), scopeModel->map(fallback));
1006 failureOrderExpr, size, order, fallbackScope);
1008 builder.setInsertionPointToEnd(switchBlock);
1011 for (
unsigned scope : allScopes) {
1012 if (scope == fallback)
1016 cgf,
expr->getScope()->getSourceRange(), scopeModel->map(scope));
1018 mlir::ArrayAttr casesAttr = builder.getArrayAttr(
1019 {cir::IntAttr::get(scopeValue.getType(), scope)});
1020 mlir::OpBuilder::InsertPoint insertPoint;
1021 cir::CaseOp::create(builder, loc, casesAttr, cir::CaseOpKind::Equal,
1024 builder.restoreInsertionPoint(insertPoint);
1026 failureOrderExpr, size, order, cirScope);
1028 builder.setInsertionPointToEnd(switchBlock);
1035static std::optional<cir::MemOrder>
1045 if (oriOrder == cir::MemOrder::Consume ||
1046 oriOrder == cir::MemOrder::Acquire ||
1047 oriOrder == cir::MemOrder::AcquireRelease)
1048 return std::nullopt;
1049 }
else if (isLoad) {
1050 if (oriOrder == cir::MemOrder::Release ||
1051 oriOrder == cir::MemOrder::AcquireRelease)
1052 return std::nullopt;
1053 }
else if (isFence) {
1054 if (oriOrder == cir::MemOrder::Relaxed)
1055 return std::nullopt;
1059 if (oriOrder == cir::MemOrder::Consume)
1060 return cir::MemOrder::Acquire;
1065 CIRGenFunction &cgf, mlir::Value order,
bool isStore,
bool isLoad,
1066 bool isFence, llvm::function_ref<
void(cir::MemOrder)> emitAtomicOpFn) {
1074 cir::SwitchOp::create(
1075 builder, order.getLoc(), order,
1076 [&](mlir::OpBuilder &, mlir::Location loc, mlir::OperationState &) {
1077 mlir::Block *switchBlock = builder.getBlock();
1079 auto emitMemOrderCase = [&](llvm::ArrayRef<cir::MemOrder> caseOrders) {
1081 for (int i = 1, e = caseOrders.size(); i < e; i++)
1082 assert((getEffectiveAtomicMemOrder(caseOrders[i - 1], isStore,
1084 getEffectiveAtomicMemOrder(caseOrders[i], isStore, isLoad,
1086 "Effective memory order must be same!");
1088 if (caseOrders.empty()) {
1089 emitDefaultCaseLabel(builder, loc);
1093 emitAtomicOpFn(cir::MemOrder::Relaxed);
1094 } else if (std::optional<cir::MemOrder> actualOrder =
1095 getEffectiveAtomicMemOrder(caseOrders[0], isStore,
1098 if (!isFence && actualOrder == cir::MemOrder::Relaxed)
1103 emitMemOrderCaseLabel(builder, loc, order.getType(), caseOrders);
1104 emitAtomicOpFn(actualOrder.value());
1109 builder.createBreak(loc);
1110 builder.setInsertionPointToEnd(switchBlock);
1113 emitMemOrderCase( {});
1114 emitMemOrderCase({cir::MemOrder::Relaxed});
1115 emitMemOrderCase({cir::MemOrder::Consume, cir::MemOrder::Acquire});
1116 emitMemOrderCase({cir::MemOrder::Release});
1117 emitMemOrderCase({cir::MemOrder::AcquireRelease});
1118 emitMemOrderCase({cir::MemOrder::SequentiallyConsistent});
1125 const Expr *memOrder,
bool isStore,
bool isLoad,
bool isFence,
1126 llvm::function_ref<
void(cir::MemOrder)> emitAtomicOpFn) {
1130 uint64_t constOrder = eval.
Val.
getInt().getZExtValue();
1135 cir::MemOrder oriOrder =
static_cast<cir::MemOrder
>(constOrder);
1136 if (std::optional<cir::MemOrder> actualOrder =
1138 emitAtomicOpFn(actualOrder.value());
1155 mlir::NamedAttrList fnAttrs;
1167 uint64_t atomicTySize,
1180 auto castToGenericAddrSpace = [&](mlir::Value v,
QualType pt) {
1185 cgf.
cgm.
errorNYI(loc,
"emitLibCallForAtomicExpr: openCL");
1195 llvm::StringRef calleeName;
1197 bool hasRetTy =
false;
1198 switch (e->
getOp()) {
1199 case AtomicExpr::AO__c11_atomic_init:
1200 case AtomicExpr::AO__opencl_atomic_init:
1201 llvm_unreachable(
"Already handled!");
1208 case AtomicExpr::AO__atomic_compare_exchange:
1209 case AtomicExpr::AO__atomic_compare_exchange_n:
1210 case AtomicExpr::AO__c11_atomic_compare_exchange_weak:
1211 case AtomicExpr::AO__c11_atomic_compare_exchange_strong:
1212 case AtomicExpr::AO__hip_atomic_compare_exchange_weak:
1213 case AtomicExpr::AO__hip_atomic_compare_exchange_strong:
1214 case AtomicExpr::AO__opencl_atomic_compare_exchange_weak:
1215 case AtomicExpr::AO__opencl_atomic_compare_exchange_strong:
1216 case AtomicExpr::AO__scoped_atomic_compare_exchange:
1217 case AtomicExpr::AO__scoped_atomic_compare_exchange_n: {
1218 calleeName =
"__atomic_compare_exchange";
1235 case AtomicExpr::AO__atomic_exchange:
1236 case AtomicExpr::AO__atomic_exchange_n:
1237 case AtomicExpr::AO__c11_atomic_exchange:
1238 case AtomicExpr::AO__hip_atomic_exchange:
1239 case AtomicExpr::AO__opencl_atomic_exchange:
1240 case AtomicExpr::AO__scoped_atomic_exchange:
1241 case AtomicExpr::AO__scoped_atomic_exchange_n:
1242 calleeName =
"__atomic_exchange";
1249 case AtomicExpr::AO__atomic_store:
1250 case AtomicExpr::AO__atomic_store_n:
1251 case AtomicExpr::AO__c11_atomic_store:
1252 case AtomicExpr::AO__hip_atomic_store:
1253 case AtomicExpr::AO__opencl_atomic_store:
1254 case AtomicExpr::AO__scoped_atomic_store:
1255 case AtomicExpr::AO__scoped_atomic_store_n:
1256 calleeName =
"__atomic_store";
1265 case AtomicExpr::AO__atomic_load:
1266 case AtomicExpr::AO__atomic_load_n:
1267 case AtomicExpr::AO__c11_atomic_load:
1268 case AtomicExpr::AO__hip_atomic_load:
1269 case AtomicExpr::AO__opencl_atomic_load:
1270 case AtomicExpr::AO__scoped_atomic_load:
1271 case AtomicExpr::AO__scoped_atomic_load_n:
1272 calleeName =
"__atomic_load";
1275 case AtomicExpr::AO__atomic_add_fetch:
1276 case AtomicExpr::AO__scoped_atomic_add_fetch:
1277 case AtomicExpr::AO__atomic_fetch_add:
1278 case AtomicExpr::AO__c11_atomic_fetch_add:
1279 case AtomicExpr::AO__hip_atomic_fetch_add:
1280 case AtomicExpr::AO__opencl_atomic_fetch_add:
1281 case AtomicExpr::AO__scoped_atomic_fetch_add:
1282 case AtomicExpr::AO__atomic_and_fetch:
1283 case AtomicExpr::AO__scoped_atomic_and_fetch:
1284 case AtomicExpr::AO__atomic_fetch_and:
1285 case AtomicExpr::AO__c11_atomic_fetch_and:
1286 case AtomicExpr::AO__hip_atomic_fetch_and:
1287 case AtomicExpr::AO__opencl_atomic_fetch_and:
1288 case AtomicExpr::AO__scoped_atomic_fetch_and:
1289 case AtomicExpr::AO__atomic_or_fetch:
1290 case AtomicExpr::AO__scoped_atomic_or_fetch:
1291 case AtomicExpr::AO__atomic_fetch_or:
1292 case AtomicExpr::AO__c11_atomic_fetch_or:
1293 case AtomicExpr::AO__hip_atomic_fetch_or:
1294 case AtomicExpr::AO__opencl_atomic_fetch_or:
1295 case AtomicExpr::AO__scoped_atomic_fetch_or:
1296 case AtomicExpr::AO__atomic_sub_fetch:
1297 case AtomicExpr::AO__scoped_atomic_sub_fetch:
1298 case AtomicExpr::AO__atomic_fetch_sub:
1299 case AtomicExpr::AO__c11_atomic_fetch_sub:
1300 case AtomicExpr::AO__hip_atomic_fetch_sub:
1301 case AtomicExpr::AO__opencl_atomic_fetch_sub:
1302 case AtomicExpr::AO__scoped_atomic_fetch_sub:
1303 case AtomicExpr::AO__atomic_xor_fetch:
1304 case AtomicExpr::AO__scoped_atomic_xor_fetch:
1305 case AtomicExpr::AO__atomic_fetch_xor:
1306 case AtomicExpr::AO__c11_atomic_fetch_xor:
1307 case AtomicExpr::AO__hip_atomic_fetch_xor:
1308 case AtomicExpr::AO__opencl_atomic_fetch_xor:
1309 case AtomicExpr::AO__scoped_atomic_fetch_xor:
1310 case AtomicExpr::AO__atomic_nand_fetch:
1311 case AtomicExpr::AO__atomic_fetch_nand:
1312 case AtomicExpr::AO__c11_atomic_fetch_nand:
1313 case AtomicExpr::AO__scoped_atomic_fetch_nand:
1314 case AtomicExpr::AO__scoped_atomic_nand_fetch:
1315 case AtomicExpr::AO__atomic_min_fetch:
1316 case AtomicExpr::AO__atomic_fetch_min:
1317 case AtomicExpr::AO__c11_atomic_fetch_min:
1318 case AtomicExpr::AO__hip_atomic_fetch_min:
1319 case AtomicExpr::AO__opencl_atomic_fetch_min:
1320 case AtomicExpr::AO__scoped_atomic_fetch_min:
1321 case AtomicExpr::AO__scoped_atomic_min_fetch:
1322 case AtomicExpr::AO__atomic_max_fetch:
1323 case AtomicExpr::AO__atomic_fetch_max:
1324 case AtomicExpr::AO__c11_atomic_fetch_max:
1325 case AtomicExpr::AO__hip_atomic_fetch_max:
1326 case AtomicExpr::AO__opencl_atomic_fetch_max:
1327 case AtomicExpr::AO__scoped_atomic_fetch_max:
1328 case AtomicExpr::AO__scoped_atomic_max_fetch:
1329 case AtomicExpr::AO__scoped_atomic_fetch_uinc:
1330 case AtomicExpr::AO__scoped_atomic_fetch_udec:
1331 case AtomicExpr::AO__atomic_fetch_fmaximum:
1332 case AtomicExpr::AO__atomic_fetch_fmaximum_num:
1333 case AtomicExpr::AO__atomic_fetch_fminimum:
1334 case AtomicExpr::AO__atomic_fetch_fminimum_num:
1335 case AtomicExpr::AO__scoped_atomic_fetch_fmaximum:
1336 case AtomicExpr::AO__scoped_atomic_fetch_fmaximum_num:
1337 case AtomicExpr::AO__scoped_atomic_fetch_fminimum:
1338 case AtomicExpr::AO__scoped_atomic_fetch_fminimum_num:
1339 case AtomicExpr::AO__atomic_test_and_set:
1340 case AtomicExpr::AO__atomic_clear:
1341 case AtomicExpr::AO__atomic_fetch_uinc:
1342 case AtomicExpr::AO__atomic_fetch_udec:
1343 llvm_unreachable(
"Integral atomic operations always become atomicrmw!");
1348 cgf.
cgm.
errorNYI(loc,
"emitLibCallForAtomicExpr: openCL");
1364 cgf.
cgm.
errorNYI(loc,
"emitLibCallForAtomicExpr: openCL");
1386 memTy = ty->getValueType();
1388 Expr *isWeakExpr =
nullptr;
1389 Expr *orderFailExpr =
nullptr;
1397 if (e->
getOp() == AtomicExpr::AO__c11_atomic_init) {
1409 std::optional<Expr::EvalResult> scopeConst;
1412 scopeConst.emplace(std::move(eval));
1414 switch (e->
getOp()) {
1419 case AtomicExpr::AO__c11_atomic_init:
1420 llvm_unreachable(
"already handled above with emitAtomicInit");
1422 case AtomicExpr::AO__atomic_load_n:
1423 case AtomicExpr::AO__scoped_atomic_load_n:
1424 case AtomicExpr::AO__c11_atomic_load:
1425 case AtomicExpr::AO__opencl_atomic_load:
1426 case AtomicExpr::AO__hip_atomic_load:
1427 case AtomicExpr::AO__atomic_test_and_set:
1428 case AtomicExpr::AO__atomic_clear:
1431 case AtomicExpr::AO__atomic_load:
1432 case AtomicExpr::AO__scoped_atomic_load:
1436 case AtomicExpr::AO__atomic_store:
1437 case AtomicExpr::AO__scoped_atomic_store:
1441 case AtomicExpr::AO__atomic_exchange:
1442 case AtomicExpr::AO__scoped_atomic_exchange:
1447 case AtomicExpr::AO__atomic_compare_exchange:
1448 case AtomicExpr::AO__atomic_compare_exchange_n:
1449 case AtomicExpr::AO__c11_atomic_compare_exchange_weak:
1450 case AtomicExpr::AO__c11_atomic_compare_exchange_strong:
1451 case AtomicExpr::AO__scoped_atomic_compare_exchange:
1452 case AtomicExpr::AO__scoped_atomic_compare_exchange_n:
1453 case AtomicExpr::AO__hip_atomic_compare_exchange_strong:
1454 case AtomicExpr::AO__hip_atomic_compare_exchange_weak:
1455 case AtomicExpr::AO__opencl_atomic_compare_exchange_strong:
1456 case AtomicExpr::AO__opencl_atomic_compare_exchange_weak:
1458 if (e->
getOp() == AtomicExpr::AO__atomic_compare_exchange ||
1459 e->
getOp() == AtomicExpr::AO__scoped_atomic_compare_exchange)
1464 if (e->
getOp() == AtomicExpr::AO__atomic_compare_exchange_n ||
1465 e->
getOp() == AtomicExpr::AO__atomic_compare_exchange ||
1466 e->
getOp() == AtomicExpr::AO__scoped_atomic_compare_exchange_n ||
1467 e->
getOp() == AtomicExpr::AO__scoped_atomic_compare_exchange)
1471 case AtomicExpr::AO__c11_atomic_fetch_add:
1472 case AtomicExpr::AO__c11_atomic_fetch_sub:
1483 mlir::Value scale = builder.getConstInt(loc, val1Scalar.getType(),
1485 val1Scalar = builder.createMul(loc, val1Scalar, scale);
1491 case AtomicExpr::AO__atomic_fetch_add:
1492 case AtomicExpr::AO__atomic_fetch_sub:
1493 case AtomicExpr::AO__atomic_add_fetch:
1494 case AtomicExpr::AO__atomic_sub_fetch:
1504 case AtomicExpr::AO__atomic_fetch_max:
1505 case AtomicExpr::AO__atomic_fetch_min:
1506 case AtomicExpr::AO__atomic_max_fetch:
1507 case AtomicExpr::AO__atomic_min_fetch:
1508 case AtomicExpr::AO__c11_atomic_fetch_max:
1509 case AtomicExpr::AO__c11_atomic_fetch_min:
1510 case AtomicExpr::AO__scoped_atomic_fetch_add:
1511 case AtomicExpr::AO__scoped_atomic_fetch_max:
1512 case AtomicExpr::AO__scoped_atomic_fetch_min:
1513 case AtomicExpr::AO__scoped_atomic_fetch_sub:
1514 case AtomicExpr::AO__scoped_atomic_fetch_fminimum:
1515 case AtomicExpr::AO__scoped_atomic_fetch_fmaximum:
1516 case AtomicExpr::AO__scoped_atomic_fetch_fminimum_num:
1517 case AtomicExpr::AO__scoped_atomic_fetch_fmaximum_num:
1518 case AtomicExpr::AO__scoped_atomic_add_fetch:
1519 case AtomicExpr::AO__scoped_atomic_max_fetch:
1520 case AtomicExpr::AO__scoped_atomic_min_fetch:
1521 case AtomicExpr::AO__scoped_atomic_sub_fetch:
1524 case AtomicExpr::AO__atomic_fetch_and:
1525 case AtomicExpr::AO__atomic_fetch_nand:
1526 case AtomicExpr::AO__atomic_fetch_or:
1527 case AtomicExpr::AO__atomic_fetch_xor:
1528 case AtomicExpr::AO__atomic_and_fetch:
1529 case AtomicExpr::AO__atomic_nand_fetch:
1530 case AtomicExpr::AO__atomic_or_fetch:
1531 case AtomicExpr::AO__atomic_xor_fetch:
1532 case AtomicExpr::AO__atomic_exchange_n:
1533 case AtomicExpr::AO__atomic_store_n:
1534 case AtomicExpr::AO__c11_atomic_fetch_and:
1535 case AtomicExpr::AO__c11_atomic_fetch_nand:
1536 case AtomicExpr::AO__c11_atomic_fetch_or:
1537 case AtomicExpr::AO__c11_atomic_fetch_xor:
1538 case AtomicExpr::AO__c11_atomic_exchange:
1539 case AtomicExpr::AO__c11_atomic_store:
1540 case AtomicExpr::AO__scoped_atomic_fetch_and:
1541 case AtomicExpr::AO__scoped_atomic_fetch_nand:
1542 case AtomicExpr::AO__scoped_atomic_fetch_or:
1543 case AtomicExpr::AO__scoped_atomic_fetch_xor:
1544 case AtomicExpr::AO__scoped_atomic_and_fetch:
1545 case AtomicExpr::AO__scoped_atomic_nand_fetch:
1546 case AtomicExpr::AO__scoped_atomic_or_fetch:
1547 case AtomicExpr::AO__scoped_atomic_xor_fetch:
1548 case AtomicExpr::AO__scoped_atomic_store_n:
1549 case AtomicExpr::AO__scoped_atomic_exchange_n:
1550 case AtomicExpr::AO__atomic_fetch_uinc:
1551 case AtomicExpr::AO__atomic_fetch_udec:
1552 case AtomicExpr::AO__scoped_atomic_fetch_uinc:
1553 case AtomicExpr::AO__scoped_atomic_fetch_udec:
1554 case AtomicExpr::AO__atomic_fetch_fminimum:
1555 case AtomicExpr::AO__atomic_fetch_fmaximum:
1556 case AtomicExpr::AO__atomic_fetch_fminimum_num:
1557 case AtomicExpr::AO__atomic_fetch_fmaximum_num:
1558 case AtomicExpr::AO__hip_atomic_exchange:
1559 case AtomicExpr::AO__hip_atomic_store:
1560 case AtomicExpr::AO__hip_atomic_fetch_add:
1561 case AtomicExpr::AO__hip_atomic_fetch_sub:
1562 case AtomicExpr::AO__hip_atomic_fetch_min:
1563 case AtomicExpr::AO__hip_atomic_fetch_max:
1564 case AtomicExpr::AO__hip_atomic_fetch_and:
1565 case AtomicExpr::AO__hip_atomic_fetch_or:
1566 case AtomicExpr::AO__hip_atomic_fetch_xor:
1567 case AtomicExpr::AO__opencl_atomic_exchange:
1568 case AtomicExpr::AO__opencl_atomic_store:
1569 case AtomicExpr::AO__opencl_atomic_fetch_add:
1570 case AtomicExpr::AO__opencl_atomic_fetch_sub:
1571 case AtomicExpr::AO__opencl_atomic_fetch_min:
1572 case AtomicExpr::AO__opencl_atomic_fetch_max:
1573 case AtomicExpr::AO__opencl_atomic_fetch_and:
1574 case AtomicExpr::AO__opencl_atomic_fetch_or:
1575 case AtomicExpr::AO__opencl_atomic_fetch_xor:
1582 bool shouldCastToIntPtrTy =
1590 AtomicInfo atomics(*
this, atomicValue, loc);
1592 if (shouldCastToIntPtrTy) {
1593 ptr = atomics.castToAtomicIntPointer(ptr);
1595 val1 = atomics.convertToAtomicIntPointer(val1, loc);
1597 val2 = atomics.convertToAtomicIntPointer(val2, loc);
1600 if (shouldCastToIntPtrTy)
1601 dest = atomics.castToAtomicIntPointer(dest);
1604 }
else if (e->
getOp() == AtomicExpr::AO__atomic_test_and_set) {
1607 dest = atomics.createTempAlloca();
1608 if (shouldCastToIntPtrTy)
1609 dest = atomics.castToAtomicIntPointer(dest);
1612 bool powerOf2Size = (size & (size - 1)) == 0;
1613 bool useLibCall = !powerOf2Size || (size > 16);
1628 bool isStore = e->
getOp() == AtomicExpr::AO__c11_atomic_store ||
1629 e->
getOp() == AtomicExpr::AO__opencl_atomic_store ||
1630 e->
getOp() == AtomicExpr::AO__hip_atomic_store ||
1631 e->
getOp() == AtomicExpr::AO__atomic_store ||
1632 e->
getOp() == AtomicExpr::AO__atomic_store_n ||
1633 e->
getOp() == AtomicExpr::AO__scoped_atomic_store ||
1634 e->
getOp() == AtomicExpr::AO__scoped_atomic_store_n ||
1635 e->
getOp() == AtomicExpr::AO__atomic_clear;
1636 bool isLoad = e->
getOp() == AtomicExpr::AO__c11_atomic_load ||
1637 e->
getOp() == AtomicExpr::AO__opencl_atomic_load ||
1638 e->
getOp() == AtomicExpr::AO__hip_atomic_load ||
1639 e->
getOp() == AtomicExpr::AO__atomic_load ||
1640 e->
getOp() == AtomicExpr::AO__atomic_load_n ||
1641 e->
getOp() == AtomicExpr::AO__scoped_atomic_load ||
1642 e->
getOp() == AtomicExpr::AO__scoped_atomic_load_n;
1644 auto emitAtomicOpCallBackFn = [&](cir::MemOrder memOrder) {
1645 emitAtomicOp(*
this, e, dest, ptr, val1, val2, isWeakExpr, orderFailExpr,
1646 size, memOrder, scopeConst, scope);
1649 emitAtomicOpCallBackFn);
1662 return emitAtomicLoad(lvalue, loc, cir::MemOrder::SequentiallyConsistent,
1669 cir::MemOrder order,
bool isVolatile,
1671 AtomicInfo info(*
this, lvalue,
getLoc(loc));
1672 return info.emitAtomicLoad(slot, loc,
true, order, isVolatile);
1677 auto order = cir::MemOrder::SequentiallyConsistent;
1690 cir::MemOrder order,
bool isVolatile,
1694 mlir::Location loc = dest.
getPointer().getLoc();
1699 AtomicInfo atomics(*
this, dest, loc);
1700 LValue lvalue = atomics.getAtomicLValue();
1705 atomics.emitCopyIntoMemory(rvalue);
1710 if (atomics.shouldUseLibCall()) {
1712 cgm.errorNYI(loc,
"emitAtomicStore: atomic store with library call");
1717 mlir::Value valueToStore = atomics.convertRValueToInt(rvalue, loc);
1720 Address addr = atomics.getAtomicAddress();
1721 if (mlir::Value value = atomics.getScalarRValValueOrNull(rvalue)) {
1723 addr = atomics.castToAtomicIntPointer(addr);
1728 cir::StoreOp store = builder.createStore(loc, valueToStore, addr);
1733 store.setMemOrder(order);
1738 store.setIsVolatile(
true);
1744 cgm.errorNYI(loc,
"emitAtomicStore: non-simple atomic lvalue");
1751 switch (atomics.getEvaluationKind()) {
1767 bool zeroed =
false;
1769 zeroed = atomics.emitMemSetZeroIfNecessary();
1770 dest = atomics.projectValue();
1785 llvm_unreachable(
"bad evaluation kind");
static bool shouldCastToInt(mlir::Type valueTy, bool cmpxchg)
Return true if.
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 RValue emitLibCallForAtomicExpr(CIRGenFunction &cgf, AtomicExpr *e, Address atomicPtr, Address dest, Address val1, Address val2, uint64_t atomicTySize, QualType resultTy)
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::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::MemCpyOp createMemCpy(mlir::Location loc, Address dst, Address src, mlir::Value len)
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.
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)
RValue emitCall(const CIRGenFunctionInfo &funcInfo, const CIRGenCallee &callee, ReturnValueSlot returnValue, const CallArgList &args, cir::CIRCallOpInterface *callOp, bool isMustTail, SourceRange clangLoc)
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.
Top level wrappers for InstallAPI frontend operations.
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.