aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/expr.c40
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr79121.c34
4 files changed, 72 insertions, 13 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f953791..bb725d6 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2017-01-19 Richard Earnshaw <rearnsha@arm.com>
+
+ PR rtl-optimization/79121
+ * expr.c (expand_expr_real_2, case LSHIFT_EXPR): Look at the signedness
+ of the inner type when shifting an extended value.
+
2017-01-17 Jan Hubicka <hubicka@ucw.cz>
PR lto/78407
diff --git a/gcc/expr.c b/gcc/expr.c
index 4c54faf..2d8868e 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -9056,9 +9056,9 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
/* Left shift optimization when shifting across word_size boundary.
- If mode == GET_MODE_WIDER_MODE (word_mode), then normally there isn't
- native instruction to support this wide mode left shift. Given below
- scenario:
+ If mode == GET_MODE_WIDER_MODE (word_mode), then normally
+ there isn't native instruction to support this wide mode
+ left shift. Given below scenario:
Type A = (Type) B << C
@@ -9067,10 +9067,11 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
| word_size |
- If the shift amount C caused we shift B to across the word size
- boundary, i.e part of B shifted into high half of destination
- register, and part of B remains in the low half, then GCC will use
- the following left shift expand logic:
+ If the shift amount C caused we shift B to across the word
+ size boundary, i.e part of B shifted into high half of
+ destination register, and part of B remains in the low
+ half, then GCC will use the following left shift expand
+ logic:
1. Initialize dest_low to B.
2. Initialize every bit of dest_high to the sign bit of B.
@@ -9080,20 +9081,30 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
5. Logic right shift D by (word_size - C).
6. Or the result of 4 and 5 to finalize dest_high.
- While, by checking gimple statements, if operand B is coming from
- signed extension, then we can simplify above expand logic into:
+ While, by checking gimple statements, if operand B is
+ coming from signed extension, then we can simplify above
+ expand logic into:
1. dest_high = src_low >> (word_size - C).
2. dest_low = src_low << C.
- We can use one arithmetic right shift to finish all the purpose of
- steps 2, 4, 5, 6, thus we reduce the steps needed from 6 into 2. */
+ We can use one arithmetic right shift to finish all the
+ purpose of steps 2, 4, 5, 6, thus we reduce the steps
+ needed from 6 into 2.
+
+ The case is similar for zero extension, except that we
+ initialize dest_high to zero rather than copies of the sign
+ bit from B. Furthermore, we need to use a logical right shift
+ in this case.
+
+ The choice of sign-extension versus zero-extension is
+ determined entirely by whether or not B is signed and is
+ independent of the current setting of unsignedp. */
temp = NULL_RTX;
if (code == LSHIFT_EXPR
&& target
&& REG_P (target)
- && ! unsignedp
&& mode == GET_MODE_WIDER_MODE (word_mode)
&& GET_MODE_SIZE (mode) == 2 * GET_MODE_SIZE (word_mode)
&& TREE_CONSTANT (treeop1)
@@ -9114,6 +9125,8 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
rtx_insn *seq, *seq_old;
unsigned int high_off = subreg_highpart_offset (word_mode,
mode);
+ bool extend_unsigned
+ = TYPE_UNSIGNED (TREE_TYPE (gimple_assign_rhs1 (def)));
rtx low = lowpart_subreg (word_mode, op0, mode);
rtx dest_low = lowpart_subreg (word_mode, target, mode);
rtx dest_high = simplify_gen_subreg (word_mode, target,
@@ -9125,7 +9138,8 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
start_sequence ();
/* dest_high = src_low >> (word_size - C). */
temp = expand_variable_shift (RSHIFT_EXPR, word_mode, low,
- rshift, dest_high, unsignedp);
+ rshift, dest_high,
+ extend_unsigned);
if (temp != dest_high)
emit_move_insn (dest_high, temp);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index e639b5d..dc54c0a 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2017-01-19 Richard Earnshaw <rearnsha@arm.com>
+
+ PR rtl-optimization/79121
+ * gcc.c-torture/execute/pr79121.c: New test.
+
2017-01-18 Michael Meissner <meissner@linux.vnet.ibm.com>
* gcc.target/powerpc/p9-xxbr-1.c: Fix typos in submission.
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr79121.c b/gcc/testsuite/gcc.c-torture/execute/pr79121.c
new file mode 100644
index 0000000..9fca7fb
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr79121.c
@@ -0,0 +1,34 @@
+extern void abort (void);
+
+__attribute__ ((noinline, noclone)) unsigned long long f1 (int x)
+{
+ return ((unsigned long long) x) << 4;
+}
+
+__attribute__ ((noinline, noclone)) long long f2 (unsigned x)
+{
+ return ((long long) x) << 4;
+}
+
+__attribute__ ((noinline, noclone)) unsigned long long f3 (unsigned x)
+{
+ return ((unsigned long long) x) << 4;
+}
+
+__attribute__ ((noinline, noclone)) long long f4 (int x)
+{
+ return ((long long) x) << 4;
+}
+
+int main ()
+{
+ if (f1 (0xf0000000) != 0xffffffff00000000)
+ abort ();
+ if (f2 (0xf0000000) != 0xf00000000)
+ abort ();
+ if (f3 (0xf0000000) != 0xf00000000)
+ abort ();
+ if (f4 (0xf0000000) != 0xffffffff00000000)
+ abort ();
+ return 0;
+}