RISC-V: Fix weak symbols with medany and explicit relocs.

Message ID 20180925225315.21675-1-jimw@sifive.com
State New
Headers show
  • RISC-V: Fix weak symbols with medany and explicit relocs.
Related show

Commit Message

Jim Wilson Sept. 25, 2018, 10:53 p.m.
When using -mcmodel=medany -mexplicit-relocs, weak symbol references aren't
handled correctly.  The conditional test gets optimized away by the compiler.

The problem is with the RTL generated for the instruction pair for a symbol
reference, where the lo part insn only has a label pointing at the high part
insn.  The optimizer sees that the weak symbol test against zero refers to a
code label which is guaranteed to be non-zero, and hence optimizes away the
test.  As a short term solution, we can get the right result if we mark the
code label as weak.  Longer term, we need to change how these insn patterns
work to solve this problem and other optimization problems.  That solution
hasn't been defined yet.

This was tested with riscv32-elf and riscv64-linux toolchain builds and tests.
There were no regressions.  The new testcase fails without the patch and works
with the patch.  This has also been tested with toolchain builds with the
compiler modified to use -mcmodel=medany -mexplicit-relocs by default.  This
fails badly without the patch as there are weak symbols in start files, and
works OK with the patch.



	* config/riscv/riscv.c (riscv_split_symbol): Mark auipc label as weak
	when target symbol is weak.

	* gcc.target/riscv/weak-1.c: New.
 gcc/config/riscv/riscv.c                |  5 +++++
 gcc/testsuite/gcc.target/riscv/weak-1.c | 14 ++++++++++++++
 2 files changed, 19 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/riscv/weak-1.c



diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c
index 9d6d981a42a..381a203da9b 100644
--- a/gcc/config/riscv/riscv.c
+++ b/gcc/config/riscv/riscv.c
@@ -1103,6 +1103,11 @@  riscv_split_symbol (rtx temp, rtx addr, machine_mode mode, rtx *low_out)
 	  label = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
+	  /* ??? Ugly hack to make weak symbols work.  May need to change the
+	     RTL for the auipc and/or low patterns to get a better fix for
+	     this.  */
+	  if (! nonzero_address_p (addr))
+	    SYMBOL_REF_WEAK (label) = 1;
 	  if (temp == NULL)
 	    temp = gen_reg_rtx (Pmode);
diff --git a/gcc/testsuite/gcc.target/riscv/weak-1.c b/gcc/testsuite/gcc.target/riscv/weak-1.c
new file mode 100644
index 00000000000..0f20501f7c5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/weak-1.c
@@ -0,0 +1,14 @@ 
+/* { dg-do compile } */
+/* { dg-options "-mcmodel=medany -mexplicit-relocs -O" } */
+/* Verify that the branch doesn't get optimized away.  */
+extern int weak_func(void) __attribute__ ((weak));
+sub (void)
+  if (weak_func)
+    return weak_func ();
+  return 0;
+/* { dg-final { scan-assembler "b\(ne|eq\)" } } */