diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 105a99b35cb..9e2740990bf 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2013-06-04 Ian Bolton + + * config/aarch64/aarch64.md (*mov_aarch64): Call + into function to generate MOVI instruction. + * config/aarch64/aarch64.c (aarch64_simd_container_mode): + New function. + (aarch64_preferred_simd_mode): Turn into wrapper. + (aarch64_output_scalar_simd_mov_immediate): New function. + * config/aarch64/aarch64-protos.h: Add prototype for above. + 2013-06-04 Ian Bolton * config/aarch64/aarch64.c (simd_immediate_info): Remove diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index 81b5b6a3427..8e099bf7f91 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -149,6 +149,7 @@ bool aarch64_legitimate_pic_operand_p (rtx); bool aarch64_move_imm (HOST_WIDE_INT, enum machine_mode); bool aarch64_mov_operand_p (rtx, enum aarch64_symbol_context, enum machine_mode); +char *aarch64_output_scalar_simd_mov_immediate (rtx, enum machine_mode); char *aarch64_output_simd_mov_immediate (rtx, enum machine_mode, unsigned); bool aarch64_pad_arg_upward (enum machine_mode, const_tree); bool aarch64_pad_reg_upward (enum machine_mode, const_tree, bool); diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 5b7cf27af1e..4471ee1be1b 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -5989,30 +5989,55 @@ aarch64_vector_mode_supported_p (enum machine_mode mode) return false; } -/* Return quad mode as the preferred SIMD mode. */ +/* Return appropriate SIMD container + for MODE within a vector of WIDTH bits. */ +static enum machine_mode +aarch64_simd_container_mode (enum machine_mode mode, unsigned width) +{ + gcc_assert (width == 64 || width == 128); + if (TARGET_SIMD) + { + if (width == 128) + switch (mode) + { + case DFmode: + return V2DFmode; + case SFmode: + return V4SFmode; + case SImode: + return V4SImode; + case HImode: + return V8HImode; + case QImode: + return V16QImode; + case DImode: + return V2DImode; + default: + break; + } + else + switch (mode) + { + case SFmode: + return V2SFmode; + case SImode: + return V2SImode; + case HImode: + return V4HImode; + case QImode: + return V8QImode; + default: + break; + } + } + return word_mode; +} + +/* Return 128-bit container as the preferred SIMD mode for MODE. */ static enum machine_mode aarch64_preferred_simd_mode (enum machine_mode mode) { - if (TARGET_SIMD) - switch (mode) - { - case DFmode: - return V2DFmode; - case SFmode: - return V4SFmode; - case SImode: - return V4SImode; - case HImode: - return V8HImode; - case QImode: - return V16QImode; - case DImode: - return V2DImode; - break; - - default:; - } - return word_mode; + return aarch64_simd_container_mode (mode, 128); } /* Return the bitmask of possible vector sizes for the vectorizer @@ -7282,6 +7307,18 @@ aarch64_output_simd_mov_immediate (rtx const_vector, return templ; } +char* +aarch64_output_scalar_simd_mov_immediate (rtx immediate, + enum machine_mode mode) +{ + enum machine_mode vmode; + + gcc_assert (!VECTOR_MODE_P (mode)); + vmode = aarch64_simd_container_mode (mode, 64); + rtx v_op = aarch64_simd_gen_const_vector_dup (vmode, INTVAL (immediate)); + return aarch64_output_simd_mov_immediate (v_op, vmode, 64); +} + /* Split operands into moves from op[1] + op[2] into op[0]. */ void diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 2064a99cdf4..e88e5be894e 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -774,17 +774,34 @@ (match_operand:SHORT 1 "general_operand" " r,M,D,m, m,rZ,*w,*w, r,*w"))] "(register_operand (operands[0], mode) || aarch64_reg_or_zero (operands[1], mode))" - "@ - mov\\t%w0, %w1 - mov\\t%w0, %1 - movi\\t%0., %1 - ldr\\t%w0, %1 - ldr\\t%0, %1 - str\\t%w1, %0 - str\\t%1, %0 - umov\\t%w0, %1.[0] - dup\\t%0., %w1 - dup\\t%0, %1.[0]" +{ + switch (which_alternative) + { + case 0: + return "mov\t%w0, %w1"; + case 1: + return "mov\t%w0, %1"; + case 2: + return aarch64_output_scalar_simd_mov_immediate (operands[1], + mode); + case 3: + return "ldr\t%w0, %1"; + case 4: + return "ldr\t%0, %1"; + case 5: + return "str\t%w1, %0"; + case 6: + return "str\t%1, %0"; + case 7: + return "umov\t%w0, %1.[0]"; + case 8: + return "dup\t%0., %w1"; + case 9: + return "dup\t%0, %1.[0]"; + default: + gcc_unreachable (); + } +} [(set_attr "v8type" "move,alu,alu,load1,load1,store1,store1,*,*,*") (set_attr "simd_type" "*,*,simd_move_imm,*,*,*,*,simd_movgp,simd_dupgp,simd_dup") (set_attr "simd" "*,*,yes,*,*,*,*,yes,yes,yes") diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9197b57b290..451a488fc4e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2013-06-04 Ian Bolton + + * gcc.target/aarch64/movi_1.c: New test. + 2013-06-04 Tobias Burnus PR fortran/37336 diff --git a/gcc/testsuite/gcc.target/aarch64/movi_1.c b/gcc/testsuite/gcc.target/aarch64/movi_1.c new file mode 100644 index 00000000000..e2842b39e02 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/movi_1.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +void +dummy (short* b) +{ + /* { dg-final { scan-assembler "movi\tv\[0-9\]+\.4h, 0x4, lsl 8" } } */ + /* { dg-final { scan-assembler-not "movi\tv\[0-9\]+\.4h, 0x400" } } */ + /* { dg-final { scan-assembler-not "movi\tv\[0-9\]+\.4h, 1024" } } */ + register short x asm ("h8") = 1024; + asm volatile ("" : : "w" (x)); + *b = x; +}