mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-23 00:41:25 +08:00
i386: Use SHR to compare with large power-of-two constants [PR94650]
Convert unsigned compares where m >= LARGE_POWER_OF_TWO and LARGE_POWER_OF_TWO represent an immediate where bit 33+ is set to use a SHR instruction and compare the result to 0. This avoids loading a large immediate with MOVABS insn. movabsq $1099511627775, %rax cmpq %rax, %rdi ja .L5 gets converted to: shrq $40, %rdi jne .L5 PR target/94650 * config/i386/predicates.md (shr_comparison_operator): New predicate. * config/i386/i386.md (compare->shr splitter): New splitters. testsuite/ChangeLog: PR target/94650 * gcc.targeti/i386/pr94650.c: New test.
This commit is contained in:
parent
6b5c7ee0df
commit
8ea03e9016
@ -1,3 +1,9 @@
|
||||
2020-05-04 Uroš Bizjak <ubizjak@gmail.com>
|
||||
|
||||
PR target/94650
|
||||
* config/i386/predicates.md (shr_comparison_operator): New predicate.
|
||||
* config/i386/i386.md (compare->shr splitter): New splitters.
|
||||
|
||||
2020-05-04 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR tree-optimization/94718
|
||||
|
@ -12310,6 +12310,36 @@
|
||||
|
||||
;; Store-flag instructions.
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:QI 0 "nonimmediate_operand")
|
||||
(match_operator:QI 1 "shr_comparison_operator"
|
||||
[(match_operand:DI 2 "register_operand")
|
||||
(match_operand 3 "const_int_operand")]))]
|
||||
"TARGET_64BIT
|
||||
&& IN_RANGE (exact_log2 (UINTVAL (operands[3]) + 1), 32, 63)"
|
||||
[(parallel
|
||||
[(set (reg:CCZ FLAGS_REG)
|
||||
(compare:CCZ
|
||||
(lshiftrt:DI (match_dup 2) (match_dup 4))
|
||||
(const_int 0)))
|
||||
(clobber (scratch:DI))])
|
||||
(set (match_dup 0)
|
||||
(match_op_dup 1 [(reg:CCZ FLAGS_REG) (const_int 0)]))]
|
||||
{
|
||||
enum rtx_code new_code;
|
||||
|
||||
operands[1] = shallow_copy_rtx (operands[1]);
|
||||
switch (GET_CODE (operands[1]))
|
||||
{
|
||||
case GTU: new_code = NE; break;
|
||||
case LEU: new_code = EQ; break;
|
||||
default: gcc_unreachable ();
|
||||
}
|
||||
PUT_CODE (operands[1], new_code);
|
||||
|
||||
operands[4] = GEN_INT (exact_log2 (UINTVAL (operands[3]) + 1));
|
||||
})
|
||||
|
||||
;; For all sCOND expanders, also expand the compare or test insn that
|
||||
;; generates cc0. Generate an equality comparison if `seq' or `sne'.
|
||||
|
||||
@ -12473,6 +12503,42 @@
|
||||
(set_attr "mode" "<MODE>")])
|
||||
|
||||
;; Basic conditional jump instructions.
|
||||
|
||||
(define_split
|
||||
[(set (pc)
|
||||
(if_then_else
|
||||
(match_operator 1 "shr_comparison_operator"
|
||||
[(match_operand:DI 2 "register_operand")
|
||||
(match_operand 3 "const_int_operand")])
|
||||
(label_ref (match_operand 0))
|
||||
(pc)))]
|
||||
"TARGET_64BIT
|
||||
&& IN_RANGE (exact_log2 (UINTVAL (operands[3]) + 1), 32, 63)"
|
||||
[(parallel
|
||||
[(set (reg:CCZ FLAGS_REG)
|
||||
(compare:CCZ
|
||||
(lshiftrt:DI (match_dup 2) (match_dup 4))
|
||||
(const_int 0)))
|
||||
(clobber (scratch:DI))])
|
||||
(set (pc)
|
||||
(if_then_else (match_op_dup 1 [(reg:CCZ FLAGS_REG) (const_int 0)])
|
||||
(label_ref (match_operand 0))
|
||||
(pc)))]
|
||||
{
|
||||
enum rtx_code new_code;
|
||||
|
||||
operands[1] = shallow_copy_rtx (operands[1]);
|
||||
switch (GET_CODE (operands[1]))
|
||||
{
|
||||
case GTU: new_code = NE; break;
|
||||
case LEU: new_code = EQ; break;
|
||||
default: gcc_unreachable ();
|
||||
}
|
||||
PUT_CODE (operands[1], new_code);
|
||||
|
||||
operands[4] = GEN_INT (exact_log2 (UINTVAL (operands[3]) + 1));
|
||||
})
|
||||
|
||||
;; We ignore the overflow flag for signed branch instructions.
|
||||
|
||||
(define_insn "*jcc"
|
||||
|
@ -1290,6 +1290,9 @@
|
||||
(define_predicate "bt_comparison_operator"
|
||||
(match_code "ne,eq"))
|
||||
|
||||
(define_predicate "shr_comparison_operator"
|
||||
(match_code "gtu,leu"))
|
||||
|
||||
;; Return true if OP is a valid comparison operator in valid mode.
|
||||
(define_predicate "ix86_comparison_operator"
|
||||
(match_operand 0 "comparison_operator")
|
||||
|
@ -1,3 +1,8 @@
|
||||
2020-05-04 Uroš Bizjak <ubizjak@gmail.com>
|
||||
|
||||
PR target/94650
|
||||
* gcc.targeti/i386/pr94650.c: New test.
|
||||
|
||||
2020-05-04 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR tree-optimization/94718
|
||||
|
30
gcc/testsuite/gcc.target/i386/pr94650.c
Normal file
30
gcc/testsuite/gcc.target/i386/pr94650.c
Normal file
@ -0,0 +1,30 @@
|
||||
/* PR target/94650 */
|
||||
/* { dg-do compile { target { ! ia32 } } } */
|
||||
/* { dg-options "-O2" } */
|
||||
|
||||
#define LARGE_POWER_OF_TWO (1ULL << 40)
|
||||
|
||||
int
|
||||
check (unsigned long long m)
|
||||
{
|
||||
return m >= LARGE_POWER_OF_TWO;
|
||||
}
|
||||
|
||||
void g (int);
|
||||
|
||||
void
|
||||
test0 (unsigned long long m)
|
||||
{
|
||||
if (m >= LARGE_POWER_OF_TWO)
|
||||
g (0);
|
||||
}
|
||||
|
||||
void
|
||||
test1 (unsigned long long m)
|
||||
{
|
||||
if (m >= LARGE_POWER_OF_TWO)
|
||||
g (m);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-assembler-not "movabs" } } */
|
||||
/* { dg-final { scan-assembler-times "shr" 3 } } */
|
Loading…
x
Reference in New Issue
Block a user