@@ -407,6 +407,70 @@ let expand_builtin_inline name args res =
407407 | _ ->
408408 raise (Error (" unrecognized builtin " ^ name))
409409
410+ (* Branch relaxation *)
411+
412+ module BInfo : BRANCH_INFORMATION = struct
413+
414+ let builtin_size = function
415+ | EF_annot _ -> 0
416+ | EF_debug _ -> 0
417+ | EF_inline_asm _ -> 32 (* hope it's no more than 8 instructions *)
418+ | _ -> assert false
419+
420+ let instr_size = function
421+ | Pfmovimmd _ | Pfmovimms _ -> 8
422+ | Pbtbl (_ , tbl ) -> 12 + 4 * List. length tbl
423+ | Plabel _ | Pcfi_adjust _ | Pcfi_rel_offset _ -> 0
424+ | Pbuiltin (ef , _ , _ ) -> builtin_size ef
425+ | _ -> 4
426+
427+ let branch_overflow ~map pc lbl range =
428+ let displ = pc + 4 - map lbl in
429+ displ < - range || displ > = range
430+
431+ let need_relaxation ~map pc instr =
432+ match instr with
433+ | Pbc (_ , lbl ) | Pcbnz (_ , _ , lbl ) | Pcbz (_ , _ , lbl ) ->
434+ (* +/- 1 MB *)
435+ branch_overflow ~map pc lbl 0x100_000
436+ | Ptbnz (_ , _ , _ , lbl ) | Ptbz (_ , _ , _ , lbl ) ->
437+ (* +/- 32 KB *)
438+ branch_overflow ~map pc lbl 0x8_000
439+ | _ ->
440+ false
441+
442+ let negate_testcond = function
443+ | TCeq -> TCne | TCne -> TCeq
444+ | TChs -> TClo | TClo -> TChs
445+ | TCmi -> TCpl | TCpl -> TCmi
446+ | TChi -> TCls | TCls -> TChi
447+ | TCge -> TClt | TClt -> TCge
448+ | TCgt -> TCle | TCle -> TCgt
449+
450+ let relax_instruction instr =
451+ match instr with
452+ | Pbc (c , lbl ) ->
453+ let lbl' = new_label() in
454+ [Pbc (negate_testcond c, lbl'); Pb lbl; Plabel lbl']
455+ | Pcbnz (sz , r , lbl ) ->
456+ let lbl' = new_label() in
457+ [Pcbz (sz, r, lbl'); Pb lbl; Plabel lbl']
458+ | Pcbz (sz , r , lbl ) ->
459+ let lbl' = new_label() in
460+ [Pcbnz (sz, r, lbl'); Pb lbl; Plabel lbl']
461+ | Ptbnz (sz , r , n , lbl ) ->
462+ let lbl' = new_label() in
463+ [Ptbz (sz, r, n, lbl'); Pb lbl; Plabel lbl']
464+ | Ptbz (sz , r , n , lbl ) ->
465+ let lbl' = new_label() in
466+ [Ptbnz (sz, r, n, lbl'); Pb lbl; Plabel lbl']
467+ | _ ->
468+ assert false
469+
470+ end
471+
472+ module BRelax = Branch_relaxation (BInfo )
473+
410474(* Expansion of instructions *)
411475
412476let expand_instruction instr =
@@ -478,7 +542,8 @@ let expand_function id fn =
478542 try
479543 set_current_function fn;
480544 expand id (* sp= *) 31 preg_to_dwarf expand_instruction fn.fn_code;
481- Errors. OK (get_current_function () )
545+ let fn' = BRelax. relaxation (get_current_function () ) in
546+ Errors. OK fn'
482547 with Error s ->
483548 Errors. Error (Errors. msg s)
484549
0 commit comments