Hi!
Please find attached the patch to fix bug in branches with offsets over 1MiB.
There has been an attempt to fix this issue in commit
050af05b9761f1979f11c151519e7244d5becd7c
However, the far_branch attribute defined in above patch used
insn_length - which computes incorrect offset. Hence, eliminated the
attribute completely, and computed the offset from insn_addresses
instead.
Ok for trunk?
gcc/Changelog
2018-02-13 Sameera Deshpande <[email protected]>
* config/aarch64/aarch64.md (far_branch): Remove attribute. Eliminate
all the dependencies on the attribute from RTL patterns.
--
- Thanks and regards,
Sameera D.
Index: gcc/config/aarch64/aarch64.md
===================================================================
--- gcc/config/aarch64/aarch64.md (revision 257620)
+++ gcc/config/aarch64/aarch64.md (working copy)
@@ -244,13 +244,6 @@
(const_string "no")
] (const_string "yes")))
-;; Attribute that specifies whether we are dealing with a branch to a
-;; label that is far away, i.e. further away than the maximum/minimum
-;; representable in a signed 21-bits number.
-;; 0 :=: no
-;; 1 :=: yes
-(define_attr "far_branch" "" (const_int 0))
-
;; Strictly for compatibility with AArch32 in pipeline models, since AArch64 has
;; no predicated insns.
(define_attr "predicated" "yes,no" (const_string "no"))
@@ -448,12 +441,7 @@
(if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
(lt (minus (match_dup 2) (pc)) (const_int 1048572)))
(const_int 4)
- (const_int 8)))
- (set (attr "far_branch")
- (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
- (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
- (const_int 0)
- (const_int 1)))]
+ (const_int 8)))]
)
;; For a 24-bit immediate CST we can optimize the compare for equality
@@ -670,12 +658,7 @@
(if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
(lt (minus (match_dup 1) (pc)) (const_int 1048572)))
(const_int 4)
- (const_int 8)))
- (set (attr "far_branch")
- (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
- (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
- (const_int 0)
- (const_int 1)))]
+ (const_int 8)))]
)
(define_insn "*tb<optab><mode>1"
@@ -692,7 +675,11 @@
{
if (get_attr_length (insn) == 8)
{
- if (get_attr_far_branch (insn) == 1)
+ long long int offset;
+ offset = INSN_ADDRESSES (INSN_UID (XEXP (operands[2], 0)))
+ - INSN_ADDRESSES (INSN_UID (insn));
+
+ if (offset <= -1048576 || offset >= 1048572)
return aarch64_gen_far_branch (operands, 2, "Ltb",
"<inv_tb>\\t%<w>0, %1, ");
else
@@ -709,12 +696,7 @@
(if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -32768))
(lt (minus (match_dup 2) (pc)) (const_int 32764)))
(const_int 4)
- (const_int 8)))
- (set (attr "far_branch")
- (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
- (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
- (const_int 0)
- (const_int 1)))]
+ (const_int 8)))]
)
@@ -727,8 +709,12 @@
""
{
if (get_attr_length (insn) == 8)
- {
- if (get_attr_far_branch (insn) == 1)
+ {
+ long long int offset;
+ offset = INSN_ADDRESSES (INSN_UID (XEXP (operands[1], 0)))
+ - INSN_ADDRESSES (INSN_UID (insn));
+
+ if (offset <= -1048576 || offset >= 1048572)
return aarch64_gen_far_branch (operands, 1, "Ltb",
"<inv_tb>\\t%<w>0, <sizem1>, ");
else
@@ -740,7 +726,7 @@
output_asm_insn (buf, operands);
return "<bcond>\t%l1";
}
- }
+ }
else
return "<tbz>\t%<w>0, <sizem1>, %l1";
}
@@ -749,12 +735,7 @@
(if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -32768))
(lt (minus (match_dup 1) (pc)) (const_int 32764)))
(const_int 4)
- (const_int 8)))
- (set (attr "far_branch")
- (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
- (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
- (const_int 0)
- (const_int 1)))]
+ (const_int 8)))]
)
;; -------------------------------------------------------------------