extern void print_operand_address (FILE *, rtx);
extern void print_operand (FILE *, rtx, int);
extern void s390_output_pool_entry (rtx, machine_mode, unsigned int);
+extern bool s390_const_int_pool_entry_p (rtx, HOST_WIDE_INT *);
extern int s390_label_align (rtx_insn *);
extern int s390_agen_dep_p (rtx_insn *, rtx_insn *);
extern rtx_insn *s390_load_got (void);
}
}
+/* Return true if MEM refers to an integer constant in the literal pool. If
+ VAL is not nullptr, then also fill it with the constant's value. */
+
+bool
+s390_const_int_pool_entry_p (rtx mem, HOST_WIDE_INT *val)
+{
+ /* Try to match the following:
+ - (mem (unspec [(symbol_ref) (reg)] UNSPEC_LTREF)).
+ - (mem (symbol_ref)). */
+
+ if (!MEM_P (mem))
+ return false;
+
+ rtx addr = XEXP (mem, 0);
+ rtx sym;
+ if (GET_CODE (addr) == UNSPEC && XINT (addr, 1) == UNSPEC_LTREF)
+ sym = XVECEXP (addr, 0, 0);
+ else
+ sym = addr;
+
+ if (!SYMBOL_REF_P (sym) || !CONSTANT_POOL_ADDRESS_P (sym))
+ return false;
+
+ rtx val_rtx = get_pool_constant (sym);
+ if (!CONST_INT_P (val_rtx))
+ return false;
+
+ if (val != nullptr)
+ *val = INTVAL (val_rtx);
+ return true;
+}
/* Return an RTL expression representing the value of the return address
for the frame COUNT steps up from the current frame. FRAME is the
[(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2)))]
"")
+; Split loading of 64-bit constants into GPRs into llihf + oilf -
+; counterintuitively, using oilf is faster than iilf. oilf clobbers
+; cc, so cc must be dead.
+(define_peephole2
+ [(set (match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "memory_operand" ""))]
+ "TARGET_64BIT
+ && TARGET_EXTIMM
+ && GENERAL_REG_P (operands[0])
+ && s390_const_int_pool_entry_p (operands[1], nullptr)
+ && peep2_reg_dead_p (1, gen_rtx_REG (CCmode, CC_REGNUM))"
+ [(set (match_dup 0) (match_dup 2))
+ (parallel
+ [(set (match_dup 0) (ior:DI (match_dup 0) (match_dup 3)))
+ (clobber (reg:CC CC_REGNUM))])]
+{
+ HOST_WIDE_INT val;
+ bool ok = s390_const_int_pool_entry_p (operands[1], &val);
+ gcc_assert (ok);
+ operands[2] = GEN_INT (val & 0xFFFFFFFF00000000ULL);
+ operands[3] = GEN_INT (val & 0x00000000FFFFFFFFULL);
+})
+
;
; movsi instruction pattern(s).
;
--- /dev/null
+/* Test that large 64-bit constants are loaded with llihf + oilf when lgrl is
+ not available. */
+
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z9-109" } */
+
+unsigned long
+magic (void)
+{
+ return 0x3f08c5392f756cd;
+}
+
+/* { dg-final { scan-assembler-times {\n\tllihf\t} 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times {\n\toilf\t} 1 { target lp64 } } } */
--- /dev/null
+/* Test that large 64-bit constants are loaded with llihf + oilf when lgrl is
+ available. */
+
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z10" } */
+
+unsigned long
+magic (void)
+{
+ return 0x3f08c5392f756cd;
+}
+
+/* { dg-final { scan-assembler-times {\n\tllihf\t} 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times {\n\toilf\t} 1 { target lp64 } } } */