Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit 54a5d84

Browse files
committed
[OPENMP] CodeGen for "omp atomic read [seq_cst]" directive.
"omp atomic read [seq_cst]" accepts expressions "v=x;". In this patch we perform an atomic load of "x" (using builtin atomic loading instructions or a call to "atomic_load()" for simple lvalues and "kmpc_atomic_start();load <x>;kmpc_atomic_end();" for other lvalues), convert the result of loading to type of "v" (using EmitScalarConversion() for simple types and EmitComplexToScalarConversion() for conversions from complex to scalar) and then store the result in "v".) Differential Revision: http://reviews.llvm.org/D6431 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@226788 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent f8e0645 commit 54a5d84

File tree

3 files changed

+603
-74
lines changed

3 files changed

+603
-74
lines changed

lib/CodeGen/CGAtomic.cpp

Lines changed: 151 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#include "CodeGenFunction.h"
1515
#include "CGCall.h"
16+
#include "CGRecordLayout.h"
1617
#include "CodeGenModule.h"
1718
#include "clang/AST/ASTContext.h"
1819
#include "clang/CodeGen/CGFunctionInfo.h"
@@ -36,34 +37,70 @@ namespace {
3637
CharUnits LValueAlign;
3738
TypeEvaluationKind EvaluationKind;
3839
bool UseLibcall;
40+
LValue LVal;
41+
CGBitFieldInfo BFI;
3942
public:
40-
AtomicInfo(CodeGenFunction &CGF, LValue &lvalue) : CGF(CGF) {
41-
assert(lvalue.isSimple());
42-
43-
AtomicTy = lvalue.getType();
44-
ValueTy = AtomicTy->castAs<AtomicType>()->getValueType();
45-
EvaluationKind = CGF.getEvaluationKind(ValueTy);
46-
43+
AtomicInfo(CodeGenFunction &CGF, LValue &lvalue)
44+
: CGF(CGF), AtomicSizeInBits(0), ValueSizeInBits(0),
45+
EvaluationKind(TEK_Scalar), UseLibcall(true) {
46+
assert(!lvalue.isGlobalReg());
4747
ASTContext &C = CGF.getContext();
48-
49-
uint64_t ValueAlignInBits;
50-
uint64_t AtomicAlignInBits;
51-
TypeInfo ValueTI = C.getTypeInfo(ValueTy);
52-
ValueSizeInBits = ValueTI.Width;
53-
ValueAlignInBits = ValueTI.Align;
54-
55-
TypeInfo AtomicTI = C.getTypeInfo(AtomicTy);
56-
AtomicSizeInBits = AtomicTI.Width;
57-
AtomicAlignInBits = AtomicTI.Align;
58-
59-
assert(ValueSizeInBits <= AtomicSizeInBits);
60-
assert(ValueAlignInBits <= AtomicAlignInBits);
61-
62-
AtomicAlign = C.toCharUnitsFromBits(AtomicAlignInBits);
63-
ValueAlign = C.toCharUnitsFromBits(ValueAlignInBits);
64-
if (lvalue.getAlignment().isZero())
65-
lvalue.setAlignment(AtomicAlign);
66-
48+
if (lvalue.isSimple()) {
49+
AtomicTy = lvalue.getType();
50+
if (auto *ATy = AtomicTy->getAs<AtomicType>())
51+
ValueTy = ATy->getValueType();
52+
else
53+
ValueTy = AtomicTy;
54+
EvaluationKind = CGF.getEvaluationKind(ValueTy);
55+
56+
uint64_t ValueAlignInBits;
57+
uint64_t AtomicAlignInBits;
58+
TypeInfo ValueTI = C.getTypeInfo(ValueTy);
59+
ValueSizeInBits = ValueTI.Width;
60+
ValueAlignInBits = ValueTI.Align;
61+
62+
TypeInfo AtomicTI = C.getTypeInfo(AtomicTy);
63+
AtomicSizeInBits = AtomicTI.Width;
64+
AtomicAlignInBits = AtomicTI.Align;
65+
66+
assert(ValueSizeInBits <= AtomicSizeInBits);
67+
assert(ValueAlignInBits <= AtomicAlignInBits);
68+
69+
AtomicAlign = C.toCharUnitsFromBits(AtomicAlignInBits);
70+
ValueAlign = C.toCharUnitsFromBits(ValueAlignInBits);
71+
if (lvalue.getAlignment().isZero())
72+
lvalue.setAlignment(AtomicAlign);
73+
74+
LVal = lvalue;
75+
} else if (lvalue.isBitField()) {
76+
auto &OrigBFI = lvalue.getBitFieldInfo();
77+
auto Offset = OrigBFI.Offset % C.toBits(lvalue.getAlignment());
78+
AtomicSizeInBits = C.toBits(
79+
C.toCharUnitsFromBits(Offset + OrigBFI.Size + C.getCharWidth() - 1)
80+
.RoundUpToAlignment(lvalue.getAlignment()));
81+
auto VoidPtrAddr = CGF.EmitCastToVoidPtr(lvalue.getBitFieldAddr());
82+
auto OffsetInChars =
83+
(C.toCharUnitsFromBits(OrigBFI.Offset) / lvalue.getAlignment()) *
84+
lvalue.getAlignment();
85+
VoidPtrAddr = CGF.Builder.CreateConstGEP1_64(
86+
VoidPtrAddr, OffsetInChars.getQuantity());
87+
auto Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
88+
VoidPtrAddr,
89+
CGF.Builder.getIntNTy(AtomicSizeInBits)->getPointerTo(),
90+
"atomic_bitfield_base");
91+
BFI = OrigBFI;
92+
BFI.Offset = Offset;
93+
BFI.StorageSize = AtomicSizeInBits;
94+
LVal = LValue::MakeBitfield(Addr, BFI, lvalue.getType(),
95+
lvalue.getAlignment());
96+
} else if (lvalue.isVectorElt()) {
97+
AtomicSizeInBits = C.getTypeSize(lvalue.getType());
98+
LVal = lvalue;
99+
} else {
100+
assert(lvalue.isExtVectorElt());
101+
AtomicSizeInBits = C.getTypeSize(lvalue.getType());
102+
LVal = lvalue;
103+
}
67104
UseLibcall = !C.getTargetInfo().hasBuiltinAtomic(
68105
AtomicSizeInBits, C.toBits(lvalue.getAlignment()));
69106
}
@@ -76,6 +113,7 @@ namespace {
76113
uint64_t getValueSizeInBits() const { return ValueSizeInBits; }
77114
TypeEvaluationKind getEvaluationKind() const { return EvaluationKind; }
78115
bool shouldUseLibcall() const { return UseLibcall; }
116+
const LValue &getAtomicLValue() const { return LVal; }
79117

80118
/// Is the atomic size larger than the underlying value type?
81119
///
@@ -87,7 +125,7 @@ namespace {
87125
return (ValueSizeInBits != AtomicSizeInBits);
88126
}
89127

90-
bool emitMemSetZeroIfNecessary(LValue dest) const;
128+
bool emitMemSetZeroIfNecessary() const;
91129

92130
llvm::Value *getAtomicSizeValue() const {
93131
CharUnits size = CGF.getContext().toCharUnitsFromBits(AtomicSizeInBits);
@@ -110,16 +148,17 @@ namespace {
110148
SourceLocation Loc) const;
111149

112150
/// Copy an atomic r-value into atomic-layout memory.
113-
void emitCopyIntoMemory(RValue rvalue, LValue lvalue) const;
151+
void emitCopyIntoMemory(RValue rvalue) const;
114152

115153
/// Project an l-value down to the value field.
116-
LValue projectValue(LValue lvalue) const {
117-
llvm::Value *addr = lvalue.getAddress();
154+
LValue projectValue() const {
155+
assert(LVal.isSimple());
156+
llvm::Value *addr = LVal.getAddress();
118157
if (hasPadding())
119158
addr = CGF.Builder.CreateStructGEP(addr, 0);
120159

121-
return LValue::MakeAddr(addr, getValueType(), lvalue.getAlignment(),
122-
CGF.getContext(), lvalue.getTBAAInfo());
160+
return LValue::MakeAddr(addr, getValueType(), LVal.getAlignment(),
161+
CGF.getContext(), LVal.getTBAAInfo());
123162
}
124163

125164
/// Materialize an atomic r-value in atomic-layout memory.
@@ -172,14 +211,15 @@ bool AtomicInfo::requiresMemSetZero(llvm::Type *type) const {
172211
llvm_unreachable("bad evaluation kind");
173212
}
174213

175-
bool AtomicInfo::emitMemSetZeroIfNecessary(LValue dest) const {
176-
llvm::Value *addr = dest.getAddress();
214+
bool AtomicInfo::emitMemSetZeroIfNecessary() const {
215+
assert(LVal.isSimple());
216+
llvm::Value *addr = LVal.getAddress();
177217
if (!requiresMemSetZero(addr->getType()->getPointerElementType()))
178218
return false;
179219

180220
CGF.Builder.CreateMemSet(addr, llvm::ConstantInt::get(CGF.Int8Ty, 0),
181221
AtomicSizeInBits / 8,
182-
dest.getAlignment().getQuantity());
222+
LVal.getAlignment().getQuantity());
183223
return true;
184224
}
185225

@@ -902,21 +942,34 @@ llvm::Value *AtomicInfo::emitCastToAtomicIntPointer(llvm::Value *addr) const {
902942
RValue AtomicInfo::convertTempToRValue(llvm::Value *addr,
903943
AggValueSlot resultSlot,
904944
SourceLocation loc) const {
905-
if (EvaluationKind == TEK_Aggregate)
906-
return resultSlot.asRValue();
907-
908-
// Drill into the padding structure if we have one.
909-
if (hasPadding())
910-
addr = CGF.Builder.CreateStructGEP(addr, 0);
911-
912-
// Otherwise, just convert the temporary to an r-value using the
913-
// normal conversion routine.
914-
return CGF.convertTempToRValue(addr, getValueType(), loc);
945+
if (LVal.isSimple()) {
946+
if (EvaluationKind == TEK_Aggregate)
947+
return resultSlot.asRValue();
948+
949+
// Drill into the padding structure if we have one.
950+
if (hasPadding())
951+
addr = CGF.Builder.CreateStructGEP(addr, 0);
952+
953+
// Otherwise, just convert the temporary to an r-value using the
954+
// normal conversion routine.
955+
return CGF.convertTempToRValue(addr, getValueType(), loc);
956+
} else if (LVal.isBitField())
957+
return CGF.EmitLoadOfBitfieldLValue(LValue::MakeBitfield(
958+
addr, LVal.getBitFieldInfo(), LVal.getType(), LVal.getAlignment()));
959+
else if (LVal.isVectorElt())
960+
return CGF.EmitLoadOfLValue(LValue::MakeVectorElt(addr, LVal.getVectorIdx(),
961+
LVal.getType(),
962+
LVal.getAlignment()),
963+
loc);
964+
assert(LVal.isExtVectorElt());
965+
return CGF.EmitLoadOfExtVectorElementLValue(LValue::MakeExtVectorElt(
966+
addr, LVal.getExtVectorElts(), LVal.getType(), LVal.getAlignment()));
915967
}
916968

917969
RValue AtomicInfo::convertIntToValue(llvm::Value *IntVal,
918970
AggValueSlot ResultSlot,
919971
SourceLocation Loc) const {
972+
assert(LVal.isSimple());
920973
// Try not to in some easy cases.
921974
assert(IntVal->getType()->isIntegerTy() && "Expected integer value");
922975
if (getEvaluationKind() == TEK_Scalar && !hasPadding()) {
@@ -958,25 +1011,43 @@ RValue AtomicInfo::convertIntToValue(llvm::Value *IntVal,
9581011
RValue CodeGenFunction::EmitAtomicLoad(LValue src, SourceLocation loc,
9591012
AggValueSlot resultSlot) {
9601013
AtomicInfo atomics(*this, src);
1014+
LValue LVal = atomics.getAtomicLValue();
1015+
llvm::Value *SrcAddr = nullptr;
1016+
llvm::AllocaInst *NonSimpleTempAlloca = nullptr;
1017+
if (LVal.isSimple())
1018+
SrcAddr = LVal.getAddress();
1019+
else {
1020+
if (LVal.isBitField())
1021+
SrcAddr = LVal.getBitFieldAddr();
1022+
else if (LVal.isVectorElt())
1023+
SrcAddr = LVal.getVectorAddr();
1024+
else {
1025+
assert(LVal.isExtVectorElt());
1026+
SrcAddr = LVal.getExtVectorAddr();
1027+
}
1028+
NonSimpleTempAlloca = CreateTempAlloca(
1029+
SrcAddr->getType()->getPointerElementType(), "atomic-load-temp");
1030+
NonSimpleTempAlloca->setAlignment(getContext().toBits(src.getAlignment()));
1031+
}
9611032

9621033
// Check whether we should use a library call.
9631034
if (atomics.shouldUseLibcall()) {
9641035
llvm::Value *tempAddr;
965-
if (!resultSlot.isIgnored()) {
966-
assert(atomics.getEvaluationKind() == TEK_Aggregate);
967-
tempAddr = resultSlot.getAddr();
968-
} else {
969-
tempAddr = CreateMemTemp(atomics.getAtomicType(), "atomic-load-temp");
970-
}
1036+
if (LVal.isSimple()) {
1037+
if (!resultSlot.isIgnored()) {
1038+
assert(atomics.getEvaluationKind() == TEK_Aggregate);
1039+
tempAddr = resultSlot.getAddr();
1040+
} else
1041+
tempAddr = CreateMemTemp(atomics.getAtomicType(), "atomic-load-temp");
1042+
} else
1043+
tempAddr = NonSimpleTempAlloca;
9711044

9721045
// void __atomic_load(size_t size, void *mem, void *return, int order);
9731046
CallArgList args;
9741047
args.add(RValue::get(atomics.getAtomicSizeValue()),
9751048
getContext().getSizeType());
976-
args.add(RValue::get(EmitCastToVoidPtr(src.getAddress())),
977-
getContext().VoidPtrTy);
978-
args.add(RValue::get(EmitCastToVoidPtr(tempAddr)),
979-
getContext().VoidPtrTy);
1049+
args.add(RValue::get(EmitCastToVoidPtr(SrcAddr)), getContext().VoidPtrTy);
1050+
args.add(RValue::get(EmitCastToVoidPtr(tempAddr)), getContext().VoidPtrTy);
9801051
args.add(RValue::get(llvm::ConstantInt::get(
9811052
IntTy, AtomicExpr::AO_ABI_memory_order_seq_cst)),
9821053
getContext().IntTy);
@@ -987,7 +1058,7 @@ RValue CodeGenFunction::EmitAtomicLoad(LValue src, SourceLocation loc,
9871058
}
9881059

9891060
// Okay, we're doing this natively.
990-
llvm::Value *addr = atomics.emitCastToAtomicIntPointer(src.getAddress());
1061+
llvm::Value *addr = atomics.emitCastToAtomicIntPointer(SrcAddr);
9911062
llvm::LoadInst *load = Builder.CreateLoad(addr, "atomic-load");
9921063
load->setAtomic(llvm::SequentiallyConsistent);
9931064

@@ -1003,40 +1074,46 @@ RValue CodeGenFunction::EmitAtomicLoad(LValue src, SourceLocation loc,
10031074
return RValue::getAggregate(nullptr, false);
10041075

10051076
// Okay, turn that back into the original value type.
1006-
return atomics.convertIntToValue(load, resultSlot, loc);
1077+
if (src.isSimple())
1078+
return atomics.convertIntToValue(load, resultSlot, loc);
1079+
1080+
auto *IntAddr = atomics.emitCastToAtomicIntPointer(NonSimpleTempAlloca);
1081+
Builder.CreateAlignedStore(load, IntAddr, src.getAlignment().getQuantity());
1082+
return atomics.convertTempToRValue(NonSimpleTempAlloca, resultSlot, loc);
10071083
}
10081084

10091085

10101086

10111087
/// Copy an r-value into memory as part of storing to an atomic type.
10121088
/// This needs to create a bit-pattern suitable for atomic operations.
1013-
void AtomicInfo::emitCopyIntoMemory(RValue rvalue, LValue dest) const {
1089+
void AtomicInfo::emitCopyIntoMemory(RValue rvalue) const {
1090+
assert(LVal.isSimple());
10141091
// If we have an r-value, the rvalue should be of the atomic type,
10151092
// which means that the caller is responsible for having zeroed
10161093
// any padding. Just do an aggregate copy of that type.
10171094
if (rvalue.isAggregate()) {
1018-
CGF.EmitAggregateCopy(dest.getAddress(),
1095+
CGF.EmitAggregateCopy(LVal.getAddress(),
10191096
rvalue.getAggregateAddr(),
10201097
getAtomicType(),
10211098
(rvalue.isVolatileQualified()
1022-
|| dest.isVolatileQualified()),
1023-
dest.getAlignment());
1099+
|| LVal.isVolatileQualified()),
1100+
LVal.getAlignment());
10241101
return;
10251102
}
10261103

10271104
// Okay, otherwise we're copying stuff.
10281105

10291106
// Zero out the buffer if necessary.
1030-
emitMemSetZeroIfNecessary(dest);
1107+
emitMemSetZeroIfNecessary();
10311108

10321109
// Drill past the padding if present.
1033-
dest = projectValue(dest);
1110+
LValue TempLVal = projectValue();
10341111

10351112
// Okay, store the rvalue in.
10361113
if (rvalue.isScalar()) {
1037-
CGF.EmitStoreOfScalar(rvalue.getScalarVal(), dest, /*init*/ true);
1114+
CGF.EmitStoreOfScalar(rvalue.getScalarVal(), TempLVal, /*init*/ true);
10381115
} else {
1039-
CGF.EmitStoreOfComplex(rvalue.getComplexVal(), dest, /*init*/ true);
1116+
CGF.EmitStoreOfComplex(rvalue.getComplexVal(), TempLVal, /*init*/ true);
10401117
}
10411118
}
10421119

@@ -1051,8 +1128,10 @@ llvm::Value *AtomicInfo::materializeRValue(RValue rvalue) const {
10511128

10521129
// Otherwise, make a temporary and materialize into it.
10531130
llvm::Value *temp = CGF.CreateMemTemp(getAtomicType(), "atomic-store-temp");
1054-
LValue tempLV = CGF.MakeAddrLValue(temp, getAtomicType(), getAtomicAlignment());
1055-
emitCopyIntoMemory(rvalue, tempLV);
1131+
LValue tempLV =
1132+
CGF.MakeAddrLValue(temp, getAtomicType(), getAtomicAlignment());
1133+
AtomicInfo Atomics(CGF, tempLV);
1134+
Atomics.emitCopyIntoMemory(rvalue);
10561135
return temp;
10571136
}
10581137

@@ -1098,7 +1177,7 @@ void CodeGenFunction::EmitAtomicStore(RValue rvalue, LValue dest, bool isInit) {
10981177

10991178
// If this is an initialization, just put the value there normally.
11001179
if (isInit) {
1101-
atomics.emitCopyIntoMemory(rvalue, dest);
1180+
atomics.emitCopyIntoMemory(rvalue);
11021181
return;
11031182
}
11041183

@@ -1214,13 +1293,13 @@ void CodeGenFunction::EmitAtomicInit(Expr *init, LValue dest) {
12141293
switch (atomics.getEvaluationKind()) {
12151294
case TEK_Scalar: {
12161295
llvm::Value *value = EmitScalarExpr(init);
1217-
atomics.emitCopyIntoMemory(RValue::get(value), dest);
1296+
atomics.emitCopyIntoMemory(RValue::get(value));
12181297
return;
12191298
}
12201299

12211300
case TEK_Complex: {
12221301
ComplexPairTy value = EmitComplexExpr(init);
1223-
atomics.emitCopyIntoMemory(RValue::getComplex(value), dest);
1302+
atomics.emitCopyIntoMemory(RValue::getComplex(value));
12241303
return;
12251304
}
12261305

@@ -1229,8 +1308,8 @@ void CodeGenFunction::EmitAtomicInit(Expr *init, LValue dest) {
12291308
// of atomic type.
12301309
bool Zeroed = false;
12311310
if (!init->getType()->isAtomicType()) {
1232-
Zeroed = atomics.emitMemSetZeroIfNecessary(dest);
1233-
dest = atomics.projectValue(dest);
1311+
Zeroed = atomics.emitMemSetZeroIfNecessary();
1312+
dest = atomics.projectValue();
12341313
}
12351314

12361315
// Evaluate the expression directly into the destination.

0 commit comments

Comments
 (0)