2019-06-28 Michael Meissner <meissner@linux.ibm.com>
+ * config/rs6000/predicates.md (pcrel_address): Use
+ SYMBOL_REF_LOCAL_P to determine if a label is local.
+ (pcrel_external_address): New predicate.
+ (non_prefixed_mem_operand): Delete, predicate not used.
+ * config/rs6000/rs6000.h (SYMBOL_FLAG_PCREL_P): Delete, we now use
+ SYMBOL_REF_LOCAL_P to determine if we can use pc-relative
+ addressing.
+ (SYMBOL_REF_PCREL_P): Likewise.
+
PR target/91009
* config/rs6000/rs6000.md (floatsi<mode>2_lfiwax): Add non-VSX
alternative.
(define_predicate "pcrel_address"
(match_code "label_ref,symbol_ref,const")
{
- if (!TARGET_PCREL)
+ if (!rs6000_pcrel_p (cfun))
return false;
- /* Discard any CONST's. */
if (GET_CODE (op) == CONST)
op = XEXP (op, 0);
op = op0;
}
- return LABEL_REF_P (op) || SYMBOL_REF_PCREL_P (op);
+ if (LABEL_REF_P (op))
+ return true;
+
+ return (SYMBOL_REF_P (op) && SYMBOL_REF_LOCAL_P (op));
+})
+
+;; Return true if the operand is an external symbol whose address can be loaded
+;; into a register using:
+;; PLA reg,label@pcrel@got
+;;
+;; The linker will either optimize this to either a PADDI if the label is
+;; defined locally in another module or a PLD of the address if the label is
+;; defined in another module.
+
+(define_predicate "pcrel_external_address"
+ (match_code "symbol_ref,const")
+{
+ if (!rs6000_pcrel_p (cfun))
+ return false;
+
+ if (GET_CODE (op) == CONST)
+ op = XEXP (op, 0);
+
+ /* Validate offset. */
+ if (GET_CODE (op) == PLUS)
+ {
+ rtx op0 = XEXP (op, 0);
+ rtx op1 = XEXP (op, 1);
+
+ if (!CONST_INT_P (op1) || !SIGNED_34BIT_OFFSET_P (INTVAL (op1), 0))
+ return false;
+
+ op = op0;
+ }
+
+ return (SYMBOL_REF_P (op) && !SYMBOL_REF_LOCAL_P (op));
})
-;; Return 1 if op is a prefixed memory operand
+;; Return 1 if op is a prefixed memory operand.
(define_predicate "prefixed_mem_operand"
(match_code "mem")
{
return rs6000_prefixed_address (XEXP (op, 0), GET_MODE (op));
})
-;; Return 1 if op is a memory operand that is not a prefixed memory
-;; operand.
-(define_predicate "non_prefixed_mem_operand"
- (and (match_operand 0 "memory_operand")
- (not (match_operand 0 "prefixed_mem_operand"))))
+;; Return 1 if op is a memory operand to an external variable when we
+;; support pc-relative addressing and the PCREL_OPT relocation to
+;; optimize references to it.
+(define_predicate "pcrel_external_mem_operand"
+ (match_code "mem")
+{
+ return pcrel_external_address (XEXP (op, 0), Pmode);
+})
;; Match the first insn (addis) in fusing the combination of addis and loads to
;; GPR registers on power8.