diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 2ddda02..b339e83 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -6422,7 +6422,26 @@ (set_attr "pool_range" "*,*,*,*,*,*,1018,*,*") (set_attr "conds" "set,clob,*,*,nocond,nocond,nocond,nocond,nocond")]) -(define_split +; Split the load of 64-bit constant into two loads for high and low 32-bit parts respectively +; to see if we can load them in fewer instructions or fewer cycles. +; For the small 64-bit integer constants that satisfy constraint J, the instruction pattern +; thumb1_movdi_insn has a better way to handle them. +(define_split + [(set (match_operand:ANY64 0 "arm_general_register_operand" "") + (match_operand:ANY64 1 "const_double_operand" ""))] + "TARGET_THUMB1 && reload_completed && !satisfies_constraint_J (operands[1])" + [(set (match_dup 0) (match_dup 1)) + (set (match_dup 2) (match_dup 3))] + " + operands[2] = gen_highpart (SImode, operands[0]); + operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]), + operands[1]); + operands[0] = gen_lowpart (SImode, operands[0]); + operands[1] = gen_lowpart (SImode, operands[1]); + " +) + +(define_split [(set (match_operand:SI 0 "register_operand" "") (match_operand:SI 1 "const_int_operand" ""))] "TARGET_THUMB1 && satisfies_constraint_J (operands[1])" diff --git a/gcc/testsuite/gcc.target/arm/thumb1-load-64bit-constant-1.c b/gcc/testsuite/gcc.target/arm/thumb1-load-64bit-constant-1.c new file mode 100644 index 0000000..9537aaf --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/thumb1-load-64bit-constant-1.c @@ -0,0 +1,14 @@ +/* { dg-require-effective-target arm_thumb1_ok } */ +/* { dg-do compile } */ +/* { dg-options "-Os" } */ +/* { dg-skip-if "" { ! { arm_thumb1 } } } */ + +extern long long madd (long long a, long long b); + +long long +foo () +{ + return madd (0x0000000100000001LL, 0x0000011100000001LL); +} + +/* { dg-final { scan-assembler-not "ldr" } } */ diff --git a/gcc/testsuite/gcc.target/arm/thumb1-load-64bit-constant-2.c b/gcc/testsuite/gcc.target/arm/thumb1-load-64bit-constant-2.c new file mode 100644 index 0000000..836682b --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/thumb1-load-64bit-constant-2.c @@ -0,0 +1,14 @@ +/* { dg-require-effective-target arm_thumb1_ok } */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-skip-if "" { ! { arm_thumb1 } } } */ + +extern long long madd (long long a); + +long long +foo () +{ + return madd (0x0000000100000001LL); +} + +/* { dg-final { scan-assembler-not "ldr" } } */ diff --git a/gcc/testsuite/gcc.target/arm/thumb1-load-64bit-constant-3.c b/gcc/testsuite/gcc.target/arm/thumb1-load-64bit-constant-3.c new file mode 100644 index 0000000..cf4d0be --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/thumb1-load-64bit-constant-3.c @@ -0,0 +1,14 @@ +/* { dg-require-effective-target arm_thumb1_ok } */ +/* { dg-do compile } */ +/* { dg-options "-Os" } */ +/* { dg-skip-if "" { ! { arm_thumb1 } } } */ + +long long +foo (int len) +{ + return (long long) (((long long) 1 << len) - 1); +} + +/* { dg-final { scan-assembler-not "ldr" } } */ +/* { dg-final { scan-assembler-times "neg" 1 } } */ +