diff options
Diffstat (limited to 'gcc/simplify-rtx.c')
-rw-r--r-- | gcc/simplify-rtx.c | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index 07b9353..9f6dbe1 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -3368,6 +3368,50 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode, return simplify_gen_binary (VEC_CONCAT, mode, subop0, subop1); } + + /* If we select one half of a vec_concat, return that. */ + if (GET_CODE (trueop0) == VEC_CONCAT + && CONST_INT_P (XVECEXP (trueop1, 0, 0))) + { + rtx subop0 = XEXP (trueop0, 0); + rtx subop1 = XEXP (trueop0, 1); + enum machine_mode mode0 = GET_MODE (subop0); + enum machine_mode mode1 = GET_MODE (subop1); + int li = GET_MODE_SIZE (GET_MODE_INNER (mode0)); + int l0 = GET_MODE_SIZE (mode0) / li; + int l1 = GET_MODE_SIZE (mode1) / li; + int i0 = INTVAL (XVECEXP (trueop1, 0, 0)); + if (i0 == 0 && !side_effects_p (op1) && mode == mode0) + { + bool success = true; + for (int i = 1; i < l0; ++i) + { + rtx j = XVECEXP (trueop1, 0, i); + if (!CONST_INT_P (j) || INTVAL (j) != i) + { + success = false; + break; + } + } + if (success) + return subop0; + } + if (i0 == l0 && !side_effects_p (op0) && mode == mode1) + { + bool success = true; + for (int i = 1; i < l1; ++i) + { + rtx j = XVECEXP (trueop1, 0, i); + if (!CONST_INT_P (j) || INTVAL (j) != i0 + i) + { + success = false; + break; + } + } + if (success) + return subop1; + } + } } if (XVECLEN (trueop1, 0) == 1 |