summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNemanja Ivanovic <nemanja.i.ibm@gmail.com>2021-12-03 06:56:29 -0600
committerTom Stellard <tstellar@redhat.com>2021-12-16 18:51:01 -0800
commit9fb79e6940b26145fdcaa79e9d74a76c61d6c2d4 (patch)
tree3903edaeffdfd37e43a344fcde2d15c07c902b80
parente68f640deecc4cc6318c14468101f4d819f93727 (diff)
downloadllvm-9fb79e6940b26145fdcaa79e9d74a76c61d6c2d4.tar.gz
[PowerPC] Handle base load with reservation mnemonic
The Power ISA defined l[bhwdq]arx as both base and extended mnemonics. The base mnemonic takes the EH bit as an operand and the extended mnemonic omits it, making it implicitly zero. The existing implementation only handles the base mnemonic when EH is 1 and internally produces a different instruction. There are historical reasons for this. This patch simply removes the limitation introduced by this implementation that disallows the base mnemonic with EH = 0 in the ASM parser. This resolves an issue that prevented some files in the Linux kernel from being built with -fintegrated-as. Also fix a crash if the value is not an integer immediate. (cherry picked from commit d6c0ef78876dc3204b0a6d92119b15aa9cd12af3)
-rw-r--r--llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp12
-rw-r--r--llvm/test/CodeGen/PowerPC/inline-asm-label.ll36
-rw-r--r--llvm/test/MC/PowerPC/ppc64-encoding-bookII.s16
-rw-r--r--llvm/test/MC/PowerPC/ppc64-errors.s4
4 files changed, 67 insertions, 1 deletions
diff --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
index 7631bb4bccfb..392de0f251a2 100644
--- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
+++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
@@ -1576,6 +1576,16 @@ bool PPCAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
std::swap(Operands[2], Operands[1]);
}
+ // Handle base mnemonic for atomic loads where the EH bit is zero.
+ if (Name == "lqarx" || Name == "ldarx" || Name == "lwarx" ||
+ Name == "lharx" || Name == "lbarx") {
+ if (Operands.size() != 5)
+ return false;
+ PPCOperand &EHOp = (PPCOperand &)*Operands[4];
+ if (EHOp.isU1Imm() && EHOp.getImm() == 0)
+ Operands.pop_back();
+ }
+
return false;
}
@@ -1745,7 +1755,7 @@ unsigned PPCAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
}
PPCOperand &Op = static_cast<PPCOperand &>(AsmOp);
- if (Op.isImm() && Op.getImm() == ImmVal)
+ if (Op.isU3Imm() && Op.getImm() == ImmVal)
return Match_Success;
return Match_InvalidOperand;
diff --git a/llvm/test/CodeGen/PowerPC/inline-asm-label.ll b/llvm/test/CodeGen/PowerPC/inline-asm-label.ll
index 6bacbd77aba2..33d0fdc926d2 100644
--- a/llvm/test/CodeGen/PowerPC/inline-asm-label.ll
+++ b/llvm/test/CodeGen/PowerPC/inline-asm-label.ll
@@ -45,3 +45,39 @@ entry:
ret i32 %4
}
+define dso_local signext i32 @NoBarrier_CompareAndSwapExtMne(i32* %ptr, i32 signext %old_value, i32 signext %new_value) #0 {
+; CHECK-LABEL: NoBarrier_CompareAndSwapExtMne:
+; CHECK: #APP
+; CHECK-NEXT: L..tmp2:
+; CHECK-NEXT: lwarx 6, 0, 3
+; CHECK-NEXT: cmpw 4, 6
+; CHECK-NEXT: bne- 0, L..tmp3
+; CHECK-NEXT: stwcx. 5, 0, 3
+; CHECK-NEXT: bne- 0, L..tmp2
+; CHECK-NEXT: L..tmp3:
+
+; NOIS-LABEL: NoBarrier_CompareAndSwapExtMne:
+; NOIS: #APP
+; NOIS-NEXT: 1: lwarx 6, 0, 3
+; NOIS-NEXT: cmpw 4, 6
+; NOIS-NEXT: bne- 2f
+; NOIS-NEXT: stwcx. 5, 0, 3
+; NOIS-NEXT: bne- 1b
+; NOIS-NEXT: 2:
+
+entry:
+ %ptr.addr = alloca i32*, align 8 %old_value.addr = alloca i32, align 4
+ %new_value.addr = alloca i32, align 4
+ %result = alloca i32, align 4
+ store i32* %ptr, i32** %ptr.addr, align 8
+ store i32 %old_value, i32* %old_value.addr, align 4
+ store i32 %new_value, i32* %new_value.addr, align 4
+ %0 = load i32*, i32** %ptr.addr, align 8
+ %1 = load i32, i32* %old_value.addr, align 4
+ %2 = load i32, i32* %new_value.addr, align 4
+ %3 = call i32 asm sideeffect "1: lwarx $0, $4, $1, 0 \0A\09 cmpw $2, $0 \0A\09 bne- 2f \0A\09 stwcx. $3, $4, $1 \0A\09 bne- 1b \0A\092: \0A\09", "=&b,b,b,b,i,~{cr0},~{ctr}"(i32* %0, i32 %1, i32 %2, i32 0)
+ store i32 %3, i32* %result, align 4
+ %4 = load i32, i32* %result, align 4
+ ret i32 %4
+}
+
diff --git a/llvm/test/MC/PowerPC/ppc64-encoding-bookII.s b/llvm/test/MC/PowerPC/ppc64-encoding-bookII.s
index 447542fba672..bd50e2321ffd 100644
--- a/llvm/test/MC/PowerPC/ppc64-encoding-bookII.s
+++ b/llvm/test/MC/PowerPC/ppc64-encoding-bookII.s
@@ -130,18 +130,34 @@
# CHECK-LE: lbarx 2, 3, 4 # encoding: [0x68,0x20,0x43,0x7c]
lbarx 2, 3, 4
+# CHECK-BE: lbarx 2, 3, 4 # encoding: [0x7c,0x43,0x20,0x68]
+# CHECK-LE: lbarx 2, 3, 4 # encoding: [0x68,0x20,0x43,0x7c]
+ lbarx 2, 3, 4, 0
+
# CHECK-BE: lharx 2, 3, 4 # encoding: [0x7c,0x43,0x20,0xe8]
# CHECK-LE: lharx 2, 3, 4 # encoding: [0xe8,0x20,0x43,0x7c]
lharx 2, 3, 4
+# CHECK-BE: lharx 2, 3, 4 # encoding: [0x7c,0x43,0x20,0xe8]
+# CHECK-LE: lharx 2, 3, 4 # encoding: [0xe8,0x20,0x43,0x7c]
+ lharx 2, 3, 4, 0
+
# CHECK-BE: lwarx 2, 3, 4 # encoding: [0x7c,0x43,0x20,0x28]
# CHECK-LE: lwarx 2, 3, 4 # encoding: [0x28,0x20,0x43,0x7c]
lwarx 2, 3, 4
+# CHECK-BE: lwarx 2, 3, 4 # encoding: [0x7c,0x43,0x20,0x28]
+# CHECK-LE: lwarx 2, 3, 4 # encoding: [0x28,0x20,0x43,0x7c]
+ lwarx 2, 3, 4, 0
+
# CHECK-BE: ldarx 2, 3, 4 # encoding: [0x7c,0x43,0x20,0xa8]
# CHECK-LE: ldarx 2, 3, 4 # encoding: [0xa8,0x20,0x43,0x7c]
ldarx 2, 3, 4
+# CHECK-BE: ldarx 2, 3, 4 # encoding: [0x7c,0x43,0x20,0xa8]
+# CHECK-LE: ldarx 2, 3, 4 # encoding: [0xa8,0x20,0x43,0x7c]
+ ldarx 2, 3, 4, 0
+
# CHECK-BE: lqarx 2, 3, 4 # encoding: [0x7c,0x43,0x22,0x28]
# CHECK-LE: lqarx 2, 3, 4 # encoding: [0x28,0x22,0x43,0x7c]
lqarx 2, 3, 4
diff --git a/llvm/test/MC/PowerPC/ppc64-errors.s b/llvm/test/MC/PowerPC/ppc64-errors.s
index 6da7406e2828..627ae410db88 100644
--- a/llvm/test/MC/PowerPC/ppc64-errors.s
+++ b/llvm/test/MC/PowerPC/ppc64-errors.s
@@ -139,3 +139,7 @@
# CHECK: error: invalid modifier 'got' (no symbols present)
addi 4, 3, 123@got
# CHECK-NEXT: addi 4, 3, 123@got
+
+# CHECK: error: invalid operand for instruction
+# CHECK-NEXT: lwarx 1, 2, 3, a
+ lwarx 1, 2, 3, a