aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoryingopq <115543042+yingopq@users.noreply.github.com>2024-02-24 15:13:43 +0800
committerTom Stellard <tstellar@redhat.com>2024-02-27 09:17:42 -0800
commite2182a6b91f5001bd9b52e3b1fe6beac434e5fe5 (patch)
tree968e3c678ed522780a46124f29dc577ff83ba93d
parent6d8f9290b6afa5e61841124ae1bdeb96d9ada820 (diff)
downloadllvm-e2182a6b91f5001bd9b52e3b1fe6beac434e5fe5.zip
llvm-e2182a6b91f5001bd9b52e3b1fe6beac434e5fe5.tar.gz
llvm-e2182a6b91f5001bd9b52e3b1fe6beac434e5fe5.tar.bz2
[Mips] Fix unable to handle inline assembly ends with compat-branch o… (#77291)
…n MIPS Modify: Add a global variable 'CurForbiddenSlotAttr' to save current instruction's forbidden slot and whether set reorder. This is the judgment condition for whether to add nop. We would add a couple of '.set noreorder' and '.set reorder' to wrap the current instruction and the next instruction. Then we can get previous instruction`s forbidden slot attribute and whether set reorder by 'CurForbiddenSlotAttr'. If previous instruction has forbidden slot and .set reorder is active and current instruction is CTI. Then emit a NOP after it. Fix https://github.com/llvm/llvm-project/issues/61045. Because https://reviews.llvm.org/D158589 was 'Needs Review' state, not ending, so we commit pull request again. (cherry picked from commit 96abee5eef31274415681018553e1d4a16dc16c9)
-rw-r--r--lld/test/ELF/mips-pc-relocs.s18
-rw-r--r--llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp78
-rw-r--r--llvm/test/CodeGen/Mips/llvm-ir/forbidden-slot-ir.ll71
-rw-r--r--llvm/test/MC/Mips/forbidden-slot.s18
-rw-r--r--llvm/test/MC/Mips/mips32r6/relocations.s22
-rw-r--r--llvm/test/MC/Mips/mips64r6/relocations.s26
-rw-r--r--llvm/test/MC/Mips/relocation.s4
7 files changed, 202 insertions, 35 deletions
diff --git a/lld/test/ELF/mips-pc-relocs.s b/lld/test/ELF/mips-pc-relocs.s
index 5e7dbed..7d23f9d 100644
--- a/lld/test/ELF/mips-pc-relocs.s
+++ b/lld/test/ELF/mips-pc-relocs.s
@@ -40,11 +40,13 @@ __start:
# ^-- (0x20020-0x20000)>>2
# CHECK-NEXT: 20004: beqc $5, $6, 0x20020
# ^-- (0x20020-4-0x20004)>>2
-# CHECK-NEXT: 20008: beqzc $9, 0x20020
-# ^-- (0x20020-4-0x20008)>>2
-# CHECK-NEXT: 2000c: bc 0x20020
-# ^-- (0x20020-4-0x2000c)>>2
-# CHECK-NEXT: 20010: aluipc $2, 0
-# ^-- %hi(0x20020-0x20010)
-# CHECK-NEXT: 20014: addiu $2, $2, 12
-# ^-- %lo(0x20020-0x20014)
+# CHECK-NEXT: 20008: nop
+# CHECK-NEXT: 2000c: beqzc $9, 0x20020
+# ^-- (0x20020-4-0x2000c)>>2
+# CHECK-NEXT: 20010: nop
+# CHECK-NEXT: 20014: bc 0x20020
+# ^-- (0x20020-4-0x200014)>>2
+# CHECK-NEXT: 20018: aluipc $2, 0
+# ^-- %hi(0x20020-0x20018)
+# CHECK-NEXT: 2001c: addiu $2, $2, 4
+# ^-- %lo(0x20020-0x2001c)
diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
index 36aab38..9d6e8dc 100644
--- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
+++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
@@ -150,6 +150,7 @@ class MipsAsmParser : public MCTargetAsmParser {
bool IsLittleEndian;
bool IsPicEnabled;
bool IsCpRestoreSet;
+ bool CurForbiddenSlotAttr;
int CpRestoreOffset;
unsigned GPReg;
unsigned CpSaveLocation;
@@ -552,6 +553,7 @@ public:
CurrentFn = nullptr;
+ CurForbiddenSlotAttr = false;
IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();
IsCpRestoreSet = false;
@@ -723,6 +725,16 @@ public:
return getSTI().hasFeature(Mips::FeatureGINV);
}
+ bool hasForbiddenSlot(const MCInstrDesc &MCID) const {
+ return !inMicroMipsMode() && (MCID.TSFlags & MipsII::HasForbiddenSlot);
+ }
+
+ bool SafeInForbiddenSlot(const MCInstrDesc &MCID) const {
+ return !(MCID.TSFlags & MipsII::IsCTI);
+ }
+
+ void onEndOfFile() override;
+
/// Warn if RegIndex is the same as the current AT.
void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
@@ -2307,7 +2319,41 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
bool FillDelaySlot =
MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
- if (FillDelaySlot)
+
+ // Get previous instruction`s forbidden slot attribute and
+ // whether set reorder.
+ bool PrevForbiddenSlotAttr = CurForbiddenSlotAttr;
+
+ // Flag represents we set reorder after nop.
+ bool SetReorderAfterNop = false;
+
+ // If previous instruction has forbidden slot and .set reorder
+ // is active and current instruction is CTI.
+ // Then emit a NOP after it.
+ if (PrevForbiddenSlotAttr && !SafeInForbiddenSlot(MCID)) {
+ TOut.emitEmptyDelaySlot(false, IDLoc, STI);
+ // When 'FillDelaySlot' is true, the existing logic will add
+ // noreorder before instruction and reorder after it. So there
+ // need exclude this case avoiding two '.set reorder'.
+ // The format of the first case is:
+ // .set noreorder
+ // bnezc
+ // nop
+ // .set reorder
+ if (AssemblerOptions.back()->isReorder() && !FillDelaySlot) {
+ SetReorderAfterNop = true;
+ TOut.emitDirectiveSetReorder();
+ }
+ }
+
+ // Save current instruction`s forbidden slot and whether set reorder.
+ // This is the judgment condition for whether to add nop.
+ // We would add a couple of '.set noreorder' and '.set reorder' to
+ // wrap the current instruction and the next instruction.
+ CurForbiddenSlotAttr =
+ hasForbiddenSlot(MCID) && AssemblerOptions.back()->isReorder();
+
+ if (FillDelaySlot || CurForbiddenSlotAttr)
TOut.emitDirectiveSetNoReorder();
MacroExpanderResultTy ExpandResult =
@@ -2322,6 +2368,17 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
return true;
}
+ // When current instruction was not CTI, recover reorder state.
+ // The format of the second case is:
+ // .set noreoder
+ // bnezc
+ // add
+ // .set reorder
+ if (PrevForbiddenSlotAttr && !SetReorderAfterNop && !FillDelaySlot &&
+ AssemblerOptions.back()->isReorder()) {
+ TOut.emitDirectiveSetReorder();
+ }
+
// We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
// If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
if (inMicroMipsMode()) {
@@ -2331,6 +2388,14 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
// If this instruction has a delay slot and .set reorder is active,
// emit a NOP after it.
+ // The format of the third case is:
+ // .set noreorder
+ // bnezc
+ // nop
+ // .set noreorder
+ // j
+ // nop
+ // .set reorder
if (FillDelaySlot) {
TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst), IDLoc, STI);
TOut.emitDirectiveSetReorder();
@@ -2356,6 +2421,17 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
return false;
}
+void MipsAsmParser::onEndOfFile() {
+ MipsTargetStreamer &TOut = getTargetStreamer();
+ SMLoc IDLoc = SMLoc();
+ // If has pending forbidden slot, fill nop and recover reorder.
+ if (CurForbiddenSlotAttr) {
+ TOut.emitEmptyDelaySlot(false, IDLoc, STI);
+ if (AssemblerOptions.back()->isReorder())
+ TOut.emitDirectiveSetReorder();
+ }
+}
+
MipsAsmParser::MacroExpanderResultTy
MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
const MCSubtargetInfo *STI) {
diff --git a/llvm/test/CodeGen/Mips/llvm-ir/forbidden-slot-ir.ll b/llvm/test/CodeGen/Mips/llvm-ir/forbidden-slot-ir.ll
new file mode 100644
index 0000000..3e6826f
--- /dev/null
+++ b/llvm/test/CodeGen/Mips/llvm-ir/forbidden-slot-ir.ll
@@ -0,0 +1,71 @@
+target triple = "mipsisa32r6el-unknown-linux-gnu"
+
+; RUN: llc -filetype=asm %s -o - | FileCheck %s --check-prefix=MIPSELR6
+; Function Attrs: noinline nounwind optnone uwtable
+define i1 @foo0() nounwind {
+; MIPSELR6: bnezc $1, $BB0_2
+; MIPSELR6-NEXT: nop
+; MIPSELR6: jr $ra
+entry:
+ %0 = icmp eq i32 0, 1
+ br i1 %0, label %2, label %3
+ ret i1 %0
+2:
+ ret i1 %0
+3:
+ ret i1 %0
+}
+
+define i32 @foo1() nounwind {
+; MIPSELR6: addiu $2, $2, 1
+; MIPSELR6-NEXT: .set noreorder
+; MIPSELR6-NEXT: beqzc $2, $tmp0
+; MIPSELR6-NEXT: nop
+; MIPSELR6-NEXT: .set reorder
+; MIPSELR6: jrc $ra
+entry:
+ %0 = tail call i32 asm "1: addiu $0, $0, 1; beqzc $0, 1b", "=r"() nounwind
+ ret i32 %0
+}
+
+define i32 @foo2() nounwind {
+; MIPSELR6: .set push
+; MIPSELR6-NEXT: .set at
+; MIPSELR6-NEXT: .set macro
+; MIPSELR6-NEXT: .set reorder
+; MIPSELR6: .set noreorder
+; MIPSELR6-NEXT: beqzc $9, End
+; MIPSELR6-NEXT: nop
+; MIPSELR6-NEXT: .set reorder
+; MIPSELR6: addiu $9, $9, 1
+entry:
+ %0 = tail call i32 asm "beqzc $$t1, End", "=r"() nounwind
+ %1 = tail call i32 asm "addiu $$t1, $$t1, 1", "=r"() nounwind
+ %2 = add nsw i32 %1, %0
+ ret i32 %2
+}
+
+define i32 @foo3() nounwind {
+; MIPSELR6: addiu $2, $2, 1
+; MIPSELR6-NEXT: .set noreorder
+; MIPSELR6-NEXT: beqzc $2, $tmp1
+; MIPSELR6-NEXT: nop
+; MIPSELR6-NEXT: .set noreorder
+; MIPSELR6-NEXT: j End
+; MIPSELR6-NEXT: nop
+; MIPSELR6-NEXT: .set reorder
+entry:
+ %0 = tail call i32 asm "1: addiu $0, $0, 1; beqzc $0, 1b; j End", "=r"() nounwind
+ ret i32 %0
+}
+
+define i32 @foo4() nounwind {
+; MIPSELR6: addiu $2, $2, 1
+; MIPSELR6-NEXT: .set noreorder
+; MIPSELR6-NEXT: beqzc $2, $tmp2
+; MIPSELR6-NEXT: addiu $2, $2, 1
+; MIPSELR6-NEXT: .set reorder
+entry:
+ %0 = tail call i32 asm "1: addiu $0, $0, 1; beqzc $0, 1b; addiu $0, $0, 1", "=r"() nounwind
+ ret i32 %0
+}
diff --git a/llvm/test/MC/Mips/forbidden-slot.s b/llvm/test/MC/Mips/forbidden-slot.s
new file mode 100644
index 0000000..da98e70
--- /dev/null
+++ b/llvm/test/MC/Mips/forbidden-slot.s
@@ -0,0 +1,18 @@
+# RUN: llvm-mc -assemble -mcpu=mips64r6 -arch=mips64el -filetype=obj %s -o tmp.o
+# RUN: llvm-objdump -d tmp.o | FileCheck %s --check-prefix=MIPSELR6
+
+# MIPSELR6: 0000000000000000 <aaa>:
+# MIPSELR6-NEXT: beqzc $13, 0x0 <aaa>
+# MIPSELR6-NEXT: b 0x0 <aaa>
+# MIPSELR6: 0000000000000008 <bbb>:
+# MIPSELR6-NEXT: beqzc $13, 0x8 <bbb>
+# MIPSELR6-NEXT: nop <aaa>
+# MIPSELR6: b 0x8 <bbb>
+ .set noreorder
+aaa:
+ beqzc $t1, aaa
+ b aaa
+ .set reorder
+bbb:
+ beqzc $t1, bbb
+ b bbb
diff --git a/llvm/test/MC/Mips/mips32r6/relocations.s b/llvm/test/MC/Mips/mips32r6/relocations.s
index dfd75e6..8d4464b 100644
--- a/llvm/test/MC/Mips/mips32r6/relocations.s
+++ b/llvm/test/MC/Mips/mips32r6/relocations.s
@@ -52,17 +52,17 @@
# CHECK-ELF: Relocations [
# CHECK-ELF: 0x0 R_MIPS_PC19_S2 bar
# CHECK-ELF: 0x4 R_MIPS_PC16 bar
-# CHECK-ELF: 0x8 R_MIPS_PC16 bar
-# CHECK-ELF: 0xC R_MIPS_PC21_S2 bar
-# CHECK-ELF: 0x10 R_MIPS_PC21_S2 bar
-# CHECK-ELF: 0x14 R_MIPS_PC26_S2 bar
-# CHECK-ELF: 0x18 R_MIPS_PC26_S2 bar
-# CHECK-ELF: 0x1C R_MIPS_PCHI16 bar
-# CHECK-ELF: 0x20 R_MIPS_PCLO16 bar
-# CHECK-ELF: 0x24 R_MIPS_PC19_S2 bar
-# CHECK-ELF: 0x28 R_MIPS_PC19_S2 bar
-# CHECK-ELF: 0x2C R_MIPS_LO16 bar
-# CHECK-ELF: 0x30 R_MIPS_LO16 bar
+# CHECK-ELF: 0xC R_MIPS_PC16 bar
+# CHECK-ELF: 0x14 R_MIPS_PC21_S2 bar
+# CHECK-ELF: 0x1C R_MIPS_PC21_S2 bar
+# CHECK-ELF: 0x24 R_MIPS_PC26_S2 bar
+# CHECK-ELF: 0x28 R_MIPS_PC26_S2 bar
+# CHECK-ELF: 0x2C R_MIPS_PCHI16 bar
+# CHECK-ELF: 0x30 R_MIPS_PCLO16 bar
+# CHECK-ELF: 0x34 R_MIPS_PC19_S2 bar
+# CHECK-ELF: 0x38 R_MIPS_PC19_S2 bar
+# CHECK-ELF: 0x3C R_MIPS_LO16 bar
+# CHECK-ELF: 0x40 R_MIPS_LO16 bar
# CHECK-ELF: ]
addiupc $2,bar
diff --git a/llvm/test/MC/Mips/mips64r6/relocations.s b/llvm/test/MC/Mips/mips64r6/relocations.s
index 8353ec0..8b02be3 100644
--- a/llvm/test/MC/Mips/mips64r6/relocations.s
+++ b/llvm/test/MC/Mips/mips64r6/relocations.s
@@ -59,19 +59,19 @@
# CHECK-ELF: Relocations [
# CHECK-ELF: 0x0 R_MIPS_PC19_S2/R_MIPS_NONE/R_MIPS_NONE bar 0x0
# CHECK-ELF: 0x4 R_MIPS_PC16/R_MIPS_NONE/R_MIPS_NONE bar 0xFFFFFFFFFFFFFFFC
-# CHECK-ELF: 0x8 R_MIPS_PC16/R_MIPS_NONE/R_MIPS_NONE bar 0xFFFFFFFFFFFFFFFC
-# CHECK-ELF: 0xC R_MIPS_PC21_S2/R_MIPS_NONE/R_MIPS_NONE bar 0xFFFFFFFFFFFFFFFC
-# CHECK-ELF: 0x10 R_MIPS_PC21_S2/R_MIPS_NONE/R_MIPS_NONE bar 0xFFFFFFFFFFFFFFFC
-# CHECK-ELF: 0x14 R_MIPS_PC26_S2/R_MIPS_NONE/R_MIPS_NONE bar 0xFFFFFFFFFFFFFFFC
-# CHECK-ELF: 0x18 R_MIPS_PC26_S2/R_MIPS_NONE/R_MIPS_NONE bar 0xFFFFFFFFFFFFFFFC
-# CHECK-ELF: 0x1C R_MIPS_PCHI16/R_MIPS_NONE/R_MIPS_NONE bar 0x0
-# CHECK-ELF: 0x20 R_MIPS_PCLO16/R_MIPS_NONE/R_MIPS_NONE bar 0x0
-# CHECK-ELF: 0x24 R_MIPS_PC19_S2/R_MIPS_NONE/R_MIPS_NONE bar 0x0
-# CHECK-ELF: 0x28 R_MIPS_PC18_S3/R_MIPS_NONE/R_MIPS_NONE bar 0x0
-# CHECK-ELF: 0x2C R_MIPS_PC19_S2/R_MIPS_NONE/R_MIPS_NONE bar 0x0
-# CHECK-ELF: 0x30 R_MIPS_PC19_S2/R_MIPS_NONE/R_MIPS_NONE bar 0x0
-# CHECK-ELF: 0x34 R_MIPS_LO16/R_MIPS_NONE/R_MIPS_NONE bar 0x0
-# CHECK-ELF: 0x38 R_MIPS_LO16/R_MIPS_NONE/R_MIPS_NONE bar 0x0
+# CHECK-ELF: 0xC R_MIPS_PC16/R_MIPS_NONE/R_MIPS_NONE bar 0xFFFFFFFFFFFFFFFC
+# CHECK-ELF: 0x14 R_MIPS_PC21_S2/R_MIPS_NONE/R_MIPS_NONE bar 0xFFFFFFFFFFFFFFFC
+# CHECK-ELF: 0x1C R_MIPS_PC21_S2/R_MIPS_NONE/R_MIPS_NONE bar 0xFFFFFFFFFFFFFFFC
+# CHECK-ELF: 0x24 R_MIPS_PC26_S2/R_MIPS_NONE/R_MIPS_NONE bar 0xFFFFFFFFFFFFFFFC
+# CHECK-ELF: 0x28 R_MIPS_PC26_S2/R_MIPS_NONE/R_MIPS_NONE bar 0xFFFFFFFFFFFFFFFC
+# CHECK-ELF: 0x2C R_MIPS_PCHI16/R_MIPS_NONE/R_MIPS_NONE bar 0x0
+# CHECK-ELF: 0x30 R_MIPS_PCLO16/R_MIPS_NONE/R_MIPS_NONE bar 0x0
+# CHECK-ELF: 0x34 R_MIPS_PC19_S2/R_MIPS_NONE/R_MIPS_NONE bar 0x0
+# CHECK-ELF: 0x38 R_MIPS_PC18_S3/R_MIPS_NONE/R_MIPS_NONE bar 0x0
+# CHECK-ELF: 0x3C R_MIPS_PC19_S2/R_MIPS_NONE/R_MIPS_NONE bar 0x0
+# CHECK-ELF: 0x40 R_MIPS_PC19_S2/R_MIPS_NONE/R_MIPS_NONE bar 0x0
+# CHECK-ELF: 0x44 R_MIPS_LO16/R_MIPS_NONE/R_MIPS_NONE bar 0x0
+# CHECK-ELF: 0x48 R_MIPS_LO16/R_MIPS_NONE/R_MIPS_NONE bar 0x0
# CHECK-ELF: ]
addiupc $2,bar
diff --git a/llvm/test/MC/Mips/relocation.s b/llvm/test/MC/Mips/relocation.s
index 9c8bb65..a92c627 100644
--- a/llvm/test/MC/Mips/relocation.s
+++ b/llvm/test/MC/Mips/relocation.s
@@ -237,7 +237,7 @@ baz: .long foo // RELOC: R_MIPS_32 foo
// ENCLE: addiu $2, $3, %tprel_lo(foo) # encoding: [A,A,0x62,0x24]
// FIXUP: # fixup A - offset: 0, value: %tprel_lo(foo), kind: fixup_Mips_TPREL_LO
-// DATA-NEXT: 00C0: D85FFFFF CBFFFFFF EC580000 EC480000
+// DATA-NEXT: 00C0: D85FFFFF 00000000 CBFFFFFF EC580000
// ?????: R_MIPS_GLOB_DAT foo
.set mips32r6
beqzc $2, foo // RELOC: R_MIPS_PC21_S2 foo
@@ -262,7 +262,7 @@ baz: .long foo // RELOC: R_MIPS_32 foo
// ENCLE: lwpc $2, foo # encoding: [A,A,0b01001AAA,0xec]
// FIXUP: # fixup A - offset: 0, value: foo, kind: fixup_MIPS_PC19_S2
-// DATA-NEXT: 00D0: 24620000 24620000 00000000
+// DATA-NEXT: 00D0: EC480000 24620000 24620000 00000000
addiu $2, $3, %pcrel_hi(foo) // RELOC: R_MIPS_PCHI16 foo
// ENCBE: addiu $2, $3, %pcrel_hi(foo) # encoding: [0x24,0x62,A,A]
// ENCLE: addiu $2, $3, %pcrel_hi(foo) # encoding: [A,A,0x62,0x24]