[lld] [lld][Hexagon] Fix predicated-add GOT_16_X mask lookup (PR #111896)
Brian Cain via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 10 12:07:22 PDT 2024
https://github.com/androm3da created https://github.com/llvm/llvm-project/pull/111896
When encountering an instruction like `if (p0) r0 = add(r0,##bar at GOT)`, lld would fail with:
```
ld.lld: error: unrecognized instruction for 16_X type: 0x7400C000
```
This issue was encountered while building libreadline with clang 19.1.0.
Fixes: #111876
>From c563557875c5245fb05be7b82c5ff95aa2697952 Mon Sep 17 00:00:00 2001
From: Brian Cain <bcain at quicinc.com>
Date: Thu, 10 Oct 2024 12:02:50 -0700
Subject: [PATCH] [lld][Hexagon] Fix predicated-add GOT_16_X mask lookup
When encountering an instruction like `if (p0) r0 = add(r0,##bar at GOT)`,
lld would fail with:
```
ld.lld: error: unrecognized instruction for 16_X type: 0x7400C000
```
This issue was encountered while building libreadline with clang 19.1.0.
Fixes: #111876
---
lld/ELF/Arch/Hexagon.cpp | 19 ++++++++++++++++---
lld/test/ELF/hexagon-shared.s | 19 +++++++++++++++----
2 files changed, 31 insertions(+), 7 deletions(-)
diff --git a/lld/ELF/Arch/Hexagon.cpp b/lld/ELF/Arch/Hexagon.cpp
index 5d2477cc800651..e3d2a2e688d2fd 100644
--- a/lld/ELF/Arch/Hexagon.cpp
+++ b/lld/ELF/Arch/Hexagon.cpp
@@ -181,11 +181,12 @@ static const InstructionMask r6[] = {
{0xd7000000, 0x006020e0}, {0xd8000000, 0x006020e0},
{0xdb000000, 0x006020e0}, {0xdf000000, 0x006020e0}};
+static uint32_t INST_PARSE_PACKET_END = 0x0000c000;
static bool isDuplex(uint32_t insn) {
// Duplex forms have a fixed mask and parse bits 15:14 are always
// zero. Non-duplex insns will always have at least one bit set in the
// parse field.
- return (0xC000 & insn) == 0;
+ return (INST_PARSE_PACKET_END & insn) == 0;
}
static uint32_t findMaskR6(uint32_t insn) {
@@ -216,6 +217,12 @@ static uint32_t findMaskR11(uint32_t insn) {
}
static uint32_t findMaskR16(uint32_t insn) {
+ if (isDuplex(insn))
+ return 0x03f00000;
+
+ // Clear the end-packet-parse bits:
+ insn = insn & ~INST_PARSE_PACKET_END;
+
if ((0xff000000 & insn) == 0x48000000)
return 0x061f20ff;
if ((0xff000000 & insn) == 0x49000000)
@@ -225,8 +232,14 @@ static uint32_t findMaskR16(uint32_t insn) {
if ((0xff000000 & insn) == 0xb0000000)
return 0x0fe03fe0;
- if (isDuplex(insn))
- return 0x03f00000;
+ if ((0xff802000 & insn) == 0x74000000)
+ return 0x00001fe0;
+ if ((0xff802000 & insn) == 0x74002000)
+ return 0x00001fe0;
+ if ((0xff802000 & insn) == 0x74800000)
+ return 0x00001fe0;
+ if ((0xff802000 & insn) == 0x74802000)
+ return 0x00001fe0;
for (InstructionMask i : r6)
if ((0xff000000 & insn) == i.cmpMask)
diff --git a/lld/test/ELF/hexagon-shared.s b/lld/test/ELF/hexagon-shared.s
index 747822039e839a..01f72865847056 100644
--- a/lld/test/ELF/hexagon-shared.s
+++ b/lld/test/ELF/hexagon-shared.s
@@ -42,6 +42,13 @@ r0 = add(r1,##bar at GOT)
{ r0 = add(r0,##bar at GOT)
memw(r0) = r2 }
+# R_HEX_GOT_16_X, pred add
+if (p0) r0 = add(r0,##bar at GOT)
+if (!p0) r0 = add(r0,##bar at GOT)
+{ p0 = cmp.gtu(r0, r1)
+ if (p0.new) r0 = add(r0,##bar at GOT) }
+{ p0 = cmp.gtu(r0, r1)
+ if (!p0.new) r0 = add(r0,##bar at GOT) }
# foo is local so no plt will be generated
foo:
@@ -78,12 +85,16 @@ pvar:
# PLT-NEXT: r28 = memw(r14+#0) }
# PLT-NEXT: jumpr r28 }
-# TEXT: 8c 00 01 00 0001008c
-# TEXT: { call 0x102d0 }
-# TEXT: if (p0) jump:nt 0x102d0
-# TEXT: r0 = #0 ; jump 0x102d0
+# TEXT: bc 00 01 00 000100bc
+# TEXT: { call 0x10300 }
+# TEXT: if (p0) jump:nt 0x10300
+# TEXT: r0 = #0 ; jump 0x10300
# TEXT: r0 = add(r1,##-65548)
# TEXT: r0 = add(r0,##-65548); memw(r0+#0) = r2 }
+# TEXT: if (p0) r0 = add(r0,##-65548)
+# TEXT: if (!p0) r0 = add(r0,##-65548)
+# TEXT: if (p0.new) r0 = add(r0,##-65548)
+# TEXT: if (!p0.new) r0 = add(r0,##-65548)
# GOT: .got:
# GOT: 00 00 00 00 00000000 <unknown>
More information about the llvm-commits
mailing list