diff options
author | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2006-10-29 15:18:24 +0000 |
---|---|---|
committer | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2006-10-29 15:18:24 +0000 |
commit | 9c42dd286eb8af0872f07596312c4f3c6ef6af03 (patch) | |
tree | 600dc261e4509a381886cd337eccdaf4e4fccd41 /gcc/config/i386/i386.c | |
parent | 630e568cbe4352038bdf71de79bece6068d10929 (diff) | |
download | gcc-9c42dd286eb8af0872f07596312c4f3c6ef6af03.tar.gz |
2006-10-29 Richard Guenther <rguenther@suse.de>
* genopinit.c (optabs): Change lfloor_optab and lceil_optab
to conversion optabs.
* optabs.c (init_optabs): Initialize lfloor_optab and lceil_optab
as conversion optab.
* optabs.h (enum optab_index): Remove OTI_lfloor and OTI_lceil.
(enum convert_optab_index): Add COI_lfloor and COI_lceil.
(lfloor_optab, lceil_optab): Adjust defines.
* builtins.c (expand_builtin_int_roundingfn): Adjust for
lfloor and lceil optabs now being conversion optabs.
* config/i386/i386-protos.h (ix86_expand_lfloorceil): Declare.
* config/i386/i386.c (ix86_expand_sse_compare_and_jump):
New static helper function.
(ix86_expand_lfloorceil): New function to expand lfloor and
lceil inline.
* config/i386/i386.md (lfloor<mode>2): Split into ...
(lfloorxf<mode>2): ... x87 variant
(lfloor<mode>di2, lfloor<mode>si2): ... and SSE variants
using ix86_expand_lfloorceil.
(lceil<mode>2, lceilxf<mode>2, lceil<mode>di2, lceil<mode>si2):
Likewise.
* doc/md.texi (lfloorMN, lceilMN): Document.
* gcc.target/i386/math-torture/lfloor.c: New testcase.
* gcc.target/i386/math-torture/lceil.c: Likewise.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@118143 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/i386/i386.c')
-rw-r--r-- | gcc/config/i386/i386.c | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index a535b45f12c..0291a97a8ae 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -19246,6 +19246,36 @@ ix86_sse_copysign_to_positive (rtx result, rtx abs_value, rtx sign) gen_rtx_IOR (mode, abs_value, sgn))); } +/* Expands a comparison of OP0 with OP1 using comparison code CODE, + swapping the operands if SWAP_OPERANDS is true. The expanded + code is a forward jump to a newly created label in case the + comparison is true. The generated label rtx is returned. */ +static rtx +ix86_expand_sse_compare_and_jump (enum rtx_code code, rtx op0, rtx op1, + bool swap_operands) +{ + rtx label, tmp; + + if (swap_operands) + { + tmp = op0; + op0 = op1; + op1 = tmp; + } + + label = gen_label_rtx (); + tmp = gen_rtx_REG (CCFPUmode, FLAGS_REG); + emit_insn (gen_rtx_SET (VOIDmode, tmp, + gen_rtx_COMPARE (CCFPUmode, op0, op1))); + tmp = gen_rtx_fmt_ee (code, VOIDmode, tmp, const0_rtx); + tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp, + gen_rtx_LABEL_REF (VOIDmode, label), pc_rtx); + tmp = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp)); + JUMP_LABEL (tmp) = label; + + return label; +} + /* Expand SSE sequence for computing lround from OP1 storing into OP0. */ void @@ -19276,4 +19306,37 @@ ix86_expand_lround (rtx op0, rtx op1) expand_fix (op0, adj, 0); } +/* Expand SSE2 sequence for computing lround from OPERAND1 storing + into OPERAND0. */ +void +ix86_expand_lfloorceil (rtx op0, rtx op1, bool do_floor) +{ + /* C code for the stuff we're doing below (for do_floor): + xi = (long)op1; + xi -= (double)xi > op1 ? 1 : 0; + return xi; + */ + enum machine_mode fmode = GET_MODE (op1); + enum machine_mode imode = GET_MODE (op0); + rtx ireg, freg, label; + + /* reg = (long)op1 */ + ireg = gen_reg_rtx (imode); + expand_fix (ireg, op1, 0); + + /* freg = (double)reg */ + freg = gen_reg_rtx (fmode); + expand_float (freg, ireg, 0); + + /* ireg = (freg > op1) ? ireg - 1 : ireg */ + label = ix86_expand_sse_compare_and_jump (UNLE, + freg, op1, !do_floor); + expand_simple_binop (imode, do_floor ? MINUS : PLUS, + ireg, const1_rtx, ireg, 0, OPTAB_DIRECT); + emit_label (label); + LABEL_NUSES (label) = 1; + + emit_move_insn (op0, ireg); +} + #include "gt-i386.h" |