Skip to content

Commit 3f600ca

Browse files
exur00keith-packard
andcommitted
arc: emit clobber of CC for -mcpu=em x >> 31
Address the issue explained here: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120375 Devices without a barrel shifter end up using a sequence of instructions. These can use the condition codes and/or loop count register, so those need to be marked as 'clobbered'. These clobbers were previously added only after split1, which is too late. This patch adds these clobbers from the beginning, in the define_expand. Previously, define_insn_and_split *<insn>si3_nobs would match any shift or rotate instruction and would generate the necessary patterns to emulate a barrel shifter, but it did not have any output assembly for itself. In many cases this would create a loop with parallel clobbers. This pattern is then matched by the <insn>si3_loop pattern. In the no-barrel-shifter.c test tree code: ;; no-barrel-shifter.c:9: int sign = (x >> 31) & 1; _2 = x.0_1 >> 31; in the expand pass becomes the following pattern that matches *lshrsi3_nobs: (insn 18 17 19 4 (set (reg:SI 153 [ _2 ]) (lshiftrt:SI (reg/v:SI 156 [ x ]) (const_int 31 [0x1f]))) "test2.c":9:24 -1 (nil)) This pattern misses the necessary clobbers and remains untouched until the split1 pass. Together with the later branch it becomes ;; no-barrel-shifter.c:9: int sign = (x >> 31) & 1; add.f 0,r0,r0 ;; no-barrel-shifter.c:14: if (mag == 0x7f800000) beq.d .L8 ;; no-barrel-shifter.c:9: int sign = (x >> 31) & 1; rlc r0,0 Leading to an issue: the add.f instructions overwrites CC but beq expects CC to contain an earlier value indicating mag == 0x7f800000. Now, these are combined in define_insn_and_split <insn>si3_loop that is explicitly emitted in the define_expand and already contains the clobbers. This can then be split into another pattern or remain the loop pattern. In the expand pass, the same example now becomes: (insn 18 17 19 4 (parallel [ (set (reg:SI 153 [ _2 ]) (lshiftrt:SI (reg/v:SI 156 [ x ]) (const_int 31 [0x1f]))) (clobber (reg:SI 60 lp_count)) (clobber (reg:CC 61 cc)) ]) "test2.c":9:24 -1 (nil)) Because the correct clobbers are now taken into account, the branch condition is reevaluated by using breq instead of br. ;; no-barrel-shifter.c:9: int sign = (x >> 31) & 1; add.f 0,r0,r0 rlc r0,0 ;; no-barrel-shifter.c:14: if (mag == 0x7f800000) breq r2,2139095040,.L8 Regtested for arc. Co-authored-by: Keith Packard <[email protected]> Signed-off-by: Loeka Rogge <[email protected]>
1 parent ef2d980 commit 3f600ca

File tree

2 files changed

+54
-25
lines changed

2 files changed

+54
-25
lines changed

gcc/config/arc/arc.md

Lines changed: 35 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3554,7 +3554,14 @@ archs4x, archs4xd"
35543554
[(set (match_operand:SI 0 "dest_reg_operand" "")
35553555
(ANY_SHIFT_ROTATE:SI (match_operand:SI 1 "register_operand" "")
35563556
(match_operand:SI 2 "nonmemory_operand" "")))]
3557-
"")
3557+
""
3558+
{
3559+
if (!TARGET_BARREL_SHIFTER && operands[2] != const1_rtx)
3560+
{
3561+
emit_insn (gen_<insn>si3_loop (operands[0], operands[1], operands[2]));
3562+
DONE;
3563+
}
3564+
})
35583565

35593566
; asl, asr, lsr patterns:
35603567
; There is no point in including an 'I' alternative since only the lowest 5
@@ -3653,35 +3660,23 @@ archs4x, archs4xd"
36533660
[(set_attr "type" "shift")
36543661
(set_attr "length" "8")])
36553662

3656-
(define_insn_and_split "*<insn>si3_nobs"
3657-
[(set (match_operand:SI 0 "dest_reg_operand")
3658-
(ANY_SHIFT_ROTATE:SI (match_operand:SI 1 "register_operand")
3659-
(match_operand:SI 2 "nonmemory_operand")))]
3663+
(define_insn_and_split "<insn>si3_loop"
3664+
[(set (match_operand:SI 0 "dest_reg_operand" "=r,r")
3665+
(ANY_SHIFT_ROTATE:SI (match_operand:SI 1 "register_operand" "0,0")
3666+
(match_operand:SI 2 "nonmemory_operand" "rn,Cal")))
3667+
(clobber (reg:SI LP_COUNT))
3668+
(clobber (reg:CC CC_REG))]
36603669
"!TARGET_BARREL_SHIFTER
3661-
&& operands[2] != const1_rtx
3662-
&& arc_pre_reload_split ()"
3663-
"#"
3664-
"&& 1"
3670+
&& operands[2] != const1_rtx"
3671+
"* return output_shift_loop (<CODE>, operands);"
3672+
"&& arc_pre_reload_split ()"
36653673
[(const_int 0)]
36663674
{
36673675
arc_split_<insn> (operands);
36683676
DONE;
3669-
})
3670-
3671-
;; <ANY_SHIFT_ROTATE>si3_loop appears after <ANY_SHIFT_ROTATE>si3_nobs
3672-
(define_insn "<insn>si3_loop"
3673-
[(set (match_operand:SI 0 "dest_reg_operand" "=r,r")
3674-
(ANY_SHIFT_ROTATE:SI
3675-
(match_operand:SI 1 "register_operand" "0,0")
3676-
(match_operand:SI 2 "nonmemory_operand" "rn,Cal")))
3677-
(clobber (reg:SI LP_COUNT))
3678-
(clobber (reg:CC CC_REG))
3679-
]
3680-
"!TARGET_BARREL_SHIFTER
3681-
&& operands[2] != const1_rtx"
3682-
"* return output_shift_loop (<CODE>, operands);"
3683-
[(set_attr "type" "shift")
3684-
(set_attr "length" "16,20")])
3677+
}
3678+
[(set_attr "type" "shift")
3679+
(set_attr "length" "16,20")])
36853680

36863681
;; DImode shifts
36873682

@@ -6413,6 +6408,21 @@ archs4x, archs4xd"
64136408
(set_attr "length" "4")
64146409
(set_attr "predicable" "no")])
64156410

6411+
;; Match <insn>si3_loop pattern if operand 2 has become const_int 1 in the meantime
6412+
(define_insn_and_split "<insn>si3_cnt1_clobber"
6413+
[(set (match_operand:SI 0 "dest_reg_operand")
6414+
(ANY_SHIFT_ROTATE:SI (match_operand:SI 1 "register_operand")
6415+
(const_int 1)))
6416+
(clobber (reg:SI LP_COUNT))
6417+
(clobber (reg:CC CC_REG))]
6418+
"!TARGET_BARREL_SHIFTER"
6419+
"#"
6420+
"&& arc_pre_reload_split ()"
6421+
[(set (match_dup 0) (ANY_SHIFT_ROTATE:SI (match_dup 1) (const_int 1)))]
6422+
""
6423+
[(set_attr "type" "shift")
6424+
(set_attr "length" "4")])
6425+
64166426
(define_peephole2
64176427
[(set (match_operand:SI 0 "register_operand" "")
64186428
(zero_extract:SI (match_dup 0)
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/* { dg-do compile } */
2+
/* { dg-options "-O2" } */
3+
/* { dg-skip-if "" { { barrelshifter } } } */
4+
int fromfloat(float fx);
5+
6+
float foo(float fx)
7+
{
8+
int x = fromfloat(fx);
9+
int sign = (x >> 31) & 1;
10+
unsigned int mag = x & 0x7fffffff;
11+
12+
if (mag > 0x7f800000)
13+
return fx;
14+
if (mag == 0x7f800000)
15+
return (sign == 0);
16+
return fx * (27 + sign);
17+
}
18+
19+
/* { dg-final { scan-assembler-not "add.f\\s\+\[0-9\]\+,r\[0-9\]\+,r\[0-9\]\+\\n\\s\+beq.d" } } */

0 commit comments

Comments
 (0)