1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-18 18:42:46 +02:00

Encode alignment attribute for cmpxchg

This is a follow up patch to D83136 adding the align attribute to `cmpxchg`.
See also D83465 for `atomicrmw`.

Differential Revision: https://reviews.llvm.org/D87443
This commit is contained in:
Guillaume Chatelet 2021-02-11 15:17:50 -05:00 committed by James Y Knight
parent 1d36d2af13
commit d83a14c77d
6 changed files with 76 additions and 30 deletions

View File

@ -9617,7 +9617,7 @@ Syntax:
::
cmpxchg [weak] [volatile] <ty>* <pointer>, <ty> <cmp>, <ty> <new> [syncscope("<target-scope>")] <success ordering> <failure ordering> ; yields { ty, i1 }
cmpxchg [weak] [volatile] <ty>* <pointer>, <ty> <cmp>, <ty> <new> [syncscope("<target-scope>")] <success ordering> <failure ordering>[, align <alignment>] ; yields { ty, i1 }
Overview:
"""""""""
@ -9649,6 +9649,13 @@ stronger than that on success, and the failure ordering cannot be either
A ``cmpxchg`` instruction can also take an optional
":ref:`syncscope <syncscope>`" argument.
The instruction can take an optional ``align`` attribute.
The alignment must be a power of two greater or equal to the size of the
`<value>` type. If unspecified, the alignment is assumed to be equal to the
size of the '<value>' type. Note that this default alignment assumption is
different from the alignment used for the load/store instructions when align
isn't specified.
The pointer passed into cmpxchg must have alignment greater than or
equal to the size in memory of the operand.

View File

@ -7432,7 +7432,8 @@ int LLParser::parseStore(Instruction *&Inst, PerFunctionState &PFS) {
/// parseCmpXchg
/// ::= 'cmpxchg' 'weak'? 'volatile'? TypeAndValue ',' TypeAndValue ','
/// TypeAndValue 'singlethread'? AtomicOrdering AtomicOrdering
/// TypeAndValue 'singlethread'? AtomicOrdering AtomicOrdering ','
/// 'Align'?
int LLParser::parseCmpXchg(Instruction *&Inst, PerFunctionState &PFS) {
Value *Ptr, *Cmp, *New; LocTy PtrLoc, CmpLoc, NewLoc;
bool AteExtraComma = false;
@ -7441,6 +7442,7 @@ int LLParser::parseCmpXchg(Instruction *&Inst, PerFunctionState &PFS) {
SyncScope::ID SSID = SyncScope::System;
bool isVolatile = false;
bool isWeak = false;
MaybeAlign Alignment;
if (EatIfPresent(lltok::kw_weak))
isWeak = true;
@ -7454,7 +7456,8 @@ int LLParser::parseCmpXchg(Instruction *&Inst, PerFunctionState &PFS) {
parseToken(lltok::comma, "expected ',' after cmpxchg cmp operand") ||
parseTypeAndValue(New, NewLoc, PFS) ||
parseScopeAndOrdering(true /*Always atomic*/, SSID, SuccessOrdering) ||
parseOrdering(FailureOrdering))
parseOrdering(FailureOrdering) ||
parseOptionalCommaAlign(Alignment, AteExtraComma))
return true;
if (SuccessOrdering == AtomicOrdering::Unordered ||
@ -7476,14 +7479,16 @@ int LLParser::parseCmpXchg(Instruction *&Inst, PerFunctionState &PFS) {
if (!New->getType()->isFirstClassType())
return error(NewLoc, "cmpxchg operand must be a first class value");
Align Alignment(
const Align DefaultAlignment(
PFS.getFunction().getParent()->getDataLayout().getTypeStoreSize(
Cmp->getType()));
AtomicCmpXchgInst *CXI = new AtomicCmpXchgInst(
Ptr, Cmp, New, Alignment, SuccessOrdering, FailureOrdering, SSID);
Ptr, Cmp, New, Alignment.getValueOr(DefaultAlignment), SuccessOrdering,
FailureOrdering, SSID);
CXI->setVolatile(isVolatile);
CXI->setWeak(isWeak);
Inst = CXI;
return AteExtraComma ? InstExtraComma : InstNormal;
}

View File

@ -5085,7 +5085,7 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
}
case bitc::FUNC_CODE_INST_CMPXCHG: {
// CMPXCHG: [ptrty, ptr, cmp, val, vol, success_ordering, synchscope,
// failure_ordering, weak]
// failure_ordering, weak, align?]
const size_t NumRecords = Record.size();
unsigned OpNum = 0;
Value *Ptr = nullptr;
@ -5100,10 +5100,14 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
return error("Invalid record");
Value *Val = nullptr;
if (popValue(Record, OpNum, NextValueNo, Cmp->getType(), Val) ||
NumRecords < OpNum + 3 || NumRecords > OpNum + 5)
if (popValue(Record, OpNum, NextValueNo, Cmp->getType(), Val))
return error("Invalid record");
if (NumRecords < OpNum + 3 || NumRecords > OpNum + 6)
return error("Invalid record");
const bool IsVol = Record[OpNum];
const AtomicOrdering SuccessOrdering =
getDecodedOrdering(Record[OpNum + 1]);
if (SuccessOrdering == AtomicOrdering::NotAtomic ||
@ -5118,14 +5122,23 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
const AtomicOrdering FailureOrdering =
getDecodedOrdering(Record[OpNum + 3]);
const Align Alignment(
TheModule->getDataLayout().getTypeStoreSize(Cmp->getType()));
const bool IsWeak = Record[OpNum + 4];
I = new AtomicCmpXchgInst(Ptr, Cmp, Val, Alignment, SuccessOrdering,
MaybeAlign Alignment;
if (NumRecords == (OpNum + 6)) {
if (Error Err = parseAlignmentValue(Record[OpNum + 5], Alignment))
return Err;
}
if (!Alignment)
Alignment =
Align(TheModule->getDataLayout().getTypeStoreSize(Cmp->getType()));
I = new AtomicCmpXchgInst(Ptr, Cmp, Val, *Alignment, SuccessOrdering,
FailureOrdering, SSID);
FullTy = StructType::get(Context, {FullTy, Type::getInt1Ty(Context)});
cast<AtomicCmpXchgInst>(I)->setVolatile(Record[OpNum]);
cast<AtomicCmpXchgInst>(I)->setWeak(Record[OpNum + 4]);
cast<AtomicCmpXchgInst>(I)->setVolatile(IsVol);
cast<AtomicCmpXchgInst>(I)->setWeak(IsWeak);
InstructionList.push_back(I);
break;

View File

@ -3060,6 +3060,7 @@ void ModuleBitcodeWriter::writeInstruction(const Instruction &I,
Vals.push_back(
getEncodedOrdering(cast<AtomicCmpXchgInst>(I).getFailureOrdering()));
Vals.push_back(cast<AtomicCmpXchgInst>(I).isWeak());
Vals.push_back(getEncodedAlign(cast<AtomicCmpXchgInst>(I).getAlign()));
break;
case Instruction::AtomicRMW:
Code = bitc::FUNC_CODE_INST_ATOMICRMW;

View File

@ -4324,6 +4324,7 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
} else if (const AtomicCmpXchgInst *CXI = dyn_cast<AtomicCmpXchgInst>(&I)) {
writeAtomicCmpXchg(CXI->getContext(), CXI->getSuccessOrdering(),
CXI->getFailureOrdering(), CXI->getSyncScopeID());
Out << ", align " << CXI->getAlign().value();
} else if (const AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(&I)) {
writeAtomic(RMWI->getContext(), RMWI->getOrdering(),
RMWI->getSyncScopeID());

View File

@ -718,22 +718,41 @@ normal:
;; Atomic Memory Ordering Constraints
define void @atomics(i32* %word) {
%cmpxchg.0 = cmpxchg i32* %word, i32 0, i32 4 monotonic monotonic
; CHECK: %cmpxchg.0 = cmpxchg i32* %word, i32 0, i32 4 monotonic monotonic
%cmpxchg.1 = cmpxchg i32* %word, i32 0, i32 5 acq_rel monotonic
; CHECK: %cmpxchg.1 = cmpxchg i32* %word, i32 0, i32 5 acq_rel monotonic
%cmpxchg.2 = cmpxchg i32* %word, i32 0, i32 6 acquire monotonic
; CHECK: %cmpxchg.2 = cmpxchg i32* %word, i32 0, i32 6 acquire monotonic
%cmpxchg.3 = cmpxchg i32* %word, i32 0, i32 7 release monotonic
; CHECK: %cmpxchg.3 = cmpxchg i32* %word, i32 0, i32 7 release monotonic
%cmpxchg.4 = cmpxchg i32* %word, i32 0, i32 8 seq_cst monotonic
; CHECK: %cmpxchg.4 = cmpxchg i32* %word, i32 0, i32 8 seq_cst monotonic
%cmpxchg.5 = cmpxchg weak i32* %word, i32 0, i32 9 seq_cst monotonic
; CHECK: %cmpxchg.5 = cmpxchg weak i32* %word, i32 0, i32 9 seq_cst monotonic
%cmpxchg.6 = cmpxchg volatile i32* %word, i32 0, i32 10 seq_cst monotonic
; CHECK: %cmpxchg.6 = cmpxchg volatile i32* %word, i32 0, i32 10 seq_cst monotonic
%cmpxchg.7 = cmpxchg weak volatile i32* %word, i32 0, i32 11 syncscope("singlethread") seq_cst monotonic
; CHECK: %cmpxchg.7 = cmpxchg weak volatile i32* %word, i32 0, i32 11 syncscope("singlethread") seq_cst monotonic
;; Atomic Compare And Exchange w/o alignment
%cmpxchg_no_align.0 = cmpxchg i32* %word, i32 0, i32 4 monotonic monotonic
; CHECK: %cmpxchg_no_align.0 = cmpxchg i32* %word, i32 0, i32 4 monotonic monotonic
%cmpxchg_no_align.1 = cmpxchg i32* %word, i32 0, i32 5 acq_rel monotonic
; CHECK: %cmpxchg_no_align.1 = cmpxchg i32* %word, i32 0, i32 5 acq_rel monotonic
%cmpxchg_no_align.2 = cmpxchg i32* %word, i32 0, i32 6 acquire monotonic
; CHECK: %cmpxchg_no_align.2 = cmpxchg i32* %word, i32 0, i32 6 acquire monotonic
%cmpxchg_no_align.3 = cmpxchg i32* %word, i32 0, i32 7 release monotonic
; CHECK: %cmpxchg_no_align.3 = cmpxchg i32* %word, i32 0, i32 7 release monotonic
%cmpxchg_no_align.4 = cmpxchg i32* %word, i32 0, i32 8 seq_cst monotonic
; CHECK: %cmpxchg_no_align.4 = cmpxchg i32* %word, i32 0, i32 8 seq_cst monotonic
%cmpxchg_no_align.5 = cmpxchg weak i32* %word, i32 0, i32 9 seq_cst monotonic
; CHECK: %cmpxchg_no_align.5 = cmpxchg weak i32* %word, i32 0, i32 9 seq_cst monotonic
%cmpxchg_no_align.6 = cmpxchg volatile i32* %word, i32 0, i32 10 seq_cst monotonic
; CHECK: %cmpxchg_no_align.6 = cmpxchg volatile i32* %word, i32 0, i32 10 seq_cst monotonic
%cmpxchg_no_align.7 = cmpxchg weak volatile i32* %word, i32 0, i32 11 syncscope("singlethread") seq_cst monotonic
; CHECK: %cmpxchg_no_align.7 = cmpxchg weak volatile i32* %word, i32 0, i32 11 syncscope("singlethread") seq_cst monotonic
;; Atomic Compare And Exchange w/ alignment
%cmpxchg.0 = cmpxchg i32* %word, i32 0, i32 4 monotonic monotonic, align 16
; CHECK: %cmpxchg.0 = cmpxchg i32* %word, i32 0, i32 4 monotonic monotonic, align 16
%cmpxchg.1 = cmpxchg i32* %word, i32 0, i32 5 acq_rel monotonic, align 16
; CHECK: %cmpxchg.1 = cmpxchg i32* %word, i32 0, i32 5 acq_rel monotonic, align 16
%cmpxchg.2 = cmpxchg i32* %word, i32 0, i32 6 acquire monotonic, align 16
; CHECK: %cmpxchg.2 = cmpxchg i32* %word, i32 0, i32 6 acquire monotonic, align 16
%cmpxchg.3 = cmpxchg i32* %word, i32 0, i32 7 release monotonic, align 16
; CHECK: %cmpxchg.3 = cmpxchg i32* %word, i32 0, i32 7 release monotonic, align 16
%cmpxchg.4 = cmpxchg i32* %word, i32 0, i32 8 seq_cst monotonic, align 16
; CHECK: %cmpxchg.4 = cmpxchg i32* %word, i32 0, i32 8 seq_cst monotonic, align 16
%cmpxchg.5 = cmpxchg weak i32* %word, i32 0, i32 9 seq_cst monotonic, align 16
; CHECK: %cmpxchg.5 = cmpxchg weak i32* %word, i32 0, i32 9 seq_cst monotonic, align 16
%cmpxchg.6 = cmpxchg volatile i32* %word, i32 0, i32 10 seq_cst monotonic, align 16
; CHECK: %cmpxchg.6 = cmpxchg volatile i32* %word, i32 0, i32 10 seq_cst monotonic, align 16
%cmpxchg.7 = cmpxchg weak volatile i32* %word, i32 0, i32 11 syncscope("singlethread") seq_cst monotonic, align 16
; CHECK: %cmpxchg.7 = cmpxchg weak volatile i32* %word, i32 0, i32 11 syncscope("singlethread") seq_cst monotonic, align 16
;; Atomic w/o alignment
%atomicrmw_no_align.xchg = atomicrmw xchg i32* %word, i32 12 monotonic
@ -782,7 +801,7 @@ define void @atomics(i32* %word) {
; CHECK: %atomicrmw.umax = atomicrmw umax i32* %word, i32 21 syncscope("singlethread") monotonic, align 16
%atomicrmw.umin = atomicrmw volatile umin i32* %word, i32 22 syncscope("singlethread") monotonic, align 16
; CHECK: %atomicrmw.umin = atomicrmw volatile umin i32* %word, i32 22 syncscope("singlethread") monotonic, align 16
fence acquire
; CHECK: fence acquire
fence release