Skip to content

Commit

Permalink
[CIR][CIRGen][NFCI] Atomics: more skeleton and helpers for c11 init
Browse files Browse the repository at this point in the history
Testcase introduced in previous commit still commented, with the
work in this patch we just move the assertion further.
  • Loading branch information
bcardosolopes authored and lanza committed Nov 3, 2024
1 parent 2db81f1 commit a8fa812
Show file tree
Hide file tree
Showing 4 changed files with 187 additions and 7 deletions.
2 changes: 2 additions & 0 deletions clang/include/clang/CIR/Dialect/IR/CIRTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,8 @@ class StructType
void computeSizeAndAlignment(const DataLayout &dataLayout) const;
};

bool isAnyFloatingPointType(mlir::Type t);

} // namespace cir
} // namespace mlir

Expand Down
182 changes: 175 additions & 7 deletions clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ class AtomicInfo {

mlir::Value getAtomicSizeValue() const { llvm_unreachable("NYI"); }

mlir::Value getScalarRValValueOrNull(RValue RVal) const;

/// Cast the given pointer to an integer pointer suitable for atomic
/// operations if the source.
Address castToAtomicIntPointer(Address Addr) const;
Expand All @@ -160,7 +162,7 @@ class AtomicInfo {
SourceLocation loc, bool AsValue) const;

/// Converts a rvalue to integer value.
mlir::Value convertRValueToInt(RValue RVal) const;
mlir::Value convertRValueToInt(RValue RVal, bool CmpXchg = false) const;

RValue ConvertIntToValueOrAtomic(mlir::Value IntVal, AggValueSlot ResultSlot,
SourceLocation Loc, bool AsValue) const;
Expand Down Expand Up @@ -218,7 +220,7 @@ class AtomicInfo {
Address CreateTempAlloca() const;

private:
bool requiresMemSetZero(llvm::Type *type) const;
bool requiresMemSetZero(mlir::Type ty) const;

/// Emits atomic load as a libcall.
void EmitAtomicLoadLibcall(mlir::Value AddForLoaded, llvm::AtomicOrdering AO,
Expand Down Expand Up @@ -268,6 +270,36 @@ static Address buildValToTemp(CIRGenFunction &CGF, Expr *E) {
return DeclPtr;
}

/// Does a store of the given IR type modify the full expected width?
static bool isFullSizeType(CIRGenModule &CGM, mlir::Type ty,
uint64_t expectedSize) {
return (CGM.getDataLayout().getTypeStoreSize(ty) * 8 == expectedSize);
}

/// Does the atomic type require memsetting to zero before initialization?
///
/// The IR type is provided as a way of making certain queries faster.
bool AtomicInfo::requiresMemSetZero(mlir::Type ty) const {
// If the atomic type has size padding, we definitely need a memset.
if (hasPadding())
return true;

// Otherwise, do some simple heuristics to try to avoid it:
switch (getEvaluationKind()) {
// For scalars and complexes, check whether the store size of the
// type uses the full size.
case TEK_Scalar:
return !isFullSizeType(CGF.CGM, ty, AtomicSizeInBits);
case TEK_Complex:
llvm_unreachable("NYI");

// Padding in structs has an undefined bit pattern. User beware.
case TEK_Aggregate:
return false;
}
llvm_unreachable("bad evaluation kind");
}

Address AtomicInfo::castToAtomicIntPointer(Address addr) const {
auto intTy = addr.getElementType().dyn_cast<mlir::cir::IntType>();
// Don't bother with int casts if the integer size is the same.
Expand Down Expand Up @@ -682,7 +714,9 @@ RValue CIRGenFunction::buildAtomicExpr(AtomicExpr *E) {

if (E->getOp() == AtomicExpr::AO__c11_atomic_init ||
E->getOp() == AtomicExpr::AO__opencl_atomic_init) {
llvm_unreachable("NYI");
LValue lvalue = makeAddrLValue(Ptr, AtomicTy);
buildAtomicInit(E->getVal1(), lvalue);
return RValue::get(nullptr);
}

auto TInfo = getContext().getTypeInfoInChars(AtomicTy);
Expand Down Expand Up @@ -1113,21 +1147,105 @@ void CIRGenFunction::buildAtomicStore(RValue rvalue, LValue lvalue,
return buildAtomicStore(rvalue, lvalue, MO, IsVolatile, isInit);
}

/// Return true if \param ValTy is a type that should be casted to integer
/// around the atomic memory operation. If \param CmpXchg is true, then the
/// cast of a floating point type is made as that instruction can not have
/// floating point operands. TODO: Allow compare-and-exchange and FP - see
/// comment in CIRGenAtomicExpandPass.cpp.
static bool shouldCastToInt(mlir::Type ValTy, bool CmpXchg) {
if (mlir::cir::isAnyFloatingPointType(ValTy))
return isa<mlir::cir::FP80Type>(ValTy) || CmpXchg;
return !isa<mlir::cir::IntType>(ValTy) && !isa<mlir::cir::PointerType>(ValTy);
}

mlir::Value AtomicInfo::getScalarRValValueOrNull(RValue RVal) const {
if (RVal.isScalar() && (!hasPadding() || !LVal.isSimple()))
return RVal.getScalarVal();
return nullptr;
}

/// Materialize an r-value into memory for the purposes of storing it
/// to an atomic type.
Address AtomicInfo::materializeRValue(RValue rvalue) const {
// Aggregate r-values are already in memory, and EmitAtomicStore
// requires them to be values of the atomic type.
if (rvalue.isAggregate())
return rvalue.getAggregateAddress();

// Otherwise, make a temporary and materialize into it.
LValue TempLV = CGF.makeAddrLValue(CreateTempAlloca(), getAtomicType());
AtomicInfo Atomics(CGF, TempLV, TempLV.getAddress().getPointer().getLoc());
Atomics.emitCopyIntoMemory(rvalue);
return TempLV.getAddress();
}

bool AtomicInfo::emitMemSetZeroIfNecessary() const {
assert(LVal.isSimple());
Address addr = LVal.getAddress();
if (!requiresMemSetZero(addr.getElementType()))
return false;

llvm_unreachable("NYI");
}

/// Copy an r-value into memory as part of storing to an atomic type.
/// This needs to create a bit-pattern suitable for atomic operations.
void AtomicInfo::emitCopyIntoMemory(RValue rvalue) const {
assert(LVal.isSimple());
// If we have an r-value, the rvalue should be of the atomic type,
// which means that the caller is responsible for having zeroed
// any padding. Just do an aggregate copy of that type.
if (rvalue.isAggregate()) {
llvm_unreachable("NYI");
return;
}

// Okay, otherwise we're copying stuff.

// Zero out the buffer if necessary.
emitMemSetZeroIfNecessary();

// Drill past the padding if present.
llvm_unreachable("NYI");

// Okay, store the rvalue in.
if (rvalue.isScalar()) {
llvm_unreachable("NYI");
} else {
llvm_unreachable("NYI");
}
}

mlir::Value AtomicInfo::convertRValueToInt(RValue RVal, bool CmpXchg) const {
// If we've got a scalar value of the right size, try to avoid going
// through memory. Floats get casted if needed by AtomicExpandPass.
if (auto Value = getScalarRValValueOrNull(RVal)) {
if (!shouldCastToInt(Value.getType(), CmpXchg)) {
return CGF.buildToMemory(Value, ValueTy);
} else {
llvm_unreachable("NYI");
}
}

llvm_unreachable("NYI");
}

/// Emit a store to an l-value of atomic type.
///
/// Note that the r-value is expected to be an r-value *of the atomic
/// type*; this means that for aggregate r-values, it should include
/// storage for any padding that was necessary.
void CIRGenFunction::buildAtomicStore(RValue rvalue, LValue dest,
mlir::cir::MemOrder AO, bool IsVolatile,
mlir::cir::MemOrder MO, bool IsVolatile,
bool isInit) {
// If this is an aggregate r-value, it should agree in type except
// maybe for address-space qualification.
auto loc = dest.getPointer().getLoc();
assert(!rvalue.isAggregate() ||
rvalue.getAggregateAddress().getElementType() ==
dest.getAddress().getElementType());

AtomicInfo atomics(*this, dest, dest.getPointer().getLoc());
AtomicInfo atomics(*this, dest, loc);
LValue LVal = atomics.getAtomicLValue();

// If this is an initialization, just put the value there normally.
Expand All @@ -1142,9 +1260,59 @@ void CIRGenFunction::buildAtomicStore(RValue rvalue, LValue dest,
llvm_unreachable("NYI");
}

llvm_unreachable("NYI");
// Okay, we're doing this natively.
auto ValToStore = atomics.convertRValueToInt(rvalue);

// Do the atomic store.
Address Addr = atomics.getAtomicAddress();
if (auto Value = atomics.getScalarRValValueOrNull(rvalue))
if (shouldCastToInt(Value.getType(), /*CmpXchg=*/false)) {
Addr = atomics.castToAtomicIntPointer(Addr);
ValToStore = builder.createIntCast(ValToStore, Addr.getElementType());
}
auto store = builder.createStore(loc, ValToStore, Addr);

if (MO == mlir::cir::MemOrder::Acquire)
MO = mlir::cir::MemOrder::Relaxed; // Monotonic
else if (MO == mlir::cir::MemOrder::AcquireRelease)
MO = mlir::cir::MemOrder::Release;
// Initializations don't need to be atomic.
if (!isInit)
store.setMemOrder(MO);

// Other decoration.
if (IsVolatile)
store.setIsVolatile(true);

// DecorateInstructionWithTBAA
assert(!UnimplementedFeature::tbaa());
return;
}

llvm_unreachable("NYI");
}
}

void CIRGenFunction::buildAtomicInit(Expr *init, LValue dest) {
AtomicInfo atomics(*this, dest, getLoc(init->getSourceRange()));

switch (atomics.getEvaluationKind()) {
case TEK_Scalar: {
mlir::Value value = buildScalarExpr(init);
atomics.emitCopyIntoMemory(RValue::get(value));
return;
}

case TEK_Complex: {
llvm_unreachable("NYI");
return;
}

case TEK_Aggregate: {
// Fix up the destination if the initializer isn't an expression
// of atomic type.
llvm_unreachable("NYI");
return;
}
}
llvm_unreachable("bad evaluation kind");
}
1 change: 1 addition & 0 deletions clang/lib/CIR/CodeGen/CIRGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -1513,6 +1513,7 @@ class CIRGenFunction : public CIRGenTypeCache {
void buildAtomicStore(RValue rvalue, LValue lvalue, bool isInit);
void buildAtomicStore(RValue rvalue, LValue lvalue, mlir::cir::MemOrder MO,
bool IsVolatile, bool isInit);
void buildAtomicInit(Expr *init, LValue dest);

/// Return the address of a local variable.
Address GetAddrOfLocalVar(const clang::VarDecl *VD) {
Expand Down
9 changes: 9 additions & 0 deletions clang/lib/CIR/Dialect/IR/CIRTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -752,6 +752,15 @@ LongDoubleType::verify(function_ref<InFlightDiagnostic()> emitError,
return success();
}

//===----------------------------------------------------------------------===//
// Floating-point type helpers
//===----------------------------------------------------------------------===//

bool mlir::cir::isAnyFloatingPointType(mlir::Type t) {
return isa<mlir::cir::SingleType, mlir::cir::DoubleType,
mlir::cir::LongDoubleType, mlir::cir::FP80Type>(t);
}

//===----------------------------------------------------------------------===//
// FuncType Definitions
//===----------------------------------------------------------------------===//
Expand Down

0 comments on commit a8fa812

Please sign in to comment.