Skip to content

Commit 375ddd6

Browse files
[ARM][MC] Add GNU Alias for ldrexd, ldaexd, stlexd, and strexd instructions (#86507)
These aliases were supported previously there was a regression at some point. This adds back the alternate forms and tidies up this section of code a little. See #83436 (comment) for the initial report regarding this change.
1 parent 44d037c commit 375ddd6

File tree

4 files changed

+67
-23
lines changed

4 files changed

+67
-23
lines changed

llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp

Lines changed: 35 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6865,8 +6865,9 @@ static void applyMnemonicAliases(StringRef &Mnemonic,
68656865
const FeatureBitset &Features,
68666866
unsigned VariantID);
68676867

6868-
// The GNU assembler has aliases of ldrd and strd with the second register
6869-
// omitted. We don't have a way to do that in tablegen, so fix it up here.
6868+
// The GNU assembler has aliases of ldrd, strd, ldrexd, strexd, ldaexd, and
6869+
// stlexd with the second register omitted. We don't have a way to do that in
6870+
// tablegen, so fix it up here.
68706871
//
68716872
// We have to be careful to not emit an invalid Rt2 here, because the rest of
68726873
// the assembly parser could then generate confusing diagnostics refering to
@@ -6876,13 +6877,19 @@ static void applyMnemonicAliases(StringRef &Mnemonic,
68766877
void ARMAsmParser::fixupGNULDRDAlias(StringRef Mnemonic,
68776878
OperandVector &Operands,
68786879
unsigned MnemonicOpsEndInd) {
6879-
if (Mnemonic != "ldrd" && Mnemonic != "strd")
6880+
if (Mnemonic != "ldrd" && Mnemonic != "strd" && Mnemonic != "ldrexd" &&
6881+
Mnemonic != "strexd" && Mnemonic != "ldaexd" && Mnemonic != "stlexd")
68806882
return;
6881-
if (Operands.size() < MnemonicOpsEndInd + 2)
6883+
6884+
unsigned IdX = Mnemonic == "strexd" || Mnemonic == "stlexd"
6885+
? MnemonicOpsEndInd + 1
6886+
: MnemonicOpsEndInd;
6887+
6888+
if (Operands.size() < IdX + 2)
68826889
return;
68836890

6884-
ARMOperand &Op2 = static_cast<ARMOperand &>(*Operands[MnemonicOpsEndInd]);
6885-
ARMOperand &Op3 = static_cast<ARMOperand &>(*Operands[MnemonicOpsEndInd + 1]);
6891+
ARMOperand &Op2 = static_cast<ARMOperand &>(*Operands[IdX]);
6892+
ARMOperand &Op3 = static_cast<ARMOperand &>(*Operands[IdX + 1]);
68866893

68876894
if (!Op2.isReg())
68886895
return;
@@ -6907,7 +6914,7 @@ void ARMAsmParser::fixupGNULDRDAlias(StringRef Mnemonic,
69076914
return;
69086915

69096916
Operands.insert(
6910-
Operands.begin() + MnemonicOpsEndInd + 1,
6917+
Operands.begin() + IdX + 1,
69116918
ARMOperand::CreateReg(PairedReg, Op2.getStartLoc(), Op2.getEndLoc()));
69126919
}
69136920

@@ -7336,47 +7343,53 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
73367343
static_cast<ARMOperand &>(*Operands[MnemonicOpsEndInd]).isImm())
73377344
removeCondCode(Operands, MnemonicOpsEndInd);
73387345

7346+
// GNU Assembler extension (compatibility).
7347+
fixupGNULDRDAlias(Mnemonic, Operands, MnemonicOpsEndInd);
7348+
73397349
// Adjust operands of ldrexd/strexd to MCK_GPRPair.
73407350
// ldrexd/strexd require even/odd GPR pair. To enforce this constraint,
73417351
// a single GPRPair reg operand is used in the .td file to replace the two
73427352
// GPRs. However, when parsing from asm, the two GRPs cannot be
73437353
// automatically
73447354
// expressed as a GPRPair, so we have to manually merge them.
73457355
// FIXME: We would really like to be able to tablegen'erate this.
7346-
if (!isThumb() && Operands.size() > MnemonicOpsEndInd + 1 &&
7356+
bool IsLoad = (Mnemonic == "ldrexd" || Mnemonic == "ldaexd");
7357+
if (!isThumb() && Operands.size() > MnemonicOpsEndInd + 1 + (!IsLoad) &&
73477358
(Mnemonic == "ldrexd" || Mnemonic == "strexd" || Mnemonic == "ldaexd" ||
73487359
Mnemonic == "stlexd")) {
7349-
bool isLoad = (Mnemonic == "ldrexd" || Mnemonic == "ldaexd");
7350-
unsigned Idx = isLoad ? MnemonicOpsEndInd : MnemonicOpsEndInd + 1;
7360+
unsigned Idx = IsLoad ? MnemonicOpsEndInd : MnemonicOpsEndInd + 1;
73517361
ARMOperand &Op1 = static_cast<ARMOperand &>(*Operands[Idx]);
73527362
ARMOperand &Op2 = static_cast<ARMOperand &>(*Operands[Idx + 1]);
73537363

73547364
const MCRegisterClass &MRC = MRI->getRegClass(ARM::GPRRegClassID);
7355-
// Adjust only if Op1 and Op2 are GPRs.
7356-
if (Op1.isReg() && Op2.isReg() && MRC.contains(Op1.getReg()) &&
7357-
MRC.contains(Op2.getReg())) {
7365+
// Adjust only if Op1 is a GPR.
7366+
if (Op1.isReg() && MRC.contains(Op1.getReg())) {
73587367
unsigned Reg1 = Op1.getReg();
7359-
unsigned Reg2 = Op2.getReg();
73607368
unsigned Rt = MRI->getEncodingValue(Reg1);
7369+
unsigned Reg2 = Op2.getReg();
73617370
unsigned Rt2 = MRI->getEncodingValue(Reg2);
7362-
7363-
// Rt2 must be Rt + 1 and Rt must be even.
7364-
if (Rt + 1 != Rt2 || (Rt & 1)) {
7371+
// Rt2 must be Rt + 1.
7372+
if (Rt + 1 != Rt2)
73657373
return Error(Op2.getStartLoc(),
7366-
isLoad ? "destination operands must be sequential"
7374+
IsLoad ? "destination operands must be sequential"
73677375
: "source operands must be sequential");
7368-
}
7376+
7377+
// Rt must be even
7378+
if (Rt & 1)
7379+
return Error(
7380+
Op1.getStartLoc(),
7381+
IsLoad ? "destination operands must start start at an even register"
7382+
: "source operands must start start at an even register");
7383+
73697384
unsigned NewReg = MRI->getMatchingSuperReg(
73707385
Reg1, ARM::gsub_0, &(MRI->getRegClass(ARM::GPRPairRegClassID)));
7386+
73717387
Operands[Idx] =
73727388
ARMOperand::CreateReg(NewReg, Op1.getStartLoc(), Op2.getEndLoc());
73737389
Operands.erase(Operands.begin() + Idx + 1);
73747390
}
73757391
}
73767392

7377-
// GNU Assembler extension (compatibility).
7378-
fixupGNULDRDAlias(Mnemonic, Operands, MnemonicOpsEndInd);
7379-
73807393
// FIXME: As said above, this is all a pretty gross hack. This instruction
73817394
// does not fit with other "subs" and tblgen.
73827395
// Adjust operands of B9.3.19 SUBS PC, LR, #imm (Thumb2) system instruction

llvm/test/MC/ARM/basic-arm-instructions.s

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1202,6 +1202,10 @@ Lforward:
12021202
@ CHECK: ldrex r1, [r7] @ encoding: [0x9f,0x1f,0x97,0xe1]
12031203
@ CHECK: ldrexd r6, r7, [r8] @ encoding: [0x9f,0x6f,0xb8,0xe1]
12041204

1205+
@ GNU alias
1206+
ldrexd r6, [r8]
1207+
@ CHECK: ldrexd r6, r7, [r8] @ encoding: [0x9f,0x6f,0xb8,0xe1]
1208+
12051209
@------------------------------------------------------------------------------
12061210
@ LDRHT
12071211
@------------------------------------------------------------------------------
@@ -2904,6 +2908,10 @@ Lforward:
29042908
@ CHECK: strex r2, r1, [r7] @ encoding: [0x91,0x2f,0x87,0xe1]
29052909
@ CHECK: strexd r6, r2, r3, [r8] @ encoding: [0x92,0x6f,0xa8,0xe1]
29062910

2911+
@ GNU alias
2912+
strexd r6, r2, [r8]
2913+
@ CHECK: strexd r6, r2, r3, [r8] @ encoding: [0x92,0x6f,0xa8,0xe1]
2914+
29072915
@------------------------------------------------------------------------------
29082916
@ STR
29092917
@------------------------------------------------------------------------------

llvm/test/MC/ARM/load-store-acquire-release-v8-thumb.s

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414
@ CHECK-V7: error: instruction requires: acquire/release
1515
@ CHECK-V7: error: instruction requires: acquire/release
1616

17+
@ GNU alias
18+
ldaexd r6, [r8]
19+
@ CHECK: ldaexd r6, r7, [r8] @ encoding: [0xd8,0xe8,0xff,0x67]
20+
1721
stlexb r1, r3, [r4]
1822
stlexh r4, r2, [r5]
1923
stlex r2, r1, [r7]
@@ -27,6 +31,10 @@
2731
@ CHECK-V7: error: instruction requires: acquire/release
2832
@ CHECK-V7: error: instruction requires: acquire/release
2933

34+
@ GNU alias
35+
stlexd r6, r2, [r8]
36+
@ CHECK: stlexd r6, r2, r3, [r8] @ encoding: [0xc8,0xe8,0xf6,0x23]
37+
3038
lda r5, [r6]
3139
ldab r5, [r6]
3240
ldah r12, [r9]

llvm/test/MC/ARM/load-store-acquire-release-v8.s

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
@ RUN: llvm-mc -triple=armv8 -show-encoding < %s | FileCheck %s
1+
@ RUN: not llvm-mc -triple=armv8 -show-encoding < %s 2> %t | FileCheck %s
2+
@ RUN: FileCheck %s < %t --check-prefix=CHECK-ERROR
23
@ RUN: not llvm-mc -triple=armv7 -show-encoding < %s 2>&1 | FileCheck %s --check-prefix=CHECK-V7
34
ldaexb r3, [r4]
45
ldaexh r2, [r5]
@@ -14,6 +15,13 @@
1415
@ CHECK-V7: instruction requires: acquire/release
1516
@ CHECK-V7: instruction requires: acquire/release
1617

18+
ldaexd r2, r4, [r8]
19+
@ CHECK-ERROR: error: destination operands must be sequential
20+
21+
@ GNU alias
22+
ldaexd r6, [r8]
23+
@ CHECK: ldaexd r6, r7, [r8] @ encoding: [0x9f,0x6e,0xb8,0xe1]
24+
1725
stlexb r1, r3, [r4]
1826
stlexh r4, r2, [r5]
1927
stlex r2, r1, [r7]
@@ -27,6 +35,13 @@
2735
@ CHECK-V7: instruction requires: acquire/release
2836
@ CHECK-V7: instruction requires: acquire/release
2937

38+
stlexd r6, r2, r4, [r8]
39+
@ CHECK-ERROR: error: source operands must be sequential
40+
41+
@ GNU alias
42+
stlexd r6, r2, [r8]
43+
@ CHECK: stlexd r6, r2, r3, [r8] @ encoding: [0x92,0x6e,0xa8,0xe1]
44+
3045
lda r5, [r6]
3146
ldab r5, [r6]
3247
ldah r12, [r9]

0 commit comments

Comments
 (0)