[(parallel [(set (match_dup 0) (ashift:SWI48 (match_dup 0) (match_dup 1)))
(clobber (reg:CC FLAGS_REG))])]
"operands[1] = GEN_INT (exact_log2 (INTVAL (operands[1])));")
+
+(define_split
+ [(set (match_operand:SWI48 0 "general_reg_operand")
+ (mult:SWI48 (match_dup 0) (match_operand:SWI48 1 "const1248_operand")))]
+ "TARGET_APX_NF && reload_completed"
+ [(set (match_dup 0) (ashift:SWI48 (match_dup 0) (match_dup 1)))]
+ "operands[1] = GEN_INT (exact_log2 (INTVAL (operands[1])));")
\f
;; Add instructions
(clobber (reg:CC FLAGS_REG))])]
"split_double_mode (<DWI>mode, &operands[0], 1, &operands[0], &operands[5]);")
-(define_insn "*add<mode>_1"
- [(set (match_operand:SWI48 0 "nonimmediate_operand" "=rm,r,r,r,r,r,r")
+(define_subst_attr "nf_name" "nf_subst" "_nf" "")
+(define_subst_attr "nf_prefix" "nf_subst" "%{nf%} " "")
+(define_subst_attr "nf_condition" "nf_subst" "TARGET_APX_NF" "true")
+(define_subst_attr "nf_mem_constraint" "nf_subst" "je" "m")
+(define_subst_attr "nf_applied" "nf_subst" "true" "false")
+
+(define_subst "nf_subst"
+ [(set (match_operand:SWI 0)
+ (match_operand:SWI 1))]
+ ""
+ [(set (match_dup 0)
+ (match_dup 1))
+ (clobber (reg:CC FLAGS_REG))])
+
+(define_insn "*add<mode>_1<nf_name>"
+ [(set (match_operand:SWI48 0 "nonimmediate_operand" "=rm,r<nf_mem_constraint>,r,r,r,r,r,r")
(plus:SWI48
- (match_operand:SWI48 1 "nonimmediate_operand" "%0,0,r,r,rje,jM,r")
- (match_operand:SWI48 2 "x86_64_general_operand" "re,BM,0,le,r,e,BM")))
- (clobber (reg:CC FLAGS_REG))]
- "ix86_binary_operator_ok (PLUS, <MODE>mode, operands, TARGET_APX_NDD)"
+ (match_operand:SWI48 1 "nonimmediate_operand" "%0,0,0,r,r,rje,jM,r")
+ (match_operand:SWI48 2 "x86_64_general_operand" "r,e,BM,0,le,r,e,BM")))]
+ "ix86_binary_operator_ok (PLUS, <MODE>mode, operands, TARGET_APX_NDD)
+ && <nf_condition>"
{
bool use_ndd = get_attr_isa (insn) == ISA_APX_NDD;
switch (get_attr_type (insn))
{
case TYPE_LEA:
- return "#";
+ if (TARGET_APX_NDD && <nf_applied>)
+ return "%{nf%} add{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2}";
+ else
+ return "#";
case TYPE_INCDEC:
if (operands[2] == const1_rtx)
- return use_ndd ? "inc{<imodesuffix>}\t{%1, %0|%0, %1}"
- : "inc{<imodesuffix>}\t%0";
+ return use_ndd ? "<nf_prefix>inc{<imodesuffix>}\t{%1, %0|%0, %1}"
+ : "<nf_prefix>inc{<imodesuffix>}\t%0";
else
{
gcc_assert (operands[2] == constm1_rtx);
- return use_ndd ? "dec{<imodesuffix>}\t{%1, %0|%0, %1}"
- : "dec{<imodesuffix>}\t%0";
+ return use_ndd ? "<nf_prefix>dec{<imodesuffix>}\t{%1, %0|%0, %1}"
+ : "<nf_prefix>dec{<imodesuffix>}\t%0";
}
default:
/* For most processors, ADD is faster than LEA. This alternative
was added to use ADD as much as possible. */
- if (which_alternative == 2)
+ if (which_alternative == 3)
std::swap (operands[1], operands[2]);
if (x86_maybe_negate_const_int (&operands[2], <MODE>mode))
- return use_ndd ? "sub{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2}"
- : "sub{<imodesuffix>}\t{%2, %0|%0, %2}";
+ return use_ndd ? "<nf_prefix>sub{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2}"
+ : "<nf_prefix>sub{<imodesuffix>}\t{%2, %0|%0, %2}";
- return use_ndd ? "add{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2}"
- : "add{<imodesuffix>}\t{%2, %0|%0, %2}";
+ return use_ndd ? "<nf_prefix>add{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2}"
+ : "<nf_prefix>add{<imodesuffix>}\t{%2, %0|%0, %2}";
}
}
- [(set_attr "isa" "*,*,*,*,apx_ndd,apx_ndd,apx_ndd")
+ [(set_attr "isa" "*,*,*,*,*,apx_ndd,apx_ndd,apx_ndd")
(set (attr "type")
- (cond [(eq_attr "alternative" "3")
+ (cond [(eq_attr "alternative" "4")
(const_string "lea")
(match_operand:SWI48 2 "incdec_operand")
(const_string "incdec")
(const_string "*")))
(set_attr "mode" "SI")])
-(define_insn "*addhi_1"
+(define_insn "*addhi_1<nf_name>"
[(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r,r,Yp,r,r")
(plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,r,Yp,rm,r")
- (match_operand:HI 2 "general_operand" "rn,m,0,ln,rn,m")))
- (clobber (reg:CC FLAGS_REG))]
- "ix86_binary_operator_ok (PLUS, HImode, operands, TARGET_APX_NDD)"
+ (match_operand:HI 2 "general_operand" "rn,m,0,ln,rn,m")))]
+ "ix86_binary_operator_ok (PLUS, HImode, operands, TARGET_APX_NDD)
+ && <nf_condition>"
{
bool use_ndd = get_attr_isa (insn) == ISA_APX_NDD;
switch (get_attr_type (insn))
{
case TYPE_LEA:
- return "#";
+ if (TARGET_APX_NDD && <nf_applied>)
+ return "%{nf%} add{w}\t{%2, %1, %0|%0, %1, %2}";
+ else
+ return "#";
case TYPE_INCDEC:
if (operands[2] == const1_rtx)
- return use_ndd ? "inc{w}\t{%1, %0|%0, %1}" : "inc{w}\t%0";
+ return use_ndd ? "<nf_prefix>inc{w}\t{%1, %0|%0, %1}"
+ : "<nf_prefix>inc{w}\t%0";
else
{
gcc_assert (operands[2] == constm1_rtx);
- return use_ndd ? "dec{w}\t{%1, %0|%0, %1}" : "dec{w}\t%0";
+ return use_ndd ? "<nf_prefix>dec{w}\t{%1, %0|%0, %1}"
+ : "<nf_prefix>dec{w}\t%0";
}
default:
std::swap (operands[1], operands[2]);
if (x86_maybe_negate_const_int (&operands[2], HImode))
- return use_ndd ? "sub{w}\t{%2, %1, %0|%0, %1, %2}"
- : "sub{w}\t{%2, %0|%0, %2}";
+ return use_ndd ? "<nf_prefix>sub{w}\t{%2, %1, %0|%0, %1, %2}"
+ : "<nf_prefix>sub{w}\t{%2, %0|%0, %2}";
- return use_ndd ? "add{w}\t{%2, %1, %0|%0, %1, %2}"
- : "add{w}\t{%2, %0|%0, %2}";
+ return use_ndd ? "<nf_prefix>add{w}\t{%2, %1, %0|%0, %1, %2}"
+ : "<nf_prefix>add{w}\t{%2, %0|%0, %2}";
}
}
[(set_attr "isa" "*,*,*,*,apx_ndd,apx_ndd")
(const_string "*")))
(set_attr "mode" "HI,HI,HI,SI,HI,HI")])
-(define_insn "*addqi_1"
+(define_insn "*addqi_1<nf_name>"
[(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,q,r,r,Yp,r,r")
(plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,q,0,r,Yp,rm,r")
- (match_operand:QI 2 "general_operand" "qn,m,0,rn,0,ln,rn,m")))
- (clobber (reg:CC FLAGS_REG))]
- "ix86_binary_operator_ok (PLUS, QImode, operands, TARGET_APX_NDD)"
+ (match_operand:QI 2 "general_operand" "qn,m,0,rn,0,ln,rn,m")))]
+ "ix86_binary_operator_ok (PLUS, QImode, operands, TARGET_APX_NDD)
+ && <nf_condition>"
{
bool widen = (get_attr_mode (insn) != MODE_QI);
bool use_ndd = get_attr_isa (insn) == ISA_APX_NDD;
switch (get_attr_type (insn))
{
case TYPE_LEA:
- return "#";
+ if (TARGET_APX_NDD && <nf_applied>)
+ return "%{nf%} add{b}\t{%2, %1, %0|%0, %1, %2}";
+ else
+ return "#";
case TYPE_INCDEC:
if (operands[2] == const1_rtx)
if (use_ndd)
- return "inc{b}\t{%1, %0|%0, %1}";
+ return "<nf_prefix>inc{b}\t{%1, %0|%0, %1}";
else
- return widen ? "inc{l}\t%k0" : "inc{b}\t%0";
+ return widen ? "<nf_prefix>inc{l}\t%k0" : "<nf_prefix>inc{b}\t%0";
else
{
gcc_assert (operands[2] == constm1_rtx);
if (use_ndd)
- return "dec{b}\t{%1, %0|%0, %1}";
+ return "<nf_prefix>dec{b}\t{%1, %0|%0, %1}";
else
- return widen ? "dec{l}\t%k0" : "dec{b}\t%0";
+ return widen ? "<nf_prefix>dec{l}\t%k0" : "<nf_prefix>dec{b}\t%0";
}
default:
if (x86_maybe_negate_const_int (&operands[2], QImode))
{
if (use_ndd)
- return "sub{b}\t{%2, %1, %0|%0, %1, %2}";
+ return "<nf_prefix>sub{b}\t{%2, %1, %0|%0, %1, %2}";
else
- return widen ? "sub{l}\t{%2, %k0|%k0, %2}"
- : "sub{b}\t{%2, %0|%0, %2}";
+ return widen ? "<nf_prefix>sub{l}\t{%2, %k0|%k0, %2}"
+ : "<nf_prefix>sub{b}\t{%2, %0|%0, %2}";
}
if (use_ndd)
- return "add{b}\t{%2, %1, %0|%0, %1, %2}";
+ return "<nf_prefix>add{b}\t{%2, %1, %0|%0, %1, %2}";
else
- return widen ? "add{l}\t{%k2, %k0|%k0, %k2}"
- : "add{b}\t{%2, %0|%0, %2}";
+ return widen ? "<nf_prefix>add{l}\t{%k2, %k0|%k0, %k2}"
+ : "<nf_prefix>add{b}\t{%2, %0|%0, %2}";
}
}
[(set_attr "isa" "*,*,*,*,*,*,apx_ndd,apx_ndd")
}
})
+(define_split
+ [(set (match_operand:SWI 0 "register_operand")
+ (plus:SWI (match_operand:SWI 1 "register_operand")
+ (match_operand:SWI 2 "<nonmemory_operand>")))]
+ "TARGET_APX_NF && reload_completed
+ && ix86_lea_for_add_ok (insn, operands)"
+ [(set (match_dup 0)
+ (plus:<LEAMODE> (match_dup 1) (match_dup 2)))]
+{
+ if (<MODE>mode != <LEAMODE>mode)
+ {
+ operands[0] = gen_lowpart (<LEAMODE>mode, operands[0]);
+ operands[1] = gen_lowpart (<LEAMODE>mode, operands[1]);
+ operands[2] = gen_lowpart (<LEAMODE>mode, operands[2]);
+ }
+})
+
;; Convert add to the lea pattern to avoid flags dependency.
(define_split
[(set (match_operand:DI 0 "register_operand")