* [PATCH 3/3] or1k: only force reg for immediates
2019-04-10 21:28 [PATCH 0/3] OpenRISC floating point support + fixes Stafford Horne
@ 2019-04-10 21:28 ` Stafford Horne
2019-04-10 21:28 ` [PATCH 1/3] or1k: Initial support for FPU Stafford Horne
` (2 subsequent siblings)
3 siblings, 0 replies; 6+ messages in thread
From: Stafford Horne @ 2019-04-10 21:28 UTC (permalink / raw)
To: GCC patches; +Cc: Richard Henderson, Openrisc, Stafford Horne
The force_reg in or1k_expand_compare is hard coded for SImode, which is fine as
this used to only be used on SI expands. However, with FP support this will
cause issues. In general we should only force the right hand operand to a
register if its an immediate. This patch adds an condition to check for that.
gcc/ChangeLog:
* config/or1k/or1k.c (or1k_expand_compare): Check for int before
force_reg.
---
gcc/config/or1k/or1k.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/gcc/config/or1k/or1k.c b/gcc/config/or1k/or1k.c
index fc10fcfabde..35d984533be 100644
--- a/gcc/config/or1k/or1k.c
+++ b/gcc/config/or1k/or1k.c
@@ -1435,11 +1435,13 @@ void
or1k_expand_compare (rtx *operands)
{
rtx sr_f = gen_rtx_REG (BImode, SR_F_REGNUM);
+ rtx righthand_op = XEXP (operands[0], 1);
- /* The RTL may receive an immediate in argument 1 of the compare, this is not
- supported unless we have l.sf*i instructions, force them into registers. */
- if (!TARGET_SFIMM)
- XEXP (operands[0], 1) = force_reg (SImode, XEXP (operands[0], 1));
+ /* Integer RTL may receive an immediate in argument 1 of the compare, this is
+ not supported unless we have l.sf*i instructions, force them into
+ registers. */
+ if (!TARGET_SFIMM && CONST_INT_P (righthand_op))
+ XEXP (operands[0], 1) = force_reg (SImode, righthand_op);
/* Emit the given comparison into the Flag bit. */
PUT_MODE (operands[0], BImode);
--
2.19.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/3] or1k: Initial support for FPU
2019-04-10 21:28 [PATCH 0/3] OpenRISC floating point support + fixes Stafford Horne
2019-04-10 21:28 ` [PATCH 3/3] or1k: only force reg for immediates Stafford Horne
@ 2019-04-10 21:28 ` Stafford Horne
2019-04-10 21:47 ` [PATCH 2/3] or1k: Allow volatile memory for sign/zero extend loads Stafford Horne
2019-04-12 15:32 ` [PATCH 0/3] OpenRISC floating point support + fixes Jeff Law
3 siblings, 0 replies; 6+ messages in thread
From: Stafford Horne @ 2019-04-10 21:28 UTC (permalink / raw)
To: GCC patches; +Cc: Richard Henderson, Openrisc, Stafford Horne
Or1k only supports ordered compares so we fall back to lib functions
for unordered operations.
Doubles work on this 32-bit architecture by using register pairing as
specified in: https://openrisc.io/proposals/orfpx64a32
Or1k does not support sf/df or df/sf conversions.
gcc/ChangeLog:
* config.gcc (or1k*-*-*): Add mhard-float and mdouble-float validations.
* config/or1k/or1k.md (type): Add fpu.
(fpu): New instruction reservation.
(F, f, fi, FI, FOP, fop): New.
(<fop><F:mode>3): New ALU instruction definition.
(float<fi><F:mode>2): New conversion instruction definition.
(fix_trunc<F:mode><fi>2): New conversion instruction definition.
(fpcmpcc): New code iterator.
(*sf_fp_insn): New instruction definition.
(cstore<F:mode>4): New expand definition.
(cbranch<F:mode>4): New expand definition.
* config/or1k/or1k.opt (msoft-float, mhard-float, mdouble-float): New
options.
* doc/invoke.texi: Document msoft-float, mhard-float and mdouble-float.
---
gcc/config.gcc | 1 +
gcc/config/or1k/or1k.md | 103 ++++++++++++++++++++++++++++++++++++++-
gcc/config/or1k/or1k.opt | 15 +++++-
gcc/doc/invoke.texi | 15 ++++++
4 files changed, 131 insertions(+), 3 deletions(-)
diff --git a/gcc/config.gcc b/gcc/config.gcc
index ebbab5d8b6a..8017851922e 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -2541,6 +2541,7 @@ or1k*-*-*)
for or1k_multilib in ${or1k_multilibs}; do
case ${or1k_multilib} in
mcmov | msext | msfimm | \
+ mhard-float | mdouble-float | \
mhard-div | mhard-mul | \
msoft-div | msoft-mul )
TM_MULTILIB_CONFIG="${TM_MULTILIB_CONFIG},${or1k_multilib}"
diff --git a/gcc/config/or1k/or1k.md b/gcc/config/or1k/or1k.md
index 2dad51cd46b..202493c5ab9 100644
--- a/gcc/config/or1k/or1k.md
+++ b/gcc/config/or1k/or1k.md
@@ -60,7 +60,7 @@
(define_attr "length" "" (const_int 4))
(define_attr "type"
- "alu,st,ld,control,multi"
+ "alu,st,ld,control,multi,fpu"
(const_string "alu"))
(define_attr "insn_support" "class1,sext,sfimm,shftimm" (const_string "class1"))
@@ -93,6 +93,10 @@
(define_insn_reservation "control" 1
(eq_attr "type" "control")
"cpu")
+(define_insn_reservation "fpu" 2
+ (eq_attr "type" "fpu")
+ "cpu")
+
; Define delay slots for any branch
(define_delay (eq_attr "type" "control")
@@ -155,6 +159,46 @@
""
"l.sub\t%0, %r1, %2")
+;; -------------------------------------------------------------------------
+;; Floating Point Arithmetic instructions
+;; -------------------------------------------------------------------------
+
+;; Mode iterator for single/double float
+(define_mode_iterator F [(SF "TARGET_HARD_FLOAT")
+ (DF "TARGET_DOUBLE_FLOAT")])
+(define_mode_attr f [(SF "s") (DF "d")])
+(define_mode_attr fi [(SF "si") (DF "di")])
+(define_mode_attr FI [(SF "SI") (DF "DI")])
+
+;; Basic arithmetic instructions
+(define_code_iterator FOP [plus minus mult div])
+(define_code_attr fop [(plus "add") (minus "sub") (mult "mul") (div "div")])
+
+(define_insn "<fop><F:mode>3"
+ [(set (match_operand:F 0 "register_operand" "=r")
+ (FOP:F (match_operand:F 1 "register_operand" "r")
+ (match_operand:F 2 "register_operand" "r")))]
+ "TARGET_HARD_FLOAT"
+ "lf.<fop>.<f>\t%0, %1, %2"
+ [(set_attr "type" "fpu")])
+
+;; Basic float<->int conversion
+(define_insn "float<fi><F:mode>2"
+ [(set (match_operand:F 0 "register_operand" "=r")
+ (float:F
+ (match_operand:<FI> 1 "register_operand" "r")))]
+ "TARGET_HARD_FLOAT"
+ "lf.itof.<f>\t%0, %1"
+ [(set_attr "type" "fpu")])
+
+(define_insn "fix_trunc<F:mode><fi>2"
+ [(set (match_operand:<FI> 0 "register_operand" "=r")
+ (fix:<FI>
+ (match_operand:F 1 "register_operand" "r")))]
+ "TARGET_HARD_FLOAT"
+ "lf.ftoi.<f>\t%0, %1"
+ [(set_attr "type" "fpu")])
+
;; -------------------------------------------------------------------------
;; Logical operators
;; -------------------------------------------------------------------------
@@ -388,6 +432,31 @@
l.sf<insn>i\t%r0, %1"
[(set_attr "insn_support" "*,sfimm")])
+;; Support FP comparisons too
+
+;; The OpenRISC FPU supports these comparisons:
+;;
+;; lf.sfeq.{d,s} - equality, r r, double or single precision
+;; lf.sfge.{d,s} - greater than or equal, r r, double or single precision
+;; lf.sfgt.{d,s} - greater than, r r, double or single precision
+;; lf.sfle.{d,s} - less than or equal, r r, double or single precision
+;; lf.sflt.{d,s} - less than, r r, double or single precision
+;; lf.sfne.{d,s} - not equal, r r, double or single precision
+;;
+;; Double precision is only supported on some hardware. Only register/register
+;; comparisons are supported. All comparisons are signed.
+
+(define_code_iterator fpcmpcc [ne eq lt gt ge le])
+
+(define_insn "*sf_fp_insn"
+ [(set (reg:BI SR_F_REGNUM)
+ (fpcmpcc:BI (match_operand:F 0 "register_operand" "r")
+ (match_operand:F 1 "register_operand" "r")))]
+ "TARGET_HARD_FLOAT"
+ "lf.sf<code>.<f>\t%0, %1"
+ [(set_attr "type" "fpu")])
+
+
;; -------------------------------------------------------------------------
;; Conditional Store instructions
;; -------------------------------------------------------------------------
@@ -408,6 +477,23 @@
DONE;
})
+;; Support FP cstores too
+(define_expand "cstore<F:mode>4"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (if_then_else:F
+ (match_operator 1 "ordered_comparison_operator"
+ [(match_operand:F 2 "register_operand" "")
+ (match_operand:F 3 "register_operand" "")])
+ (match_dup 0)
+ (const_int 0)))]
+ "TARGET_HARD_FLOAT"
+{
+ or1k_expand_compare (operands + 1);
+ PUT_MODE (operands[1], SImode);
+ emit_insn (gen_rtx_SET (operands[0], operands[1]));
+ DONE;
+})
+
;; Being able to "copy" SR_F to a general register is helpful for
;; the atomic insns, wherein the usual usage is to test the success
;; of the compare-and-swap. Representing the operation in this way,
@@ -501,6 +587,21 @@
or1k_expand_compare (operands);
})
+;; Support FP branching
+
+(define_expand "cbranch<F:mode>4"
+ [(set (pc)
+ (if_then_else
+ (match_operator 0 "ordered_comparison_operator"
+ [(match_operand:F 1 "register_operand" "")
+ (match_operand:F 2 "register_operand" "")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ "TARGET_HARD_FLOAT"
+{
+ or1k_expand_compare (operands);
+})
+
(define_insn "*cbranch"
[(set (pc)
(if_then_else
diff --git a/gcc/config/or1k/or1k.opt b/gcc/config/or1k/or1k.opt
index 7bdbd842dd4..9a7e1c8bae7 100644
--- a/gcc/config/or1k/or1k.opt
+++ b/gcc/config/or1k/or1k.opt
@@ -21,8 +21,6 @@
; See the GCC internals manual (options.texi) for a description of
; this file's format.
-; Please try to keep this file in ASCII collating order.
-
mhard-div
Target RejectNegative InverseMask(SOFT_DIV)
Use hardware divide instructions, use -msoft-div for emulation.
@@ -31,6 +29,19 @@ mhard-mul
Target RejectNegative InverseMask(SOFT_MUL).
Use hardware multiply instructions, use -msoft-mul for emulation.
+msoft-float
+Target RejectNegative InverseMask(HARD_FLOAT)
+Use gcc provided software routines for floating point operations.
+
+mhard-float
+Target RejectNegative Mask(HARD_FLOAT)
+Use hardware floating point instructions.
+
+mdouble-float
+Target Mask(DOUBLE_FLOAT)
+Allows generation of binaries which support 64-bit doubles on 32-bit systems by
+storing doubles in register pairs.
+
mcmov
Target RejectNegative Mask(CMOV)
Allows generation of binaries which use the l.cmov instruction. If your target
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index cfc3063929b..5b474be265a 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -1028,6 +1028,7 @@ Objective-C and Objective-C++ Dialects}.
@emph{OpenRISC Options}
@gccoptlist{-mboard=@var{name} -mnewlib -mhard-mul -mhard-div @gol
-msoft-mul -msoft-div @gol
+-msoft-float -mhard-float -mdouble-float @gol
-mcmov -mror -msext -msfimm -mshftimm}
@emph{PDP-11 Options}
@@ -23551,6 +23552,20 @@ default.
Generate code for hardware which supports multiply instructions. This is the
default.
+@item -msoft-float
+@opindex msoft-float
+Generate code which uses library calls for floating point operations. This is
+the default.
+
+@item -mhard-float
+@opindex mhard-float
+Generate code for hardware which supports floating point instructions.
+
+@item -mdouble-float
+@opindex mdouble-float
+Generate code for hardware which supports 64-bit floating point operations
+on 32-bit OpenRISC targets.
+
@item -mcmov
@opindex mcmov
Generate code for hardware which supports the conditional move (@code{l.cmov})
--
2.19.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 2/3] or1k: Allow volatile memory for sign/zero extend loads
2019-04-10 21:28 [PATCH 0/3] OpenRISC floating point support + fixes Stafford Horne
2019-04-10 21:28 ` [PATCH 3/3] or1k: only force reg for immediates Stafford Horne
2019-04-10 21:28 ` [PATCH 1/3] or1k: Initial support for FPU Stafford Horne
@ 2019-04-10 21:47 ` Stafford Horne
2019-04-12 15:32 ` [PATCH 0/3] OpenRISC floating point support + fixes Jeff Law
3 siblings, 0 replies; 6+ messages in thread
From: Stafford Horne @ 2019-04-10 21:47 UTC (permalink / raw)
To: GCC patches; +Cc: Richard Henderson, Openrisc, Stafford Horne
Volatile memory does not match the memory_operand predicate. This
causes extra extend/mask instructions instructions when reading
from volatile memory. On OpenRISC this can be treated the same
as regular memory.
gcc/ChangeLog:
* config/or1k/or1k.md (zero_extend<mode>si2): Update predicate.
(extend<mode>si2): Update predicate.
* gcc/config/or1k/predicates.md (volatile_mem_operand): New.
(reg_or_mem_operand): New.
---
gcc/config/or1k/or1k.md | 6 +++---
gcc/config/or1k/predicates.md | 16 ++++++++++++++++
2 files changed, 19 insertions(+), 3 deletions(-)
diff --git a/gcc/config/or1k/or1k.md b/gcc/config/or1k/or1k.md
index 202493c5ab9..23ded94feb3 100644
--- a/gcc/config/or1k/or1k.md
+++ b/gcc/config/or1k/or1k.md
@@ -372,11 +372,11 @@
;; Sign Extending
;; -------------------------------------------------------------------------
-;; Zero extension can always be done with AND and an extending load.
+;; Zero extension can always be done with AND or an extending load.
(define_insn "zero_extend<mode>si2"
[(set (match_operand:SI 0 "register_operand" "=r,r")
- (zero_extend:SI (match_operand:I12 1 "nonimmediate_operand" "r,m")))]
+ (zero_extend:SI (match_operand:I12 1 "reg_or_mem_operand" "r,m")))]
""
"@
l.andi\t%0, %1, <zext_andi>
@@ -388,7 +388,7 @@
(define_insn "extend<mode>si2"
[(set (match_operand:SI 0 "register_operand" "=r,r")
- (sign_extend:SI (match_operand:I12 1 "nonimmediate_operand" "r,m")))]
+ (sign_extend:SI (match_operand:I12 1 "reg_or_mem_operand" "r,m")))]
"TARGET_SEXT"
"@
l.ext<ldst>s\t%0, %1
diff --git a/gcc/config/or1k/predicates.md b/gcc/config/or1k/predicates.md
index 879236bca49..17599d0ee3b 100644
--- a/gcc/config/or1k/predicates.md
+++ b/gcc/config/or1k/predicates.md
@@ -82,3 +82,19 @@
(define_predicate "equality_comparison_operator"
(match_code "ne,eq"))
+
+;; Borrowed from rs6000
+; Return 1 if the operand is in volatile memory. Note that during the
+;; RTL generation phase, memory_operand does not return TRUE for volatile
+;; memory references. So this function allows us to recognize volatile
+;; references where it's safe.
+(define_predicate "volatile_mem_operand"
+ (and (and (match_code "mem")
+ (match_test "MEM_VOLATILE_P (op)"))
+ (if_then_else (match_test "reload_completed")
+ (match_operand 0 "memory_operand")
+ (match_test "memory_address_p (mode, XEXP (op, 0))"))))
+
+(define_predicate "reg_or_mem_operand"
+ (ior (match_operand 0 "nonimmediate_operand")
+ (match_operand 0 "volatile_mem_operand")))
--
2.19.1
^ permalink raw reply [flat|nested] 6+ messages in thread