aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorUros Bizjak <uros@kss-loka.si>2004-12-08 07:50:58 +0100
committerUros Bizjak <uros@gcc.gnu.org>2004-12-08 07:50:58 +0100
commit7c82106ff9548634c85fa7cd7f1cc3a906fd6efa (patch)
treee48bafdbb500e4727cafc2120e27bae69a7c2c4c /gcc
parentac1b13f457ad72970d58b53ef88b45ddab522d41 (diff)
downloadgcc-7c82106ff9548634c85fa7cd7f1cc3a906fd6efa.zip
gcc-7c82106ff9548634c85fa7cd7f1cc3a906fd6efa.tar.gz
gcc-7c82106ff9548634c85fa7cd7f1cc3a906fd6efa.tar.bz2
i386-protos.h (ix86_split_fp_branch): New rtx argument.
* config/i386/i386-protos.h (ix86_split_fp_branch): New rtx argument. * config/i386/i386.c (output_fp_compare): Fix is_sse condition. Use EFLAGS_P only when fcomi insn should be used. Fix handling of eflags_p variable. Change alt table accordingly. For non-fcomi compare insn always use trailing fnstsw insn. Fix intmode calculation for ficom insn. (ix86_split_fp_branch): Add "rtx pushed" as new parameter. Call ix86_free_from_memory when "pushed" is specified. (ix86_expand_branch): Change call to ix86_split_fp_branch. * config/i386/i386.md (*cmpfp_0_sf, *cmpfp_0_df, *cmpfp_0_xf): Change eflags_p parameter in call to output_fp_compare. (*cmpfp_2_sf, *cmpfp_2_df, *cmpfp_2_xf): Remove. (*cmpfp_2_sf_1, *cmpfp_2_df_1, *cmpfp_2_xf_1): Rename to *cmpfp_2_sf, *cmpfp_2_df, *cmpfp_2_xf. Change eflags_p parameter in call to output_fp_compare. (*cmpfp_2_u): Remove. (*cmpfp_2_u_1): Rename to *cmpfp_2_u. Change eflags_p parameter in call to output_fp_compare. (*ficom_1): Remove insn definition and corresponding define_split. (*cmpfp_si): New insn definition. (*fp_jcc_8): New insn definition. Add new splitters for "memory_operand" and "register_operand". (define_split): Add new parameter in call to ix86_split_fp_branch. config/i386/predicates.md (float_operator): New predicate. From-SVN: r91856
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog31
-rw-r--r--gcc/config/i386/i386-protos.h3
-rw-r--r--gcc/config/i386/i386.c69
-rw-r--r--gcc/config/i386/i386.md197
-rw-r--r--gcc/config/i386/predicates.md4
5 files changed, 162 insertions, 142 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9c03269..7b526cc 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,34 @@
+2004-12-07 Uros Bizjak <uros@kss-loka.si>
+
+ * config/i386/i386-protos.h (ix86_split_fp_branch): New rtx
+ argument.
+
+ * config/i386/i386.c (output_fp_compare): Fix is_sse condition.
+ Use EFLAGS_P only when fcomi insn should be used. Fix handling
+ of eflags_p variable. Change alt table accordingly. For non-fcomi
+ compare insn always use trailing fnstsw insn. Fix intmode
+ calculation for ficom insn.
+ (ix86_split_fp_branch): Add "rtx pushed" as new parameter. Call
+ ix86_free_from_memory when "pushed" is specified.
+ (ix86_expand_branch): Change call to ix86_split_fp_branch.
+
+ * config/i386/i386.md (*cmpfp_0_sf, *cmpfp_0_df, *cmpfp_0_xf):
+ Change eflags_p parameter in call to output_fp_compare.
+ (*cmpfp_2_sf, *cmpfp_2_df, *cmpfp_2_xf): Remove.
+ (*cmpfp_2_sf_1, *cmpfp_2_df_1, *cmpfp_2_xf_1): Rename to
+ *cmpfp_2_sf, *cmpfp_2_df, *cmpfp_2_xf. Change eflags_p
+ parameter in call to output_fp_compare.
+ (*cmpfp_2_u): Remove.
+ (*cmpfp_2_u_1): Rename to *cmpfp_2_u. Change eflags_p parameter
+ in call to output_fp_compare.
+ (*ficom_1): Remove insn definition and corresponding define_split.
+ (*cmpfp_si): New insn definition.
+ (*fp_jcc_8): New insn definition. Add new splitters for
+ "memory_operand" and "register_operand".
+ (define_split): Add new parameter in call to ix86_split_fp_branch.
+
+ config/i386/predicates.md (float_operator): New predicate.
+
2004-12-08 Kazu Hirata <kazu@cs.umass.edu>
* c-common.c (verify_tree): Don't check code length if we know
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index d0ff2e1..c79acd0 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -165,7 +165,8 @@ extern rtx ix86_va_arg (tree, tree);
extern rtx ix86_force_to_memory (enum machine_mode, rtx);
extern void ix86_free_from_memory (enum machine_mode);
-extern void ix86_split_fp_branch (enum rtx_code code, rtx, rtx, rtx, rtx, rtx);
+extern void ix86_split_fp_branch (enum rtx_code code, rtx, rtx,
+ rtx, rtx, rtx, rtx);
extern int ix86_hard_regno_mode_ok (int, enum machine_mode);
extern int ix86_register_move_cost (enum machine_mode, enum reg_class,
enum reg_class);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 1a63fe0..2bd53bc 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -7208,25 +7208,24 @@ output_fix_trunc (rtx insn, rtx *operands)
}
/* Output code for INSN to compare OPERANDS. EFLAGS_P is 1 when fcomi
- should be used and 2 when fnstsw should be used. UNORDERED_P is true
- when fucom should be used. */
+ should be used. UNORDERED_P is true when fucom should be used. */
const char *
output_fp_compare (rtx insn, rtx *operands, int eflags_p, int unordered_p)
{
int stack_top_dies;
rtx cmp_op0, cmp_op1;
- int is_sse = SSE_REG_P (operands[0]) | SSE_REG_P (operands[1]);
+ int is_sse = SSE_REG_P (operands[0]) || SSE_REG_P (operands[1]);
- if (eflags_p == 2)
+ if (eflags_p)
{
- cmp_op0 = operands[1];
- cmp_op1 = operands[2];
+ cmp_op0 = operands[0];
+ cmp_op1 = operands[1];
}
else
{
- cmp_op0 = operands[0];
- cmp_op1 = operands[1];
+ cmp_op0 = operands[1];
+ cmp_op1 = operands[2];
}
if (is_sse)
@@ -7268,7 +7267,7 @@ output_fp_compare (rtx insn, rtx *operands, int eflags_p, int unordered_p)
is also a stack register that dies, then this must be a
`fcompp' float compare */
- if (eflags_p == 1)
+ if (eflags_p)
{
/* There is no double popping fcomi variant. Fortunately,
eflags is immune from the fstp's cc clobbering. */
@@ -7280,35 +7279,25 @@ output_fp_compare (rtx insn, rtx *operands, int eflags_p, int unordered_p)
}
else
{
- if (eflags_p == 2)
- {
- if (unordered_p)
- return "fucompp\n\tfnstsw\t%0";
- else
- return "fcompp\n\tfnstsw\t%0";
- }
+ if (unordered_p)
+ return "fucompp\n\tfnstsw\t%0";
else
- {
- if (unordered_p)
- return "fucompp";
- else
- return "fcompp";
- }
+ return "fcompp\n\tfnstsw\t%0";
}
}
else
{
/* Encoded here as eflags_p | intmode | unordered_p | stack_top_dies. */
- static const char * const alt[24] =
+ static const char * const alt[16] =
{
- "fcom%z1\t%y1",
- "fcomp%z1\t%y1",
- "fucom%z1\t%y1",
- "fucomp%z1\t%y1",
+ "fcom%z2\t%y2\n\tfnstsw\t%0",
+ "fcomp%z2\t%y2\n\tfnstsw\t%0",
+ "fucom%z2\t%y2\n\tfnstsw\t%0",
+ "fucomp%z2\t%y2\n\tfnstsw\t%0",
- "ficom%z1\t%y1",
- "ficomp%z1\t%y1",
+ "ficom%z2\t%y2\n\tfnstsw\t%0",
+ "ficomp%z2\t%y2\n\tfnstsw\t%0",
NULL,
NULL,
@@ -7320,16 +7309,6 @@ output_fp_compare (rtx insn, rtx *operands, int eflags_p, int unordered_p)
NULL,
NULL,
NULL,
- NULL,
-
- "fcom%z2\t%y2\n\tfnstsw\t%0",
- "fcomp%z2\t%y2\n\tfnstsw\t%0",
- "fucom%z2\t%y2\n\tfnstsw\t%0",
- "fucomp%z2\t%y2\n\tfnstsw\t%0",
-
- "ficom%z2\t%y2\n\tfnstsw\t%0",
- "ficomp%z2\t%y2\n\tfnstsw\t%0",
- NULL,
NULL
};
@@ -7337,11 +7316,11 @@ output_fp_compare (rtx insn, rtx *operands, int eflags_p, int unordered_p)
const char *ret;
mask = eflags_p << 3;
- mask |= (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT) << 2;
+ mask |= (GET_MODE_CLASS (GET_MODE (cmp_op1)) == MODE_INT) << 2;
mask |= unordered_p << 1;
mask |= stack_top_dies;
- if (mask >= 24)
+ if (mask >= 16)
abort ();
ret = alt[mask];
if (ret == NULL)
@@ -8458,7 +8437,7 @@ ix86_expand_branch (enum rtx_code code, rtx label)
{
ix86_split_fp_branch (code, ix86_compare_op0, ix86_compare_op1,
gen_rtx_LABEL_REF (VOIDmode, label),
- pc_rtx, NULL_RTX);
+ pc_rtx, NULL_RTX, NULL_RTX);
}
else
{
@@ -8606,7 +8585,7 @@ ix86_expand_branch (enum rtx_code code, rtx label)
/* Split branch based on floating point condition. */
void
ix86_split_fp_branch (enum rtx_code code, rtx op1, rtx op2,
- rtx target1, rtx target2, rtx tmp)
+ rtx target1, rtx target2, rtx tmp, rtx pushed)
{
rtx second, bypass;
rtx label = NULL_RTX;
@@ -8625,6 +8604,10 @@ ix86_split_fp_branch (enum rtx_code code, rtx op1, rtx op2,
condition = ix86_expand_fp_compare (code, op1, op2,
tmp, &second, &bypass);
+ /* Remove pushed operand from stack. */
+ if (pushed)
+ ix86_free_from_memory (GET_MODE (pushed));
+
if (split_branch_probability >= 0)
{
/* Distribute the probabilities across the jumps.
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 84617c5..84b97e8 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -797,6 +797,9 @@
;; CCFPmode compare with exceptions
;; CCFPUmode compare with no exceptions
+;; We may not use "#" to split and emit these, since the REG_DEAD notes
+;; used to manage the reg stack popping would not be preserved.
+
(define_insn "*cmpfp_0_sf"
[(set (match_operand:HI 0 "register_operand" "=a")
(unspec:HI
@@ -805,7 +808,7 @@
(match_operand:SF 2 "const0_operand" "X"))]
UNSPEC_FNSTSW))]
"TARGET_80387"
- "* return output_fp_compare (insn, operands, 2, 0);"
+ "* return output_fp_compare (insn, operands, 0, 0);"
[(set_attr "type" "multi")
(set_attr "mode" "SF")])
@@ -817,7 +820,7 @@
(match_operand:DF 2 "const0_operand" "X"))]
UNSPEC_FNSTSW))]
"TARGET_80387"
- "* return output_fp_compare (insn, operands, 2, 0);"
+ "* return output_fp_compare (insn, operands, 0, 0);"
[(set_attr "type" "multi")
(set_attr "mode" "DF")])
@@ -829,24 +832,11 @@
(match_operand:XF 2 "const0_operand" "X"))]
UNSPEC_FNSTSW))]
"TARGET_80387"
- "* return output_fp_compare (insn, operands, 2, 0);"
+ "* return output_fp_compare (insn, operands, 0, 0);"
[(set_attr "type" "multi")
(set_attr "mode" "XF")])
-;; We may not use "#" to split and emit these, since the REG_DEAD notes
-;; used to manage the reg stack popping would not be preserved.
-
-(define_insn "*cmpfp_2_sf"
- [(set (reg:CCFP FPSR_REG)
- (compare:CCFP
- (match_operand:SF 0 "register_operand" "f")
- (match_operand:SF 1 "nonimmediate_operand" "fm")))]
- "TARGET_80387"
- "* return output_fp_compare (insn, operands, 0, 0);"
- [(set_attr "type" "fcmp")
- (set_attr "mode" "SF")])
-
-(define_insn "*cmpfp_2_sf_1"
+(define_insn "*cmpfp_sf"
[(set (match_operand:HI 0 "register_operand" "=a")
(unspec:HI
[(compare:CCFP
@@ -854,21 +844,11 @@
(match_operand:SF 2 "nonimmediate_operand" "fm"))]
UNSPEC_FNSTSW))]
"TARGET_80387"
- "* return output_fp_compare (insn, operands, 2, 0);"
- [(set_attr "type" "fcmp")
- (set_attr "mode" "SF")])
-
-(define_insn "*cmpfp_2_df"
- [(set (reg:CCFP FPSR_REG)
- (compare:CCFP
- (match_operand:DF 0 "register_operand" "f")
- (match_operand:DF 1 "nonimmediate_operand" "fm")))]
- "TARGET_80387"
"* return output_fp_compare (insn, operands, 0, 0);"
[(set_attr "type" "fcmp")
- (set_attr "mode" "DF")])
+ (set_attr "mode" "SF")])
-(define_insn "*cmpfp_2_df_1"
+(define_insn "*cmpfp_df"
[(set (match_operand:HI 0 "register_operand" "=a")
(unspec:HI
[(compare:CCFP
@@ -876,21 +856,11 @@
(match_operand:DF 2 "nonimmediate_operand" "fm"))]
UNSPEC_FNSTSW))]
"TARGET_80387"
- "* return output_fp_compare (insn, operands, 2, 0);"
+ "* return output_fp_compare (insn, operands, 0, 0);"
[(set_attr "type" "multi")
(set_attr "mode" "DF")])
-(define_insn "*cmpfp_2_xf"
- [(set (reg:CCFP FPSR_REG)
- (compare:CCFP
- (match_operand:XF 0 "register_operand" "f")
- (match_operand:XF 1 "register_operand" "f")))]
- "TARGET_80387"
- "* return output_fp_compare (insn, operands, 0, 0);"
- [(set_attr "type" "fcmp")
- (set_attr "mode" "XF")])
-
-(define_insn "*cmpfp_2_xf_1"
+(define_insn "*cmpfp_xf"
[(set (match_operand:HI 0 "register_operand" "=a")
(unspec:HI
[(compare:CCFP
@@ -898,29 +868,11 @@
(match_operand:XF 2 "register_operand" "f"))]
UNSPEC_FNSTSW))]
"TARGET_80387"
- "* return output_fp_compare (insn, operands, 2, 0);"
+ "* return output_fp_compare (insn, operands, 0, 0);"
[(set_attr "type" "multi")
(set_attr "mode" "XF")])
-(define_insn "*cmpfp_2u"
- [(set (reg:CCFPU FPSR_REG)
- (compare:CCFPU
- (match_operand 0 "register_operand" "f")
- (match_operand 1 "register_operand" "f")))]
- "TARGET_80387
- && FLOAT_MODE_P (GET_MODE (operands[0]))
- && GET_MODE (operands[0]) == GET_MODE (operands[1])"
- "* return output_fp_compare (insn, operands, 0, 1);"
- [(set_attr "type" "fcmp")
- (set (attr "mode")
- (cond [(match_operand:SF 1 "" "")
- (const_string "SF")
- (match_operand:DF 1 "" "")
- (const_string "DF")
- ]
- (const_string "XF")))])
-
-(define_insn "*cmpfp_2u_1"
+(define_insn "*cmpfp_u"
[(set (match_operand:HI 0 "register_operand" "=a")
(unspec:HI
[(compare:CCFPU
@@ -930,7 +882,7 @@
"TARGET_80387
&& FLOAT_MODE_P (GET_MODE (operands[1]))
&& GET_MODE (operands[1]) == GET_MODE (operands[2])"
- "* return output_fp_compare (insn, operands, 2, 1);"
+ "* return output_fp_compare (insn, operands, 0, 1);"
[(set_attr "type" "multi")
(set (attr "mode")
(cond [(match_operand:SF 1 "" "")
@@ -940,40 +892,21 @@
]
(const_string "XF")))])
-;; Patterns to match the SImode-in-memory ficom instructions.
-;;
-;; %%% Play games with accepting gp registers, as otherwise we have to
-;; force them to memory during rtl generation, which is no good. We
-;; can get rid of this once we teach reload to do memory input reloads
-;; via pushes.
-
-(define_insn "*ficom_1"
- [(set (reg:CCFP FPSR_REG)
- (compare:CCFP
- (match_operand 0 "register_operand" "f,f")
- (float (match_operand:SI 1 "nonimmediate_operand" "m,?r"))))]
- "0 && TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[0]))
- && GET_MODE (XEXP (SET_SRC (PATTERN (insn)), 1)) == GET_MODE (operands[0])"
- "#")
-
-;; Split the not-really-implemented gp register case into a
-;; push-op-pop sequence.
-;;
-;; %%% This is most efficient, but am I gonna get in trouble
-;; for separating cc0_setter and cc0_user?
-
-(define_split
- [(set (reg:CCFP FPSR_REG)
- (compare:CCFP
- (match_operand:SF 0 "register_operand" "")
- (float (match_operand:SI 1 "register_operand" ""))))]
- "0 && TARGET_80387 && reload_completed"
- [(set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 1))
- (set (reg:CCFP FPSR_REG) (compare:CCFP (match_dup 0) (match_dup 2)))
- (parallel [(set (match_dup 1) (mem:SI (reg:SI SP_REG)))
- (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])]
- "operands[2] = gen_rtx_MEM (Pmode, stack_pointer_rtx);
- operands[2] = gen_rtx_FLOAT (GET_MODE (operands[0]), operands[2]);")
+(define_insn "*cmpfp_si"
+ [(set (match_operand:HI 0 "register_operand" "=a")
+ (unspec:HI
+ [(compare:CCFP
+ (match_operand 1 "register_operand" "f")
+ (match_operator 3 "float_operator"
+ [(match_operand:SI 2 "memory_operand" "m")]))]
+ UNSPEC_FNSTSW))]
+ "TARGET_80387 && TARGET_USE_FIOP
+ && FLOAT_MODE_P (GET_MODE (operands[1]))
+ && (GET_MODE (operands [3]) == GET_MODE (operands[1]))"
+ "* return output_fp_compare (insn, operands, 0, 0);"
+ [(set_attr "type" "multi")
+ (set_attr "fp_int_src" "true")
+ (set_attr "mode" "SI")])
;; FP compares, step 2
;; Move the fpsw to ax.
@@ -13298,6 +13231,30 @@
&& ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
"#")
+;; The order of operands in *fp_jcc_8 is forced by combine in
+;; simplify_comparison () function. Float operator is treated as RTX_OBJ
+;; with a precedence over other operators and is always put in the first
+;; place. Swap condition and operands to match ficom instruction.
+
+(define_insn "*fp_jcc_8"
+ [(set (pc)
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operator 1 "float_operator"
+ [(match_operand:SI 2 "nonimmediate_operand" "m,?r")])
+ (match_operand 3 "register_operand" "f,f")])
+ (label_ref (match_operand 4 "" ""))
+ (pc)))
+ (clobber (reg:CCFP FPSR_REG))
+ (clobber (reg:CCFP FLAGS_REG))
+ (clobber (match_scratch:HI 5 "=a,a"))]
+ "TARGET_80387 && TARGET_USE_FIOP
+ && FLOAT_MODE_P (GET_MODE (operands[3]))
+ && GET_MODE (operands[1]) == GET_MODE (operands[3])
+ && !ix86_use_fcomi_compare (swap_condition (GET_CODE (operands[0])))
+ && ix86_fp_compare_mode (swap_condition (GET_CODE (operands[0]))) == CCFPmode
+ && ix86_fp_jump_nontrivial_p (swap_condition (GET_CODE (operands[0])))"
+ "#")
+
(define_split
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
@@ -13311,7 +13268,7 @@
[(const_int 0)]
{
ix86_split_fp_branch (GET_CODE (operands[0]), operands[1], operands[2],
- operands[3], operands[4], NULL_RTX);
+ operands[3], operands[4], NULL_RTX, NULL_RTX);
DONE;
})
@@ -13329,7 +13286,51 @@
[(const_int 0)]
{
ix86_split_fp_branch (GET_CODE (operands[0]), operands[1], operands[2],
- operands[3], operands[4], operands[5]);
+ operands[3], operands[4], operands[5], NULL_RTX);
+ DONE;
+})
+
+(define_split
+ [(set (pc)
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operator 1 "float_operator"
+ [(match_operand:SI 2 "memory_operand" "")])
+ (match_operand 3 "register_operand" "")])
+ (match_operand 4 "" "")
+ (match_operand 5 "" "")))
+ (clobber (reg:CCFP FPSR_REG))
+ (clobber (reg:CCFP FLAGS_REG))
+ (clobber (match_scratch:HI 6 "=a"))]
+ "reload_completed"
+ [(const_int 0)]
+{
+ operands[7] = gen_rtx_FLOAT (GET_MODE (operands[1]), operands[2]);
+ ix86_split_fp_branch (swap_condition (GET_CODE (operands[0])),
+ operands[3], operands[7],
+ operands[4], operands[5], operands[6], NULL_RTX);
+ DONE;
+})
+
+;; %%% Kill this when reload knows how to do it.
+(define_split
+ [(set (pc)
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operator 1 "float_operator"
+ [(match_operand:SI 2 "register_operand" "")])
+ (match_operand 3 "register_operand" "")])
+ (match_operand 4 "" "")
+ (match_operand 5 "" "")))
+ (clobber (reg:CCFP FPSR_REG))
+ (clobber (reg:CCFP FLAGS_REG))
+ (clobber (match_scratch:HI 6 "=a"))]
+ "reload_completed"
+ [(const_int 0)]
+{
+ operands[7] = ix86_force_to_memory (GET_MODE (operands[2]), operands[2]);
+ operands[7] = gen_rtx_FLOAT (GET_MODE (operands[1]), operands[7]);
+ ix86_split_fp_branch (swap_condition (GET_CODE (operands[0])),
+ operands[3], operands[7],
+ operands[4], operands[5], operands[6], operands[2]);
DONE;
})
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index ec747ae..9154aea 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -795,6 +795,10 @@
(define_predicate "div_operator"
(match_code "div"))
+;; Return true if this is a float extend operation.
+(define_predicate "float_operator"
+ (match_code "float"))
+
;; Return true for ARITHMETIC_P.
(define_predicate "arith_or_logical_operator"
(match_code "PLUS,MULT,AND,IOR,XOR,SMIN,SMAX,UMIN,UMAX,COMPARE,MINUS,DIV,