mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-01-27 10:54:14 +08:00
re PR middle-end/17886 (variable rotate and unsigned long long rotate should be better optimized)
PR 17886 * expmed.c (expand_shift): Move logic to reverse rotation direction when rotating by constants ... * optabs.c (expand_binop): ... here. * config/i386/i386.md (rotrdi3): Handle 32-bit mode. (ix86_rotrdi3): New pattern. (rotldi3): Handle 32-bit mode. (ix86_rotldi3): New pattern. From-SVN: r104761
This commit is contained in:
parent
4bc7cba795
commit
0f8594eee9
@ -1,3 +1,14 @@
|
||||
2005-09-28 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
PR 17886
|
||||
* expmed.c (expand_shift): Move logic to reverse rotation
|
||||
direction when rotating by constants ...
|
||||
* optabs.c (expand_binop): ... here.
|
||||
* config/i386/i386.md (rotrdi3): Handle 32-bit mode.
|
||||
(ix86_rotrdi3): New pattern.
|
||||
(rotldi3): Handle 32-bit mode.
|
||||
(ix86_rotldi3): New pattern.
|
||||
|
||||
2005-09-29 Alan Modra <amodra@bigpond.net.au>
|
||||
|
||||
PR target/24102
|
||||
|
@ -12004,13 +12004,49 @@
|
||||
;; Rotate instructions
|
||||
|
||||
(define_expand "rotldi3"
|
||||
[(set (match_operand:DI 0 "nonimmediate_operand" "")
|
||||
(rotate:DI (match_operand:DI 1 "nonimmediate_operand" "")
|
||||
[(set (match_operand:DI 0 "shiftdi_operand" "")
|
||||
(rotate:DI (match_operand:DI 1 "shiftdi_operand" "")
|
||||
(match_operand:QI 2 "nonmemory_operand" "")))
|
||||
(clobber (reg:CC FLAGS_REG))]
|
||||
"TARGET_64BIT"
|
||||
"ix86_expand_binary_operator (ROTATE, DImode, operands); DONE;")
|
||||
""
|
||||
{
|
||||
if (TARGET_64BIT)
|
||||
{
|
||||
ix86_expand_binary_operator (ROTATE, DImode, operands);
|
||||
DONE;
|
||||
}
|
||||
if (!const_1_to_31_operand (operands[2], VOIDmode))
|
||||
FAIL;
|
||||
emit_insn (gen_ix86_rotldi3 (operands[0], operands[1], operands[2]));
|
||||
DONE;
|
||||
})
|
||||
|
||||
;; Implement rotation using two double-precision shift instructions
|
||||
;; and a scratch register.
|
||||
(define_insn_and_split "ix86_rotldi3"
|
||||
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||
(rotate:DI (match_operand:DI 1 "register_operand" "0")
|
||||
(match_operand:QI 2 "const_1_to_31_operand" "I")))
|
||||
(clobber (reg:CC FLAGS_REG))
|
||||
(clobber (match_scratch:SI 3 "=&r"))]
|
||||
"!TARGET_64BIT"
|
||||
""
|
||||
"&& reload_completed"
|
||||
[(set (match_dup 3) (match_dup 4))
|
||||
(parallel
|
||||
[(set (match_dup 4)
|
||||
(ior:SI (ashift:SI (match_dup 4) (match_dup 2))
|
||||
(lshiftrt:SI (match_dup 5)
|
||||
(minus:QI (const_int 32) (match_dup 2)))))
|
||||
(clobber (reg:CC FLAGS_REG))])
|
||||
(parallel
|
||||
[(set (match_dup 5)
|
||||
(ior:SI (ashift:SI (match_dup 5) (match_dup 2))
|
||||
(lshiftrt:SI (match_dup 3)
|
||||
(minus:QI (const_int 32) (match_dup 2)))))
|
||||
(clobber (reg:CC FLAGS_REG))])]
|
||||
"split_di (operands, 1, operands + 4, operands + 5);")
|
||||
|
||||
(define_insn "*rotlsi3_1_one_bit_rex64"
|
||||
[(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
|
||||
(rotate:DI (match_operand:DI 1 "nonimmediate_operand" "0")
|
||||
@ -12192,12 +12228,48 @@
|
||||
(set_attr "mode" "QI")])
|
||||
|
||||
(define_expand "rotrdi3"
|
||||
[(set (match_operand:DI 0 "nonimmediate_operand" "")
|
||||
(rotatert:DI (match_operand:DI 1 "nonimmediate_operand" "")
|
||||
(match_operand:QI 2 "nonmemory_operand" "")))
|
||||
[(set (match_operand:DI 0 "shiftdi_operand" "")
|
||||
(rotate:DI (match_operand:DI 1 "shiftdi_operand" "")
|
||||
(match_operand:QI 2 "nonmemory_operand" "")))
|
||||
(clobber (reg:CC FLAGS_REG))]
|
||||
"TARGET_64BIT"
|
||||
"ix86_expand_binary_operator (ROTATERT, DImode, operands); DONE;")
|
||||
""
|
||||
{
|
||||
if (TARGET_64BIT)
|
||||
{
|
||||
ix86_expand_binary_operator (ROTATERT, DImode, operands);
|
||||
DONE;
|
||||
}
|
||||
if (!const_1_to_31_operand (operands[2], VOIDmode))
|
||||
FAIL;
|
||||
emit_insn (gen_ix86_rotrdi3 (operands[0], operands[1], operands[2]));
|
||||
DONE;
|
||||
})
|
||||
|
||||
;; Implement rotation using two double-precision shift instructions
|
||||
;; and a scratch register.
|
||||
(define_insn_and_split "ix86_rotrdi3"
|
||||
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||
(rotatert:DI (match_operand:DI 1 "register_operand" "0")
|
||||
(match_operand:QI 2 "const_1_to_31_operand" "I")))
|
||||
(clobber (reg:CC FLAGS_REG))
|
||||
(clobber (match_scratch:SI 3 "=&r"))]
|
||||
"!TARGET_64BIT"
|
||||
""
|
||||
"&& reload_completed"
|
||||
[(set (match_dup 3) (match_dup 4))
|
||||
(parallel
|
||||
[(set (match_dup 4)
|
||||
(ior:SI (ashiftrt:SI (match_dup 4) (match_dup 2))
|
||||
(ashift:SI (match_dup 5)
|
||||
(minus:QI (const_int 32) (match_dup 2)))))
|
||||
(clobber (reg:CC FLAGS_REG))])
|
||||
(parallel
|
||||
[(set (match_dup 5)
|
||||
(ior:SI (ashiftrt:SI (match_dup 5) (match_dup 2))
|
||||
(ashift:SI (match_dup 3)
|
||||
(minus:QI (const_int 32) (match_dup 2)))))
|
||||
(clobber (reg:CC FLAGS_REG))])]
|
||||
"split_di (operands, 1, operands + 4, operands + 5);")
|
||||
|
||||
(define_insn "*rotrdi3_1_one_bit_rex64"
|
||||
[(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
|
||||
|
13
gcc/expmed.c
13
gcc/expmed.c
@ -2237,19 +2237,6 @@ expand_shift (enum tree_code code, enum machine_mode mode, rtx shifted,
|
||||
temp = expand_binop (mode,
|
||||
left ? rotl_optab : rotr_optab,
|
||||
shifted, op1, target, unsignedp, methods);
|
||||
|
||||
/* If we don't have the rotate, but we are rotating by a constant
|
||||
that is in range, try a rotate in the opposite direction. */
|
||||
|
||||
if (temp == 0 && GET_CODE (op1) == CONST_INT
|
||||
&& INTVAL (op1) > 0
|
||||
&& (unsigned int) INTVAL (op1) < GET_MODE_BITSIZE (mode))
|
||||
temp = expand_binop (mode,
|
||||
left ? rotr_optab : rotl_optab,
|
||||
shifted,
|
||||
GEN_INT (GET_MODE_BITSIZE (mode)
|
||||
- INTVAL (op1)),
|
||||
target, unsignedp, methods);
|
||||
}
|
||||
else if (unsignedp)
|
||||
temp = expand_binop (mode,
|
||||
|
19
gcc/optabs.c
19
gcc/optabs.c
@ -1049,6 +1049,7 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
|
||||
|| binoptab->code == ROTATERT);
|
||||
rtx entry_last = get_last_insn ();
|
||||
rtx last;
|
||||
bool first_pass_p;
|
||||
|
||||
class = GET_MODE_CLASS (mode);
|
||||
|
||||
@ -1098,6 +1099,8 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
|
||||
}
|
||||
}
|
||||
|
||||
retry:
|
||||
|
||||
/* If we can do it with a three-operand insn, do so. */
|
||||
|
||||
if (methods != OPTAB_MUST_WIDEN
|
||||
@ -1183,6 +1186,22 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
|
||||
delete_insns_since (last);
|
||||
}
|
||||
|
||||
/* If we were trying to rotate by a constant value, and that didn't
|
||||
work, try rotating the other direction before falling back to
|
||||
shifts and bitwise-or. */
|
||||
if (first_pass_p
|
||||
&& (binoptab == rotl_optab || binoptab == rotr_optab)
|
||||
&& class == MODE_INT
|
||||
&& GET_CODE (op1) == CONST_INT
|
||||
&& INTVAL (op1) > 0
|
||||
&& (unsigned int) INTVAL (op1) < GET_MODE_BITSIZE (mode))
|
||||
{
|
||||
first_pass_p = false;
|
||||
op1 = GEN_INT (GET_MODE_BITSIZE (mode) - INTVAL (op1));
|
||||
binoptab = binoptab == rotl_optab ? rotr_optab : rotl_optab;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
/* If this is a multiply, see if we can do a widening operation that
|
||||
takes operands of this mode and makes a wider mode. */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user