Commits

David Schneider committed 4132424

refactor load, store and move helper methods.

Use imm offsets for VLDR and VSTR if possible

  • Participants
  • Parent commits 4c8a771
  • Branches jitframe-on-heap

Comments (0)

Files changed (2)

rpython/jit/backend/arm/assembler.py

         faildescr._arm_failure_recovery_block = 0
 
     # regalloc support
-    def load_reg(self, mc, target, base, ofs, cond=c.AL, helper=r.ip):
-        if target.is_vfp_reg():
-            return self._load_vfp_reg(mc, target, base, ofs, cond)
-        elif target.is_reg():
-            return self._load_core_reg(mc, target, base, ofs, cond)
-
-    def _load_vfp_reg(self, mc, target, base, ofs, cond=c.AL, helper=r.ip):
-        if check_imm_arg(ofs):
-            mc.VLDR(target.value, base.value, imm=ofs, cond=cond)
-        else:
-            mc.gen_load_int(helper.value, ofs)
-            mc.VLDR(target.value, base.value, helper.value, cond=cond)
-
-    def _load_core_reg(self, mc, target, base, ofs, cond=c.AL, helper=r.ip):
-        if check_imm_arg(ofs):
-            mc.LDR_ri(target.value, base.value, imm=ofs, cond=cond)
-        else:
-            mc.gen_load_int(helper.value, ofs)
-            mc.LDR_rr(target.value, base.value, helper.value, cond=cond)
-
-    def store_reg(self, mc, source, base, ofs, cond=c.AL, helper=r.ip):
-        if source.is_vfp_reg():
-            return self._store_vfp_reg(mc, source, base, ofs, cond)
-        else:
-            return self._store_core_reg(mc, source, base, ofs, cond)
-
-    def _store_vfp_reg(self, mc, source, base, ofs, cond=c.AL, helper=r.ip):
-        if check_imm_arg(ofs):
-            mc.VSTR(source.value, base.value, imm=ofs, cond=cond)
-        else:
-            mc.gen_load_int(helper.value, ofs)
-            mc.VSTR(source.value, base.value, helper.value, cond=cond)
-
-    def _store_core_reg(self, mc, source, base, ofs, cond=c.AL, helper=r.ip):
-        if check_imm_arg(ofs):
-            mc.STR_ri(source.value, base.value, imm=ofs, cond=cond)
-        else:
-            gen_load_int(helper.value, ofs)
-            mc.STR_rr(source.value, base.value, helper.value, cond=cond)
-
     def load(self, loc, value):
+        """load an immediate value into a register"""
         assert (loc.is_reg() and value.is_imm()
                     or loc.is_vfp_reg() and value.is_imm_float())
         if value.is_imm():
             self.mc.gen_load_int(r.ip.value, value.getint())
             self.mc.VLDR(loc.value, r.ip.value)
 
+    def load_reg(self, mc, target, base, ofs, cond=c.AL, helper=r.ip):
+        if target.is_vfp_reg():
+            return self._load_vfp_reg(mc, target, base, ofs, cond, helper)
+        elif target.is_reg():
+            return self._load_core_reg(mc, target, base, ofs, cond, helper)
+
+    def _load_vfp_reg(self, mc, target, base, ofs, cond=c.AL, helper=r.ip):
+        if check_imm_arg(ofs):
+            mc.VLDR(target.value, base.value, imm=ofs, cond=cond)
+        else:
+            mc.gen_load_int(helper.value, ofs, cond=cond)
+            mc.ADD_rr(helper.value, base.value, helper.value, cond=cond)
+            mc.VLDR(target.value, helper.value, cond=cond)
+
+    def _load_core_reg(self, mc, target, base, ofs, cond=c.AL, helper=r.ip):
+        if check_imm_arg(ofs):
+            mc.LDR_ri(target.value, base.value, imm=ofs, cond=cond)
+        else:
+            mc.gen_load_int(helper.value, ofs, cond=cond)
+            mc.LDR_rr(target.value, base.value, helper.value, cond=cond)
+
+    def store_reg(self, mc, source, base, ofs, cond=c.AL, helper=r.ip):
+        if source.is_vfp_reg():
+            return self._store_vfp_reg(mc, source, base, ofs, cond, helper)
+        else:
+            return self._store_core_reg(mc, source, base, ofs, cond, helper)
+
+    def _store_vfp_reg(self, mc, source, base, ofs, cond=c.AL, helper=r.ip):
+        if check_imm_arg(ofs):
+            mc.VSTR(source.value, base.value, imm=ofs, cond=cond)
+        else:
+            mc.gen_load_int(helper.value, ofs, cond=cond)
+            mc.ADD_rr(helper.value, base.value, helper.value, cond=cond)
+            mc.VSTR(source.value, helper.value, cond=cond)
+
+    def _store_core_reg(self, mc, source, base, ofs, cond=c.AL, helper=r.ip):
+        if check_imm_arg(ofs):
+            mc.STR_ri(source.value, base.value, imm=ofs, cond=cond)
+        else:
+            mc.gen_load_int(helper.value, ofs, cond=cond)
+            mc.STR_rr(source.value, base.value, helper.value, cond=cond)
+
     def _mov_imm_to_loc(self, prev_loc, loc, cond=c.AL):
         if not loc.is_reg() and not (loc.is_stack() and loc.type != FLOAT):
             raise AssertionError("invalid target for move from imm value")
             else:
                 temp = r.ip
             offset = loc.value
-            if not check_imm_arg(offset, size=0xFFF):
+            is_imm = check_imm_arg(offset, size=0xFFF)
+            if not is_imm:
                 self.mc.PUSH([temp.value], cond=cond)
-                self.mc.gen_load_int(temp.value, offset, cond=cond)
-                self.mc.STR_rr(prev_loc.value, r.fp.value,
-                                            temp.value, cond=cond)
+            self.store_reg(self.mc, prev_loc, r.fp, offset, helper=temp, cond=cond)
+            if not is_imm:
                 self.mc.POP([temp.value], cond=cond)
-            else:
-                self.mc.STR_ri(prev_loc.value, r.fp.value,
-                                            imm=offset, cond=cond)
         else:
             assert 0, 'unsupported case'
 
                 when moving from the stack'
             # unspill a core register
             offset = prev_loc.value
-            if not check_imm_arg(offset, size=0xFFF):
+            is_imm = check_imm_arg(offset, size=0xFFF)
+            if not is_imm:
                 self.mc.PUSH([r.lr.value], cond=cond)
-                pushed = True
-                self.mc.gen_load_int(r.lr.value, offset, cond=cond)
-                self.mc.LDR_rr(loc.value, r.fp.value, r.lr.value, cond=cond)
-            else:
-                self.mc.LDR_ri(loc.value, r.fp.value, imm=offset, cond=cond)
-            if pushed:
+            self.load_reg(self.mc, loc, r.fp, offset, cond=cond, helper=r.lr)
+            if not is_imm:
                 self.mc.POP([r.lr.value], cond=cond)
         elif loc.is_vfp_reg():
             assert prev_loc.type == FLOAT, 'trying to load from an \
                 incompatible location into a float register'
             # load spilled value into vfp reg
             offset = prev_loc.value
-            self.mc.PUSH([r.ip.value], cond=cond)
-            pushed = True
-            if not check_imm_arg(offset):
-                self.mc.gen_load_int(r.ip.value, offset, cond=cond)
-                self.mc.ADD_rr(r.ip.value, r.fp.value, r.ip.value, cond=cond)
-            else:
-                self.mc.ADD_ri(r.ip.value, r.fp.value, offset, cond=cond)
-            self.mc.VLDR(loc.value, r.ip.value, cond=cond)
-            if pushed:
+            is_imm = check_imm_arg(offset)
+            if not is_imm:
+                self.mc.PUSH([r.ip.value], cond=cond)
+            self.load_reg(self.mc, loc, r.fp, offset, cond=cond, helper=r.ip)
+            if not is_imm:
                 self.mc.POP([r.ip.value], cond=cond)
         else:
             assert 0, 'unsupported case'
         if loc.is_vfp_reg():
             self.mc.PUSH([r.ip.value], cond=cond)
             self.mc.gen_load_int(r.ip.value, prev_loc.getint(), cond=cond)
-            self.mc.VLDR(loc.value, r.ip.value, cond=cond)
+            self.load_reg(self.mc, loc, r.ip, 0, cond=cond)
             self.mc.POP([r.ip.value], cond=cond)
         elif loc.is_stack():
             self.regalloc_push(r.vfp_ip)
             assert loc.type == FLOAT, 'trying to store to an \
                 incompatible location from a float register'
             # spill vfp register
-            self.mc.PUSH([r.ip.value], cond=cond)
             offset = loc.value
-            if not check_imm_arg(offset):
-                self.mc.gen_load_int(r.ip.value, offset, cond=cond)
-                self.mc.ADD_rr(r.ip.value, r.fp.value, r.ip.value, cond=cond)
-            else:
-                self.mc.ADD_ri(r.ip.value, r.fp.value, offset, cond=cond)
-            self.mc.VSTR(prev_loc.value, r.ip.value, cond=cond)
-            self.mc.POP([r.ip.value], cond=cond)
+            is_imm = check_imm_arg(offset)
+            if not is_imm:
+                self.mc.PUSH([r.ip.value], cond=cond)
+            self.store_reg(self.mc, prev_loc, r.fp, offset, cond=cond)
+            if not is_imm:
+                self.mc.POP([r.ip.value], cond=cond)
         else:
             assert 0, 'unsupported case'
 
         elif vfp_loc.is_stack():
             # move from two core registers to a float stack location
             offset = vfp_loc.value
-            if not check_imm_arg(offset, size=0xFFF):
+            if not check_imm_arg(offset + WORD, size=0xFFF):
                 self.mc.PUSH([r.ip.value], cond=cond)
                 self.mc.gen_load_int(r.ip.value, offset, cond=cond)
                 self.mc.STR_rr(reg1.value, r.fp.value, r.ip.value, cond=cond)
                 self.mc.STR_rr(reg2.value, r.fp.value, r.ip.value, cond=cond)
                 self.mc.POP([r.ip.value], cond=cond)
             else:
-                assert 0, 'verify this code'
                 self.mc.STR_ri(reg1.value, r.fp.value, imm=offset, cond=cond)
                 self.mc.STR_ri(reg2.value, r.fp.value,
                                                 imm=offset + WORD, cond=cond)

rpython/jit/backend/arm/test/test_regalloc_mov.py

 
 
 def stack(i, **kwargs):
-    return StackLocation(i, get_fp_offset(i), **kwargs)
+    return StackLocation(i, get_fp_offset(0, i), **kwargs)
 
 
 def stack_float(i, **kwargs):
-    return StackLocation(i, get_fp_offset(i + 1), type=FLOAT)
+    return StackLocation(i, get_fp_offset(0, i + 1), type=FLOAT)
 
 
 def imm_float(value):
         expected = [
                 mi('PUSH', [lr.value], cond=AL),
                 mi('gen_load_int', lr.value, 100, cond=AL),
-                mi('STR_ri', lr.value, fp.value, imm=-s.value, cond=AL),
+                mi('STR_ri', lr.value, fp.value, imm=s.value, cond=AL),
                 mi('POP', [lr.value], cond=AL)]
         self.mov(val, s, expected)
 
         expected = [
                 mi('PUSH', [lr.value], cond=AL),
                 mi('gen_load_int', lr.value, 65536, cond=AL),
-                mi('STR_ri', lr.value, fp.value, imm=-s.value, cond=AL),
+                mi('STR_ri', lr.value, fp.value, imm=s.value, cond=AL),
                 mi('POP', [lr.value], cond=AL)]
 
         self.mov(val, s, expected)
         expected = [mi('PUSH', [lr.value], cond=AL),
                     mi('gen_load_int', lr.value, 100, cond=AL),
                     mi('PUSH', [ip.value], cond=AL),
-                    mi('gen_load_int', ip.value, -s.value, cond=AL),
+                    mi('gen_load_int', ip.value, s.value, cond=AL),
                     mi('STR_rr', lr.value, fp.value, ip.value, cond=AL),
                     mi('POP', [ip.value], cond=AL),
                     mi('POP', [lr.value], cond=AL)]
         expected = [mi('PUSH', [lr.value], cond=AL),
                     mi('gen_load_int', lr.value, 65536, cond=AL),
                     mi('PUSH', [ip.value], cond=AL),
-                    mi('gen_load_int', ip.value, -s.value, cond=AL),
+                    mi('gen_load_int', ip.value, s.value, cond=AL),
                     mi('STR_rr', lr.value, fp.value, ip.value, cond=AL),
                     mi('POP', [ip.value], cond=AL),
                     mi('POP', [lr.value], cond=AL)]
     def test_mov_reg_to_stack(self):
         s = stack(10)
         r6 = r(6)
-        expected = [mi('STR_ri', r6.value, fp.value, imm=-s.value, cond=AL)]
+        expected = [mi('STR_ri', r6.value, fp.value, imm=s.value, cond=AL)]
         self.mov(r6, s, expected)
 
     def test_mov_reg_to_big_stackloc(self):
         s = stack(8191)
         r6 = r(6)
         expected = [mi('PUSH', [ip.value], cond=AL),
-                    mi('gen_load_int', ip.value, -s.value, cond=AL),
+                    mi('gen_load_int', ip.value, s.value, cond=AL),
                     mi('STR_rr', r6.value, fp.value, ip.value, cond=AL),
                     mi('POP', [ip.value], cond=AL)]
         self.mov(r6, s, expected)
     def test_mov_stack_to_reg(self):
         s = stack(10)
         r6 = r(6)
-        expected = [mi('LDR_ri', r6.value, fp.value, imm=-s.value, cond=AL)]
+        expected = [mi('LDR_ri', r6.value, fp.value, imm=s.value, cond=AL)]
         self.mov(s, r6, expected)
 
     def test_mov_big_stackloc_to_reg(self):
         r6 = r(6)
         expected = [
                     mi('PUSH', [lr.value], cond=AL),
-                    mi('gen_load_int', lr.value, -s.value, cond=AL),
+                    mi('gen_load_int', lr.value, s.value, cond=AL),
                     mi('LDR_rr', r6.value, fp.value, lr.value, cond=AL),
                     mi('POP', [lr.value], cond=AL)]
         self.mov(s, r6, expected)
         expected = [
                     mi('PUSH', [ip.value], cond=AL),
                     mi('gen_load_int', ip.value, f.value, cond=AL),
-                    mi('VLDR', 5, ip.value, cond=AL),
+                    mi('VLDR', 5, ip.value, imm=0, cond=AL),
                     mi('POP', [ip.value], cond=AL)]
         self.mov(f, reg, expected)
 
     def test_mov_vfp_reg_to_stack(self):
         reg = vfp(7)
         s = stack_float(3)
-        expected = [mi('PUSH', [ip.value], cond=AL),
-                    mi('SUB_ri', ip.value, fp.value, s.value, cond=AL),
-                    mi('VSTR', reg.value, ip.value, cond=AL),
-                    mi('POP', [ip.value], cond=AL)]
+        expected = [mi('VSTR', reg.value, fp.value, imm=188, cond=AL)]
         self.mov(reg, s, expected)
 
     def test_mov_vfp_reg_to_large_stackloc(self):
         s = stack_float(800)
         expected = [mi('PUSH', [ip.value], cond=AL),
                     mi('gen_load_int', ip.value, s.value, cond=AL),
-                    mi('SUB_rr', ip.value, fp.value, ip.value, cond=AL),
+                    mi('ADD_rr', ip.value, fp.value, ip.value, cond=AL),
                     mi('VSTR', reg.value, ip.value, cond=AL),
                     mi('POP', [ip.value], cond=AL)]
         self.mov(reg, s, expected)
     def test_mov_stack_to_vfp_reg(self):
         reg = vfp(7)
         s = stack_float(3)
-        expected = [mi('PUSH', [ip.value], cond=AL),
-                    mi('SUB_ri', ip.value, fp.value, s.value, cond=AL),
-                    mi('VLDR', reg.value, ip.value, cond=AL),
-                    mi('POP', [ip.value], cond=AL)]
+        expected = [mi('VLDR', reg.value, fp.value, imm=188, cond=AL)]
         self.mov(s, reg, expected)
 
     def test_mov_big_stackloc_to_vfp_reg(self):
         s = stack_float(800)
         expected = [mi('PUSH', [ip.value], cond=AL),
                     mi('gen_load_int', ip.value, s.value, cond=AL),
-                    mi('SUB_rr', ip.value, fp.value, ip.value, cond=AL),
+                    mi('ADD_rr', ip.value, fp.value, ip.value, cond=AL),
                     mi('VSTR', reg.value, ip.value, cond=AL),
                     mi('POP', [ip.value], cond=AL)]
         self.mov(reg, s, expected)
         r1 = r(1)
         r2 = r(2)
         e = [
-            mi('LDR_ri', r1.value, fp.value, imm=-s.value, cond=AL),
-            mi('LDR_ri', r2.value, fp.value, imm=-s.value + WORD, cond=AL)]
+            mi('LDR_ri', r1.value, fp.value, imm=s.value, cond=AL),
+            mi('LDR_ri', r2.value, fp.value, imm=s.value + WORD, cond=AL)]
         self.mov(s, r1, r2, e)
 
     def test_from_big_vfp_stack(self):
         r2 = r(2)
         e = [
             mi('PUSH', [ip.value], cond=AL),
-            mi('gen_load_int', ip.value, -s.value, cond=AL),
+            mi('gen_load_int', ip.value, s.value, cond=AL),
             mi('LDR_rr', r1.value, fp.value, ip.value, cond=AL),
             mi('ADD_ri', ip.value, ip.value, imm=WORD, cond=AL),
             mi('LDR_rr', r2.value, fp.value, ip.value, cond=AL),
         r1 = r(1)
         r2 = r(2)
         e = [
-            mi('STR_ri', r1.value, fp.value, imm=-s.value, cond=AL),
-            mi('STR_ri', r2.value, fp.value, imm=-s.value + WORD, cond=AL)]
+            mi('STR_ri', r1.value, fp.value, imm=s.value, cond=AL),
+            mi('STR_ri', r2.value, fp.value, imm=s.value + WORD, cond=AL)]
         self.mov(r1, r2, s, e)
 
     def test_from_big_vfp_stack(self):
         r2 = r(2)
         e = [
             mi('PUSH', [ip.value], cond=AL),
-            mi('gen_load_int', ip.value, -s.value, cond=AL),
+            mi('gen_load_int', ip.value, s.value, cond=AL),
             mi('STR_rr', r1.value, fp.value, ip.value, cond=AL),
             mi('ADD_ri', ip.value, ip.value, imm=4, cond=AL),
             mi('STR_rr', r2.value, fp.value, ip.value, cond=AL),
         f = imm_float(7)
         e = [mi('PUSH', [ip.value], cond=AL),
             mi('gen_load_int', ip.value, 7, cond=AL),
-            mi('VLDR', vfp_ip.value, ip.value, cond=AL),
+            mi('VLDR', vfp_ip.value, ip.value, imm=0, cond=AL),
             mi('POP', [ip.value], cond=AL),
             mi('VPUSH', [vfp_ip.value], cond=AL)
             ]
 
     def test_push_stack(self):
         s = stack(7)
-        e = [mi('LDR_ri', ip.value, fp.value, imm=-s.value, cond=AL),
+        e = [mi('LDR_ri', ip.value, fp.value, imm=s.value, cond=AL),
             mi('PUSH', [ip.value], cond=AL)
             ]
         self.push(s, e)
     def test_push_big_stack(self):
         s = stack(1025)
         e = [mi('PUSH', [lr.value], cond=AL),
-            mi('gen_load_int', lr.value, -s.value, cond=AL),
+            mi('gen_load_int', lr.value, s.value, cond=AL),
             mi('LDR_rr', ip.value, fp.value, lr.value, cond=AL),
             mi('POP', [lr.value], cond=AL),
             mi('PUSH', [ip.value], cond=AL)
     def test_push_stack_float(self):
         sf = stack_float(4)
         e = [
-            mi('PUSH', [ip.value], cond=AL),
-            mi('SUB_ri', ip.value, fp.value, sf.value, cond=AL),
-            mi('VLDR', vfp_ip.value, ip.value, cond=AL),
-            mi('POP', [ip.value], cond=AL),
+            mi('VLDR', vfp_ip.value, fp.value, imm=192, cond=AL),
             mi('VPUSH', [vfp_ip.value], cond=AL),
         ]
         self.push(sf, e)
         e = [
             mi('PUSH', [ip.value], cond=AL),
             mi('gen_load_int', ip.value, sf.value, cond=AL),
-            mi('SUB_rr', ip.value, fp.value, ip.value, cond=AL),
+            mi('ADD_rr', ip.value, fp.value, ip.value, cond=AL),
             mi('VLDR', vfp_ip.value, ip.value, cond=AL),
             mi('POP', [ip.value], cond=AL),
             mi('VPUSH', [vfp_ip.value], cond=AL),
         s = stack(12)
         e = [
             mi('POP', [ip.value], cond=AL),
-            mi('STR_ri', ip.value, fp.value, imm=-s.value, cond=AL)]
+            mi('STR_ri', ip.value, fp.value, imm=s.value, cond=AL)]
         self.pop(s, e)
 
     def test_pop_big_stackloc(self):
         e = [
             mi('POP', [ip.value], cond=AL),
             mi('PUSH', [lr.value], cond=AL),
-            mi('gen_load_int', lr.value, -s.value, cond=AL),
+            mi('gen_load_int', lr.value, s.value, cond=AL),
             mi('STR_rr', ip.value, fp.value, lr.value, cond=AL),
             mi('POP', [lr.value], cond=AL)
             ]
         s = stack_float(12)
         e = [
             mi('VPOP', [vfp_ip.value], cond=AL),
-            mi('PUSH', [ip.value], cond=AL),
-            mi('SUB_ri', ip.value, fp.value, s.value, cond=AL),
-            mi('VSTR', vfp_ip.value, ip.value, cond=AL),
-            mi('POP', [ip.value], cond=AL)]
+            mi('VSTR', vfp_ip.value, fp.value, imm=s.value, cond=AL),
+            ]
         self.pop(s, e)
 
     def test_pop_big_float_stackloc(self):
             mi('VPOP', [vfp_ip.value], cond=AL),
             mi('PUSH', [ip.value], cond=AL),
             mi('gen_load_int', ip.value, s.value, cond=AL),
-            mi('SUB_rr', ip.value, fp.value, ip.value, cond=AL),
+            mi('ADD_rr', ip.value, fp.value, ip.value, cond=AL),
             mi('VSTR', vfp_ip.value, ip.value, cond=AL),
             mi('POP', [ip.value], cond=AL)]
         self.pop(s, e)