From d40f3cb1128208d901b6224b52ff36ff05680d28 Mon Sep 17 00:00:00 2001
From: Richard Henderson <rth@twiddle.net>
Date: Sat, 31 Aug 2013 06:13:49 -0700
Subject: [PATCH] tcg-ppc64: Fold constant call address into descriptor load

Eliminates one insn per call:

 :  lis     r2,4165
-:  ori     r2,r2,59616
-:  ld      r0,0(r2)
+:  ld      r0,-5920(r2)
 :  mtctr   r0
-:  ld      r2,8(r2)
+:  ld      r2,-5912(r2)
 :  bctrl

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 tcg/ppc64/tcg-target.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index 5ac62bf40d..8eb04060e6 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -713,16 +713,24 @@ static void tcg_out_call(TCGContext *s, tcg_target_long arg, int const_arg)
         tcg_out32(s, BCLR | BO_ALWAYS | LK);
     }
 #else
-    int reg = arg;
+    TCGReg reg = arg;
+    int ofs = 0;
 
     if (const_arg) {
+        /* Fold the low bits of the constant into the addresses below.  */
+        ofs = (int16_t)arg;
+        if (ofs + 8 < 0x8000) {
+            arg -= ofs;
+        } else {
+            ofs = 0;
+        }
         reg = TCG_REG_R2;
         tcg_out_movi(s, TCG_TYPE_I64, reg, arg);
     }
 
-    tcg_out32(s, LD | TAI(TCG_REG_R0, reg, 0));
+    tcg_out32(s, LD | TAI(TCG_REG_R0, reg, ofs));
     tcg_out32(s, MTSPR | RA(TCG_REG_R0) | CTR);
-    tcg_out32(s, LD | TAI(TCG_REG_R2, reg, 8));
+    tcg_out32(s, LD | TAI(TCG_REG_R2, reg, ofs + 8));
     tcg_out32(s, BCCTR | BO_ALWAYS | LK);
 #endif
 }
-- 
2.30.2