Hi,

aarch64_build_constant incorrectly truncates the immediate when
constants are generated with MOVN. This causes coinor-osi tests to fail
(tracked also in https://bugs.launchpad.net/gcc-linaro/+bug/1263576)

Attached patch fixes this. Also attaching a reduced testcase that
reproduces this. Tested on aarch64-none-linux-gnu with no new
regressions. Is this OK for trunk?

Thanks,
Kugan

gcc/
+2013-10-15  Matthew Gretton-Dann  <matthew.gretton-d...@linaro.org>
+           Kugan Vivekanandarajah  <kug...@linaro.org>
+
+       PR target/59588
+       * config/aarch64/aarch64.c (aarch64_build_constant): Fix incorrect
+       truncation.
+


gcc/testsuite/
+2014-01-11  Matthew Gretton-Dann  <matthew.gretton-d...@linaro.org>
+           Kugan Vivekanandarajah  <kug...@linaro.org>
+
+       PR target/59695
+       * g++.dg/pr59695.C: New file.
+
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 3d32ea5..854666f 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -2486,7 +2486,7 @@ aarch64_build_constant (int regnum, HOST_WIDE_INT val)
       if (ncount < zcount)
        {
          emit_move_insn (gen_rtx_REG (Pmode, regnum),
-                         GEN_INT ((~val) & 0xffff));
+                         GEN_INT (~((~val) & 0xffff)));
          tval = 0xffff;
        }
       else
diff --git a/gcc/testsuite/g++.dg/pr59695.C b/gcc/testsuite/g++.dg/pr59695.C
index e69de29..0da06cb 100644
--- a/gcc/testsuite/g++.dg/pr59695.C
+++ b/gcc/testsuite/g++.dg/pr59695.C
@@ -0,0 +1,125 @@
+
+/* PR target/53055 */
+/* { dg-do run { target aarch64*-*-* } } */
+/* { dg-options "-O0" } */
+
+#define  DEFINE_VIRTUALS_FNS(i)        virtual void  xxx##i () {} \
+  virtual void  foo1_##i ()    {}\
+  virtual void  foo2_##i ()    {}\
+  virtual void  foo3_##i ()    {}\
+  virtual void  foo4_##i ()    {}\
+  virtual void  foo5_##i ()    {}\
+  virtual void  foo6_##i ()    {}\
+  virtual void  foo7_##i ()    {}\
+  virtual void  foo8_##i ()    {}\
+  virtual void  foo9_##i ()    {}\
+  virtual void  foo10_##i ()   {}\
+  virtual void  foo11_##i ()   {}\
+  virtual void  foo12_##i ()   {}\
+  virtual void  foo13_##i ()   {}\
+  virtual void  foo14_##i ()   {}\
+  virtual void  foo15_##i ()   {}\
+  virtual void  foo16_##i ()   {}\
+  virtual void  foo17_##i ()   {}\
+  virtual void  foo18_##i ()   {}\
+  virtual void  foo19_##i ()   {}\
+  virtual void  foo20_##i ()   {}\
+  virtual void  foo21_##i ()   {}\
+  virtual void  foo22_##i ()   {}\
+
+class base_class_2
+{
+
+public:
+  /* Define lots of virtual functions */
+  DEFINE_VIRTUALS_FNS (1)
+  DEFINE_VIRTUALS_FNS (2)
+  DEFINE_VIRTUALS_FNS (3)
+  DEFINE_VIRTUALS_FNS (4)
+  DEFINE_VIRTUALS_FNS (5)
+  DEFINE_VIRTUALS_FNS (6)
+  DEFINE_VIRTUALS_FNS (7)
+  DEFINE_VIRTUALS_FNS (8)
+  DEFINE_VIRTUALS_FNS (9)
+  DEFINE_VIRTUALS_FNS (10)
+  DEFINE_VIRTUALS_FNS (11)
+  DEFINE_VIRTUALS_FNS (12)
+  DEFINE_VIRTUALS_FNS (13)
+  DEFINE_VIRTUALS_FNS (14)
+  DEFINE_VIRTUALS_FNS (15)
+  DEFINE_VIRTUALS_FNS (16)
+  DEFINE_VIRTUALS_FNS (17)
+  DEFINE_VIRTUALS_FNS (18)
+  DEFINE_VIRTUALS_FNS (19)
+  DEFINE_VIRTUALS_FNS (20)
+
+  base_class_2();
+  virtual ~base_class_2 ();
+};
+
+base_class_2::base_class_2()
+{
+}
+
+base_class_2::~base_class_2 ()
+{
+}
+
+class base_class_1
+{
+public:
+  virtual ~base_class_1();
+  base_class_1();
+};
+
+base_class_1::base_class_1()
+{
+}
+
+base_class_1::~base_class_1()
+{
+}
+
+class base_Impl_class :
+  virtual public base_class_2, public base_class_1
+{
+public:
+  base_Impl_class ();
+  virtual ~base_Impl_class ();
+};
+
+base_Impl_class::base_Impl_class ()
+{
+}
+
+base_Impl_class::~base_Impl_class ()
+{
+}
+
+
+class test_cls : public base_Impl_class
+{
+public:
+  test_cls();
+  virtual ~test_cls();
+};
+
+test_cls::test_cls()
+{
+}
+
+test_cls::~test_cls()
+{
+}
+
+int main()
+{
+  test_cls *test = new test_cls;
+  base_class_2 *p1 = test;
+
+  /* PR 53055  destructor thunk offsets are not setup
+   correctly resulting in crash.  */
+  delete p1;
+  return 0;
+}
+

Reply via email to