================
@@ -63,25 +63,89 @@ static RValue emitBuiltinBitOp(CIRGenFunction &cgf, const
CallExpr *e,
static void emitAtomicFenceOp(CIRGenFunction &cgf, const CallExpr *expr,
cir::SyncScopeKind syncScope) {
CIRGenBuilderTy &builder = cgf.getBuilder();
- mlir::Value orderingVal = cgf.emitScalarExpr(expr->getArg(0));
-
- auto constOrdering = orderingVal.getDefiningOp<cir::ConstantOp>();
-
- if (!constOrdering) {
- // TODO(cir): Emit code to switch on `orderingVal`,
- // and creating the fence op for valid values.
- cgf.cgm.errorNYI("Variable atomic fence ordering");
+ mlir::Location loc = cgf.getLoc(expr->getSourceRange());
+
+ // Convert the memory order specified by user to effective one:
+ // Relaxed -> std::nullopt
+ // Consume/Acquire -> Acquire
+ // Release -> Release
+ // AcquireRelease -> AcquireRelease
+ // SequentiallyConsistent -> SequentiallyConsistent
+ auto getEffectiveMemOrder =
+ [](cir::MemOrder oriOrder) -> std::optional<cir::MemOrder> {
+ if (oriOrder == cir::MemOrder::Relaxed)
+ return std::nullopt;
+ else if (oriOrder == cir::MemOrder::Consume ||
+ oriOrder == cir::MemOrder::Acquire)
+ return cir::MemOrder::Acquire;
+ else
+ return oriOrder;
+ };
+
+ // Handle constant memory ordering.
+ Expr::EvalResult eval;
+ if (expr->getArg(0)->EvaluateAsInt(eval, cgf.getContext())) {
+ uint64_t constOrder = eval.Val.getInt().getZExtValue();
+ // Not emit anything if it's an invalid constant.
+ if (!cir::isValidCIRAtomicOrderingCABI(constOrder))
+ return;
+ cir::MemOrder caseOrder = static_cast<cir::MemOrder>(constOrder);
+ if (std::optional<cir::MemOrder> order = getEffectiveMemOrder(caseOrder))
+ cir::AtomicFenceOp::create(
+ builder, loc, order.value(),
+ cir::SyncScopeKindAttr::get(&cgf.getMLIRContext(), syncScope));
return;
}
- auto constOrderingAttr = constOrdering.getValueAttr<cir::IntAttr>();
- assert(constOrderingAttr && "Expected integer constant for ordering");
-
- auto ordering = static_cast<cir::MemOrder>(constOrderingAttr.getUInt());
-
- cir::AtomicFenceOp::create(
- builder, cgf.getLoc(expr->getSourceRange()), ordering,
- cir::SyncScopeKindAttr::get(&cgf.getMLIRContext(), syncScope));
+ // Otherwise, handle variable memory ordering. Emit `SwitchOp` to convert
+ // dynamic value to static value.
+ mlir::Value varOrder = cgf.emitScalarExpr(expr->getArg(0));
+ cir::SwitchOp::create(
----------------
Luhaocong wrote:
Yes, of course! But it looks like a challenge that may require modifying a
large amount of code, should I merge these code in this PR or a separate NFC PR
?
https://github.com/llvm/llvm-project/pull/172455
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits