+2008-06-19 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.h (ix86_tune_indices)
+ [X86_TUNE_FUSE_CMP_AND_BRANCH]: New.
+ (TARGET_FUSE_CMP_AND_BRANCH): New define.
+ * config/i386/i386.md (*jcc_fused_1): New insn pattern
+ (*jcc_fused_2): Ditto.
+ * config/i386/i386.c (ix86_tune_features): Add m_CORE2 to
+ X86_TUNE_USE_VECTOR_COMPARES targets.
+ (print operand): Handle 'E' and 'e' code.
+
2008-06-19 Anatoly Sokolov <aesok@post.ru>
* config/avr/avr.c (avr_mcu_t): Add attiny13a.
/* X86_TUNE_USE_VECTOR_CONVERTS: Prefer vector packed SSE conversion
from integer to FP. */
m_AMDFAM10,
+
+ /* X86_TUNE_FUSE_CMP_AND_BRANCH: Fuse a compare or test instruction
+ with a subsequent conditional jump instruction into a single
+ compare-and-branch uop. */
+ m_CORE2,
};
/* Feature tests against the various architecture variations. */
L,W,B,Q,S,T -- print the opcode suffix for specified size of operand.
C -- print opcode suffix for set/cmov insn.
c -- like C, but print reversed condition
+ E,e -- likewise, but for compare-and-branch fused insn.
F,f -- likewise, but for floating-point.
O -- if HAVE_AS_IX86_CMOV_SUN_SYNTAX, expand to "w.", "l." or "q.",
otherwise nothing
put_condition_code (GET_CODE (x), GET_MODE (XEXP (x, 0)), 1, 1, file);
return;
+ case 'E':
+ put_condition_code (GET_CODE (x), CCmode, 0, 0, file);
+ return;
+
+ case 'e':
+ put_condition_code (GET_CODE (x), CCmode, 1, 0, file);
+ return;
+
case 'H':
/* It doesn't actually matter what mode we use here, as we're
only going to use this for printing. */
X86_TUNE_NOT_UNPAIRABLE,
X86_TUNE_NOT_VECTORMODE,
X86_TUNE_USE_VECTOR_CONVERTS,
+ X86_TUNE_FUSE_CMP_AND_BRANCH,
X86_TUNE_LAST
};
#define TARGET_MOVE_M1_VIA_OR ix86_tune_features[X86_TUNE_MOVE_M1_VIA_OR]
#define TARGET_NOT_UNPAIRABLE ix86_tune_features[X86_TUNE_NOT_UNPAIRABLE]
#define TARGET_NOT_VECTORMODE ix86_tune_features[X86_TUNE_NOT_VECTORMODE]
-#define TARGET_USE_VECTOR_CONVERTS ix86_tune_features[X86_TUNE_USE_VECTOR_CONVERTS]
+#define TARGET_USE_VECTOR_CONVERTS \
+ ix86_tune_features[X86_TUNE_USE_VECTOR_CONVERTS]
+#define TARGET_FUSE_CMP_AND_BRANCH \
+ ix86_tune_features[X86_TUNE_FUSE_CMP_AND_BRANCH]
/* Feature tests against the various architecture variations. */
enum ix86_arch_indices {
(const_int 2)
(const_int 6)))])
+;; ??? Handle alignment requirements for compare and branch fused macro-op;
+;; the branch instruction does not start at a 16-byte boundary or cross
+;; a 16-byte boundary.
+
+(define_insn "*jcc_fused_1"
+ [(set (pc)
+ (if_then_else (match_operator 1 "ix86_comparison_uns_operator"
+ [(match_operand:SI 2 "nonimmediate_operand" "r,m,r")
+ (match_operand:SI 3 "general_operand" "ri,r,m")])
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ "TARGET_FUSE_CMP_AND_BRANCH && !TARGET_64BIT
+ && !(MEM_P (operands[2]) && MEM_P (operands[3]))"
+{
+ if (REG_P (operands[2])
+ && operands[3] == CONST0_RTX (GET_MODE (operands[3])))
+ output_asm_insn ("test{l}\t%2, %2", operands);
+ else
+ output_asm_insn ("cmp{l}\t{%3, %2|%2, %3}",operands);
+
+ return "%+j%E1\t%l0\t# fused";
+}
+ [(set_attr "type" "multi")
+ (set_attr "mode" "SI")])
+
+(define_insn "*jcc_fused_2"
+ [(set (pc)
+ (if_then_else (match_operator 1 "ix86_comparison_uns_operator"
+ [(match_operand:SI 2 "nonimmediate_operand" "r,m,r")
+ (match_operand:SI 3 "general_operand" "ri,r,m")])
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ "TARGET_FUSE_CMP_AND_BRANCH && !TARGET_64BIT
+ && !(MEM_P (operands[2]) && MEM_P (operands[3]))"
+{
+ if (REG_P (operands[2])
+ && operands[3] == CONST0_RTX (GET_MODE (operands[3])))
+ output_asm_insn ("test{l}\t%2, %2", operands);
+ else
+ output_asm_insn ("cmp{l}\t{%3, %2|%2, %3}",operands);
+
+ return "%+j%e1\t%l0\t# fused";
+}
+ [(set_attr "type" "multi")
+ (set_attr "mode" "SI")])
+
;; In general it is not safe to assume too much about CCmode registers,
;; so simplify-rtx stops when it sees a second one. Under certain
;; conditions this is safe on x86, so help combine not create