aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/gcc/config/i386/i386.md
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.9/gcc/config/i386/i386.md')
-rw-r--r--gcc-4.9/gcc/config/i386/i386.md175
1 files changed, 138 insertions, 37 deletions
diff --git a/gcc-4.9/gcc/config/i386/i386.md b/gcc-4.9/gcc/config/i386/i386.md
index 058702904..39d395875 100644
--- a/gcc-4.9/gcc/config/i386/i386.md
+++ b/gcc-4.9/gcc/config/i386/i386.md
@@ -111,6 +111,7 @@
UNSPEC_LEA_ADDR
UNSPEC_XBEGIN_ABORT
UNSPEC_STOS
+ UNSPEC_INSN_FALSE_DEP
;; For SSE/MMX support:
UNSPEC_FIX_NOTRUNC
@@ -11878,7 +11879,8 @@
DONE;
}
- flags_mode = TARGET_BMI ? CCCmode : CCZmode;
+ flags_mode
+ = (TARGET_BMI && !TARGET_AVOID_FALSE_DEP_FOR_BMI) ? CCCmode : CCZmode;
operands[2] = gen_reg_rtx (<MODE>mode);
operands[3] = gen_rtx_REG (flags_mode, FLAGS_REG);
@@ -11904,7 +11906,8 @@
(parallel [(set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))
(clobber (reg:CC FLAGS_REG))])]
{
- enum machine_mode flags_mode = TARGET_BMI ? CCCmode : CCZmode;
+ enum machine_mode flags_mode
+ = (TARGET_BMI && !TARGET_AVOID_FALSE_DEP_FOR_BMI) ? CCCmode : CCZmode;
operands[3] = gen_lowpart (QImode, operands[2]);
operands[4] = gen_rtx_REG (flags_mode, FLAGS_REG);
@@ -11919,7 +11922,7 @@
(const_int 0)))
(set (match_operand:SWI48 0 "register_operand" "=r")
(ctz:SWI48 (match_dup 1)))]
- "TARGET_BMI"
+ "TARGET_BMI && !TARGET_AVOID_FALSE_DEP_FOR_BMI"
"tzcnt{<imodesuffix>}\t{%1, %0|%0, %1}"
[(set_attr "type" "alu1")
(set_attr "prefix_0f" "1")
@@ -11940,7 +11943,58 @@
(set_attr "btver2_decode" "double")
(set_attr "mode" "<MODE>")])
-(define_insn "ctz<mode>2"
+(define_expand "ctz<mode>2"
+ [(parallel
+ [(set (match_operand:SWI248 0 "register_operand")
+ (ctz:SWI248
+ (match_operand:SWI248 1 "nonimmediate_operand")))
+ (clobber (reg:CC FLAGS_REG))])])
+
+; False dependency happens when destination is only updated by tzcnt,
+; lzcnt or popcnt. There is no false dependency when destination is
+; also used in source.
+(define_insn_and_split "*ctz<mode>2_falsedep_1"
+ [(set (match_operand:SWI48 0 "register_operand" "=r")
+ (ctz:SWI48
+ (match_operand:SWI48 1 "nonimmediate_operand" "rm")))
+ (clobber (reg:CC FLAGS_REG))]
+ "(TARGET_BMI || TARGET_GENERIC)
+ && TARGET_AVOID_FALSE_DEP_FOR_BMI && optimize_function_for_speed_p (cfun)"
+ "#"
+ "&& reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (ctz:SWI48 (match_dup 1)))
+ (unspec [(match_dup 0)] UNSPEC_INSN_FALSE_DEP)
+ (clobber (reg:CC FLAGS_REG))])]
+{
+ if (!reg_mentioned_p (operands[0], operands[1]))
+ ix86_expand_clear (operands[0]);
+})
+
+(define_insn "*ctz<mode>2_falsedep"
+ [(set (match_operand:SWI48 0 "register_operand" "=r")
+ (ctz:SWI48
+ (match_operand:SWI48 1 "nonimmediate_operand" "rm")))
+ (unspec [(match_operand:SWI48 2 "register_operand" "0")]
+ UNSPEC_INSN_FALSE_DEP)
+ (clobber (reg:CC FLAGS_REG))]
+ ""
+{
+ if (TARGET_BMI)
+ return "tzcnt{<imodesuffix>}\t{%1, %0|%0, %1}";
+ else if (TARGET_GENERIC)
+ /* tzcnt expands to 'rep bsf' and we can use it even if !TARGET_BMI. */
+ return "rep%; bsf{<imodesuffix>}\t{%1, %0|%0, %1}";
+ else
+ gcc_unreachable ();
+}
+ [(set_attr "type" "alu1")
+ (set_attr "prefix_0f" "1")
+ (set_attr "prefix_rep" "1")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "*ctz<mode>2"
[(set (match_operand:SWI248 0 "register_operand" "=r")
(ctz:SWI248 (match_operand:SWI248 1 "nonimmediate_operand" "rm")))
(clobber (reg:CC FLAGS_REG))]
@@ -11987,7 +12041,47 @@
operands[2] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode)-1);
})
-(define_insn "clz<mode>2_lzcnt"
+(define_expand "clz<mode>2_lzcnt"
+ [(parallel
+ [(set (match_operand:SWI248 0 "register_operand")
+ (clz:SWI248
+ (match_operand:SWI248 1 "nonimmediate_operand")))
+ (clobber (reg:CC FLAGS_REG))])]
+ "TARGET_LZCNT")
+
+(define_insn_and_split "*clz<mode>2_lzcnt_falsedep_1"
+ [(set (match_operand:SWI48 0 "register_operand" "=r")
+ (clz:SWI48
+ (match_operand:SWI48 1 "nonimmediate_operand" "rm")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_LZCNT
+ && TARGET_AVOID_FALSE_DEP_FOR_BMI && optimize_function_for_speed_p (cfun)"
+ "#"
+ "&& reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (clz:SWI48 (match_dup 1)))
+ (unspec [(match_dup 0)] UNSPEC_INSN_FALSE_DEP)
+ (clobber (reg:CC FLAGS_REG))])]
+{
+ if (!reg_mentioned_p (operands[0], operands[1]))
+ ix86_expand_clear (operands[0]);
+})
+
+(define_insn "*clz<mode>2_lzcnt_falsedep"
+ [(set (match_operand:SWI48 0 "register_operand" "=r")
+ (clz:SWI48
+ (match_operand:SWI48 1 "nonimmediate_operand" "rm")))
+ (unspec [(match_operand:SWI48 2 "register_operand" "0")]
+ UNSPEC_INSN_FALSE_DEP)
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_LZCNT"
+ "lzcnt{<imodesuffix>}\t{%1, %0|%0, %1}"
+ [(set_attr "prefix_rep" "1")
+ (set_attr "type" "bitmanip")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "*clz<mode>2_lzcnt"
[(set (match_operand:SWI248 0 "register_operand" "=r")
(clz:SWI248 (match_operand:SWI248 1 "nonimmediate_operand" "rm")))
(clobber (reg:CC FLAGS_REG))]
@@ -12270,10 +12364,39 @@
(set_attr "prefix_0f" "1")
(set_attr "mode" "HI")])
-(define_insn "popcount<mode>2"
- [(set (match_operand:SWI248 0 "register_operand" "=r")
- (popcount:SWI248
- (match_operand:SWI248 1 "nonimmediate_operand" "rm")))
+(define_expand "popcount<mode>2"
+ [(parallel
+ [(set (match_operand:SWI248 0 "register_operand")
+ (popcount:SWI248
+ (match_operand:SWI248 1 "nonimmediate_operand")))
+ (clobber (reg:CC FLAGS_REG))])]
+ "TARGET_POPCNT")
+
+(define_insn_and_split "*popcount<mode>2_falsedep_1"
+ [(set (match_operand:SWI48 0 "register_operand" "=r")
+ (popcount:SWI48
+ (match_operand:SWI48 1 "nonimmediate_operand" "rm")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_POPCNT
+ && TARGET_AVOID_FALSE_DEP_FOR_BMI && optimize_function_for_speed_p (cfun)"
+ "#"
+ "&& reload_completed"
+ [(parallel
+ [(set (match_dup 0)
+ (popcount:SWI48 (match_dup 1)))
+ (unspec [(match_dup 0)] UNSPEC_INSN_FALSE_DEP)
+ (clobber (reg:CC FLAGS_REG))])]
+{
+ if (!reg_mentioned_p (operands[0], operands[1]))
+ ix86_expand_clear (operands[0]);
+})
+
+(define_insn "*popcount<mode>2_falsedep"
+ [(set (match_operand:SWI48 0 "register_operand" "=r")
+ (popcount:SWI48
+ (match_operand:SWI48 1 "nonimmediate_operand" "rm")))
+ (unspec [(match_operand:SWI48 2 "register_operand" "0")]
+ UNSPEC_INSN_FALSE_DEP)
(clobber (reg:CC FLAGS_REG))]
"TARGET_POPCNT"
{
@@ -12287,15 +12410,12 @@
(set_attr "type" "bitmanip")
(set_attr "mode" "<MODE>")])
-(define_insn "*popcount<mode>2_cmp"
- [(set (reg FLAGS_REG)
- (compare
- (popcount:SWI248
- (match_operand:SWI248 1 "nonimmediate_operand" "rm"))
- (const_int 0)))
- (set (match_operand:SWI248 0 "register_operand" "=r")
- (popcount:SWI248 (match_dup 1)))]
- "TARGET_POPCNT && ix86_match_ccmode (insn, CCZmode)"
+(define_insn "*popcount<mode>2"
+ [(set (match_operand:SWI248 0 "register_operand" "=r")
+ (popcount:SWI248
+ (match_operand:SWI248 1 "nonimmediate_operand" "rm")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_POPCNT"
{
#if TARGET_MACHO
return "popcnt\t{%1, %0|%0, %1}";
@@ -12307,25 +12427,6 @@
(set_attr "type" "bitmanip")
(set_attr "mode" "<MODE>")])
-(define_insn "*popcountsi2_cmp_zext"
- [(set (reg FLAGS_REG)
- (compare
- (popcount:SI (match_operand:SI 1 "nonimmediate_operand" "rm"))
- (const_int 0)))
- (set (match_operand:DI 0 "register_operand" "=r")
- (zero_extend:DI(popcount:SI (match_dup 1))))]
- "TARGET_64BIT && TARGET_POPCNT && ix86_match_ccmode (insn, CCZmode)"
-{
-#if TARGET_MACHO
- return "popcnt\t{%1, %0|%0, %1}";
-#else
- return "popcnt{l}\t{%1, %0|%0, %1}";
-#endif
-}
- [(set_attr "prefix_rep" "1")
- (set_attr "type" "bitmanip")
- (set_attr "mode" "SI")])
-
(define_expand "bswapdi2"
[(set (match_operand:DI 0 "register_operand")
(bswap:DI (match_operand:DI 1 "nonimmediate_operand")))]