[llvm] 17517f3 - Encode alignment attribute for `cmpxchg`
James Y Knight via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 11 12:18:32 PST 2021
Author: Guillaume Chatelet
Date: 2021-02-11T15:17:50-05:00
New Revision: 17517f3178b5cdda832c4e90f618437c13560013
URL: https://github.com/llvm/llvm-project/commit/17517f3178b5cdda832c4e90f618437c13560013
DIFF: https://github.com/llvm/llvm-project/commit/17517f3178b5cdda832c4e90f618437c13560013.diff
LOG: 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
Added:
Modified:
llvm/docs/LangRef.rst
llvm/lib/AsmParser/LLParser.cpp
llvm/lib/Bitcode/Reader/BitcodeReader.cpp
llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
llvm/lib/IR/AsmWriter.cpp
llvm/test/Bitcode/compatibility.ll
Removed:
################################################################################
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 2aa04b9d0777..fdd9c14c5b7a 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -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
+
diff erent 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.
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 82d82b56c8e3..7554c88887e4 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -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;
}
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index 365cf5f55766..4a77f8c5f6d8 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -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];
+
+ MaybeAlign Alignment;
- I = new AtomicCmpXchgInst(Ptr, Cmp, Val, Alignment, SuccessOrdering,
+ 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;
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index 29620ff6114c..9a4f724d6379 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -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;
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index abffdae573ae..bb300a230b95 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -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());
diff --git a/llvm/test/Bitcode/compatibility.ll b/llvm/test/Bitcode/compatibility.ll
index 3370b5a84428..34c5cfd41204 100644
--- a/llvm/test/Bitcode/compatibility.ll
+++ b/llvm/test/Bitcode/compatibility.ll
@@ -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
More information about the llvm-commits
mailing list