Skip to content

Commit c38f17b

Browse files
clazissartemiy-volkov
authored andcommitted
arc64: Use bclrl,bsetl and vpack to load large integers
1 parent 41566a3 commit c38f17b

File tree

5 files changed

+95
-9
lines changed

5 files changed

+95
-9
lines changed

gcc/config/arc64/arc64.cc

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1110,8 +1110,8 @@ arc64_legitimate_constant1_p (machine_mode mode, rtx x, bool nosym)
11101110
{
11111111
switch (GET_CODE (x))
11121112
{
1113-
case CONST_DOUBLE:
11141113
case CONST_INT:
1114+
case CONST_DOUBLE:
11151115
case CONST_WIDE_INT:
11161116
case HIGH:
11171117
if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
@@ -1690,6 +1690,9 @@ arc64_get_effective_mode_for_address_scaling (const machine_mode mode)
16901690
'C': Constant address, switches on/off @plt.
16911691
's': Scalled immediate.
16921692
'S': Scalled immediate, to be used in pair with 's'.
1693+
'T': Like 's' but the immediate is not limited to sub123 type insns.
1694+
't': Like 'T' but the input immediate is bitwise complemented.
1695+
'q': Sign extended lower 32bit of an immediate.
16931696
'N': Negative immediate, to be used in pair with 's'.
16941697
'V': 2x16b vector immediate, hi lane is zero.
16951698
'P': Constant address, swithces on/off _s to be used with 'C'
@@ -1718,6 +1721,7 @@ arc64_print_operand (FILE *file, rtx x, int code)
17181721

17191722
int scalled = 0;
17201723
int sign = 1;
1724+
bool invert = false;
17211725
machine_mode effective_mode;
17221726

17231727
switch (code)
@@ -1809,7 +1813,7 @@ arc64_print_operand (FILE *file, rtx x, int code)
18091813
return;
18101814
}
18111815
ival = INTVAL (x);
1812-
ival &= 0xffffffffULL;
1816+
ival = zext_hwi (ival, 32);
18131817
fprintf (file,"0x%08" PRIx32, (uint32_t) ival);
18141818
break;
18151819

@@ -1899,6 +1903,36 @@ arc64_print_operand (FILE *file, rtx x, int code)
18991903
fputs ("_s", file);
19001904
break;
19011905

1906+
case 't':
1907+
invert = true;
1908+
/* FALLTHRU */
1909+
case 'T':
1910+
if (!CONST_INT_P (x))
1911+
{
1912+
output_operand_lossage ("invalid operand for %%s code");
1913+
return;
1914+
}
1915+
ival = INTVAL (x);
1916+
if (invert)
1917+
ival = ~ival;
1918+
1919+
ival = zext_hwi (ival >> 32, 32) << 32;
1920+
ival = ctz_hwi (ival);
1921+
1922+
asm_fprintf (file, "%d", (int) ival);
1923+
break;
1924+
1925+
case 'q':
1926+
if (!CONST_INT_P (x))
1927+
{
1928+
output_operand_lossage ("invalid operand for %%s code");
1929+
return;
1930+
}
1931+
ival = INTVAL (x);
1932+
ival = sext_hwi (ival, 32);
1933+
asm_fprintf (file, "%d", (int) ival);
1934+
break;
1935+
19021936
case 's':
19031937
if (REG_P (x))
19041938
break;
@@ -5042,7 +5076,7 @@ arc64_prepare_move_operands (rtx op0, rtx op1, machine_mode mode)
50425076
{
50435077
case CONST_INT:
50445078
gcc_assert (mode == Pmode);
5045-
if (!SIGNED_INT32 (INTVAL (op1)) && !UNSIGNED_INT32 (INTVAL (op1)))
5079+
if (splittable_const_int_operand (op1, mode))
50465080
{
50475081
HOST_WIDE_INT val;
50485082
/* We have a large 64bit immediate:

gcc/config/arc64/arc64.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,10 @@ extern const enum reg_class arc64_regno_to_regclass[];
508508

509509
#define IS_POWEROF2_P(X) (! ( (X) & ((X) - 1)) && (X))
510510

511+
/* If this is a single bit mask, then we can load it with bset. */
512+
#define SINGLE_BIT_MASK_OPERAND(VALUE) \
513+
(pow2p_hwi (VALUE))
514+
511515
/* These assume that REGNO is a hard or pseudo reg number.
512516
They give nonzero only if REGNO is a hard reg of the suitable class
513517
or a pseudo reg currently allocated to a suitable hard reg.

gcc/config/arc64/arc64.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -969,8 +969,8 @@ xorl"
969969
;; Long insns: movl, stl, ldl
970970
;;
971971
(define_insn "*arc64_movdi"
972-
[(set (match_operand:DI 0 "arc64_dest_operand" "=qh, q,r, r, r, r,Ucnst, r,r,Ustk<,Ustor")
973-
(match_operand:DI 1 "arc64_movl_operand" "qh,U08S0,r,S12S0,S32S0SymMV,SyPic,S32S0,Ustk>,m, r, r"))]
972+
[(set (match_operand:DI 0 "arc64_dest_operand" "=qh, q, r, r,r, r, r, r, r,Ucnst, r,r,Ustk<,Ustor")
973+
(match_operand:DI 1 "arc64_movl_operand" "qh,U08S0,BCLRX,BSETX,r,S12S0,S32S0SymMV,U38S0,SyPic,S32S0,Ustk>,m, r, r"))]
974974
"TARGET_64BIT
975975
&& (register_operand (operands[0], DImode)
976976
|| register_operand (operands[1], DImode)
@@ -979,17 +979,20 @@ xorl"
979979
"@
980980
movl_s\\t%0,%1
981981
movl_s\\t%0,%1
982+
bclrl\\t%0,%q1,%t1
983+
bsetl\\t%0,%L1,%T1
982984
movl\\t%0,%1
983985
movl\\t%0,%1
984986
movl\\t%0,%1
987+
vpack2wl\\t%0,%L1,%H1
985988
addl\\t%0,pcl,%1
986989
stl%U0\\t%1,%0
987990
popl_s\\t%0
988991
ldl%U1\\t%0,%1
989992
pushl_s\\t%1
990993
stl%U0\\t%1,%0"
991-
[(set_attr "type" "move,move,move,move,move,addl,st,ld,ld,st,st")
992-
(set_attr "length" "2,2,4,4,8,8,8,2,*,2,*")]
994+
[(set_attr "type" "move,move,bclr,bset,move,move,move,vpack,addl,st,ld,ld,st,st")
995+
(set_attr "length" "2,2,8,8,4,4,8,8,8,8,2,*,2,*")]
993996
)
994997

995998
;; Hi/Low moves for constant and symbol loading.

gcc/config/arc64/constraints.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,25 @@
383383
(match_code "const_int")
384384
(match_test "SIGNED_INT16 (ival)")))
385385

386+
(define_constraint "BSETX" "@internal
387+
A 1-bit + 32b integer constant suitable for BSET instruction"
388+
(and
389+
(match_code "const_int")
390+
(match_test "SINGLE_BIT_MASK_OPERAND (zext_hwi (ival >> 32, 32))")
391+
(match_test "UNSIGNED_INT32 (zext_hwi (ival, 32))")))
392+
393+
(define_constraint "BCLRX" "@internal
394+
A 1-bit + 32b integer constant suitable for BCLR instruction"
395+
(and
396+
(match_code "const_int")
397+
(match_test "SINGLE_BIT_MASK_OPERAND (zext_hwi ((~ival) >> 32, 32))")
398+
(match_test "(sext_hwi (ival, 32)) < 0")))
399+
400+
(define_constraint "U38S0" "@internal
401+
A 38-bit integer constant suitable for VPACK2WL instruction"
402+
(and
403+
(match_code "const_int")
404+
(match_test "UNSIGNED (ival, 38)")))
386405

387406
; TODO: Below this line definition should be corrected
388407
(define_constraint "SR_R0"

gcc/config/arc64/predicates.md

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,33 @@
1818
;; along with GCC; see the file COPYING3. If not see
1919
;; <http://www.gnu.org/licenses/>.
2020

21+
;; A legitimate CONST_INT operand that takes more than one instruction
22+
;; to load
23+
(define_predicate "splittable_const_int_operand"
24+
(match_code "const_int")
25+
{
26+
/* ARC32 can fit all. */
27+
if (!TARGET_64BIT)
28+
return false;
29+
30+
/* Check if we can fit it in a standard LIMM/XLIMM field. */
31+
if (SIGNED_INT32 (INTVAL (op)) || UNSIGNED_INT32 (INTVAL (op)))
32+
return false;
33+
34+
/* Check if the constant can be loaded in a single bsetl/bclrl instruction. */
35+
if ((SINGLE_BIT_MASK_OPERAND (zext_hwi (INTVAL (op) >> 32, 32))
36+
&& UNSIGNED_INT32 (zext_hwi (INTVAL (op), 32)))
37+
|| (SINGLE_BIT_MASK_OPERAND (zext_hwi ((~INTVAL (op)) >> 32, 32))
38+
&& (sext_hwi (INTVAL (op), 32) < 0)))
39+
return false;
40+
41+
/* Check if the constant can be loaded in a single vpack2wl instruction. */
42+
if (UNSIGNED (INTVAL (op), 38))
43+
return false;
44+
45+
return true;
46+
})
47+
2148
;; Place holder for mov operand predicate
2249
(define_predicate "arc64_movl_operand"
2350
(and (match_code "unspec,reg, subreg, mem, const, const_int, symbol_ref, label_ref")
@@ -30,8 +57,7 @@
3057
(ior (match_test "XINT (op,1) == ARC64_UNSPEC_PCREL")
3158
(match_test "XINT (op,1) == ARC64_UNSPEC_TLS_GD")))
3259
(and (match_code "const_int")
33-
(ior (match_test "UNSIGNED_INT32 (INTVAL (op))")
34-
(match_test "SIGNED_INT32 (INTVAL (op))"))))))
60+
(match_test "!splittable_const_int_operand (op, mode)")))))
3561

3662
(define_predicate "arc64_movf_operand"
3763
(and (match_code "reg, subreg, mem, const, const_double")

0 commit comments

Comments
 (0)