+2015-08-24 Renlin Li <renlin.li@arm.com>
+
+ * config/arm/arm-protos.h (arm_valid_symbolic_address_p): Declare.
+ * config/arm/arm.c (arm_valid_symbolic_address_p): Define.
+ * config/arm/arm.md (arm_movt): Use arm_valid_symbolic_address_p.
+ * config/arm/constraints.md ("j"): Add check for high code.
+
2015-08-24 Tom de Vries <tom@codesourcery.com>
PR tree-optimization/65468
extern void arm_emit_coreregs_64bit_shift (enum rtx_code, rtx, rtx, rtx, rtx,
rtx);
+extern bool arm_valid_symbolic_address_p (rtx);
extern bool arm_validize_comparison (rtx *, rtx *, rtx *);
#endif /* RTX_CODE */
#undef BRANCH
}
+/* Returns true if the pattern is a valid symbolic address, which is either a
+ symbol_ref or (symbol_ref + addend).
+
+ According to the ARM ELF ABI, the initial addend of REL-type relocations
+ processing MOVW and MOVT instructions is formed by interpreting the 16-bit
+ literal field of the instruction as a 16-bit signed value in the range
+ -32768 <= A < 32768. */
+
+bool
+arm_valid_symbolic_address_p (rtx addr)
+{
+ rtx xop0, xop1 = NULL_RTX;
+ rtx tmp = addr;
+
+ if (GET_CODE (tmp) == SYMBOL_REF || GET_CODE (tmp) == LABEL_REF)
+ return true;
+
+ /* (const (plus: symbol_ref const_int)) */
+ if (GET_CODE (addr) == CONST)
+ tmp = XEXP (addr, 0);
+
+ if (GET_CODE (tmp) == PLUS)
+ {
+ xop0 = XEXP (tmp, 0);
+ xop1 = XEXP (tmp, 1);
+
+ if (GET_CODE (xop0) == SYMBOL_REF && CONST_INT_P (xop1))
+ return IN_RANGE (INTVAL (xop1), -0x8000, 0x7fff);
+ }
+
+ return false;
+}
/* Returns true if a valid comparison operation and makes
the operands in a form that is valid. */
[(set (match_operand:SI 0 "nonimmediate_operand" "=r")
(lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
(match_operand:SI 2 "general_operand" "i")))]
- "arm_arch_thumb2"
+ "arm_arch_thumb2 && arm_valid_symbolic_address_p (operands[2])"
"movt%?\t%0, #:upper16:%c2"
[(set_attr "predicable" "yes")
(set_attr "predicable_short_it" "no")
(define_constraint "j"
"A constant suitable for a MOVW instruction. (ARM/Thumb-2)"
(and (match_test "TARGET_32BIT && arm_arch_thumb2")
- (ior (match_code "high")
+ (ior (and (match_code "high")
+ (match_test "arm_valid_symbolic_address_p (XEXP (op, 0))"))
(and (match_code "const_int")
(match_test "(ival & 0xffff0000) == 0")))))