diff options
author | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-08-19 22:51:20 +0000 |
---|---|---|
committer | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-08-19 22:51:20 +0000 |
commit | 5fb2a157d6342ff8c2650e71db49eb02c74b46fa (patch) | |
tree | e967345a26c84656cfebfc8e15d937bdfd7e968a /gcc/expr.c | |
parent | cd2f377379015425539a6c10a7c5b2c043035439 (diff) | |
download | gcc-5fb2a157d6342ff8c2650e71db49eb02c74b46fa.tar.gz |
PR middle-end/41123
* expr.c (expand_expr_real_1) <normal_inner_ref>: Handle all kinds
of CONCAT, not just bitpos 0 bitsize size of the whole CONCAT.
* gcc.dg/pr41123.c: New test.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@150946 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/expr.c')
-rw-r--r-- | gcc/expr.c | 37 |
1 files changed, 27 insertions, 10 deletions
diff --git a/gcc/expr.c b/gcc/expr.c index 08c747ecffb..6805cdc6e6d 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -7871,6 +7871,33 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, || mode1 == BLKmode || bitpos + bitsize > GET_MODE_BITSIZE (mode2)); + /* Handle CONCAT first. */ + if (GET_CODE (op0) == CONCAT && !must_force_mem) + { + if (bitpos == 0 + && bitsize == GET_MODE_BITSIZE (GET_MODE (op0))) + return op0; + if (bitpos == 0 + && bitsize == GET_MODE_BITSIZE (GET_MODE (XEXP (op0, 0))) + && bitsize) + { + op0 = XEXP (op0, 0); + mode2 = GET_MODE (op0); + } + else if (bitpos == GET_MODE_BITSIZE (GET_MODE (XEXP (op0, 0))) + && bitsize == GET_MODE_BITSIZE (GET_MODE (XEXP (op0, 1))) + && bitpos + && bitsize) + { + op0 = XEXP (op0, 1); + bitpos = 0; + mode2 = GET_MODE (op0); + } + else + /* Otherwise force into memory. */ + must_force_mem = 1; + } + /* If this is a constant, put it in a register if it is a legitimate constant and we don't need a memory reference. */ if (CONSTANT_P (op0) @@ -7944,16 +7971,6 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, MEM_VOLATILE_P (op0) = 1; } - /* The following code doesn't handle CONCAT. - Assume only bitpos == 0 can be used for CONCAT, due to - one element arrays having the same mode as its element. */ - if (GET_CODE (op0) == CONCAT) - { - gcc_assert (bitpos == 0 - && bitsize == GET_MODE_BITSIZE (GET_MODE (op0))); - return op0; - } - /* In cases where an aligned union has an unaligned object as a field, we might be extracting a BLKmode value from an integer-mode (e.g., SImode) object. Handle this case |