- rtx pat;
- enum machine_mode mode = GET_MODE (operands[0]);
-
- if (GET_MODE_SIZE (mode) < 4)
- operands[0] = gen_lowpart (SImode, operands[0]);
- if (mode != Pmode)
- operands[1] = gen_lowpart (Pmode, operands[1]);
- operands[2] = gen_int_mode (1 << INTVAL (operands[2]), Pmode);
-
- pat = gen_rtx_MULT (Pmode, operands[1], operands[2]);
- if (Pmode != SImode)
- pat = gen_rtx_SUBREG (SImode, pat, 0);
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
- DONE;
-})
-
-;; Rare case of shifting RSP is handled by generating move and shift
-(define_split
- [(set (match_operand 0 "register_operand" "")
- (ashift (match_operand 1 "register_operand" "")
- (match_operand:QI 2 "const_int_operand" "")))
- (clobber (reg:CC FLAGS_REG))]
- "reload_completed
- && true_regnum (operands[0]) != true_regnum (operands[1])"
- [(const_int 0)]
-{
- rtx pat, clob;
- emit_move_insn (operands[0], operands[1]);
- pat = gen_rtx_SET (VOIDmode, operands[0],
- gen_rtx_ASHIFT (GET_MODE (operands[0]),
- operands[0], operands[2]));
- clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
- emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, pat, clob)));
- DONE;
-})
-
-(define_insn "*ashlsi3_1_zext"
- [(set (match_operand:DI 0 "register_operand" "=r,r")
- (zero_extend:DI (ashift:SI (match_operand:SI 1 "register_operand" "0,l")
- (match_operand:QI 2 "nonmemory_operand" "cI,M"))))
- (clobber (reg:CC FLAGS_REG))]
- "TARGET_64BIT && ix86_binary_operator_ok (ASHIFT, SImode, operands)"
-{
- switch (get_attr_type (insn))
- {
- case TYPE_ALU:
- gcc_assert (operands[2] == const1_rtx);
- return "add{l}\t%k0, %k0";
-
- case TYPE_LEA:
- return "#";
-
- default:
- if (REG_P (operands[2]))
- return "sal{l}\t{%b2, %k0|%k0, %b2}";
- else if (operands[2] == const1_rtx
- && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)))
- return "sal{l}\t%k0";
- else
- return "sal{l}\t{%2, %k0|%k0, %2}";
- }
-}
- [(set (attr "type")
- (cond [(eq_attr "alternative" "1")
- (const_string "lea")
- (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
- (const_int 0))
- (match_operand 2 "const1_operand" ""))
- (const_string "alu")
- ]
- (const_string "ishift")))
- (set (attr "length_immediate")
- (if_then_else
- (ior (eq_attr "type" "alu")
- (and (eq_attr "type" "ishift")
- (and (match_operand 2 "const1_operand" "")
- (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
- (const_int 0)))))
- (const_string "0")
- (const_string "*")))
- (set_attr "mode" "SI")])
-
-;; Convert lea to the lea pattern to avoid flags dependency.
-(define_split
- [(set (match_operand:DI 0 "register_operand" "")
- (zero_extend:DI (ashift (match_operand 1 "register_operand" "")
- (match_operand:QI 2 "const_int_operand" ""))))
- (clobber (reg:CC FLAGS_REG))]
- "TARGET_64BIT && reload_completed
- && true_regnum (operands[0]) != true_regnum (operands[1])"
- [(set (match_dup 0) (zero_extend:DI
- (subreg:SI (mult:SI (match_dup 1)
- (match_dup 2)) 0)))]
-{
- operands[1] = gen_lowpart (Pmode, operands[1]);
- operands[2] = gen_int_mode (1 << INTVAL (operands[2]), Pmode);
-})
-
-;; This pattern can't accept a variable shift count, since shifts by
-;; zero don't affect the flags. We assume that shifts by constant
-;; zero are optimized away.
-(define_insn "*ashlsi3_cmp"
- [(set (reg FLAGS_REG)
- (compare
- (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0")
- (match_operand:QI 2 "const_1_to_31_operand" "I"))
- (const_int 0)))
- (set (match_operand:SI 0 "nonimmediate_operand" "=rm")
- (ashift:SI (match_dup 1) (match_dup 2)))]
- "(optimize_function_for_size_p (cfun)
- || !TARGET_PARTIAL_FLAG_REG_STALL
- || (operands[2] == const1_rtx
- && (TARGET_SHIFT1
- || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))
- && ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (ASHIFT, SImode, operands)"
-{
- switch (get_attr_type (insn))
- {
- case TYPE_ALU:
- gcc_assert (operands[2] == const1_rtx);
- return "add{l}\t%0, %0";
-
- default:
- if (REG_P (operands[2]))
- return "sal{l}\t{%b2, %0|%0, %b2}";
- else if (operands[2] == const1_rtx
- && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)))
- return "sal{l}\t%0";
- else
- return "sal{l}\t{%2, %0|%0, %2}";
- }
-}
- [(set (attr "type")
- (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
- (const_int 0))
- (match_operand 0 "register_operand" ""))
- (match_operand 2 "const1_operand" ""))
- (const_string "alu")
- ]
- (const_string "ishift")))
- (set (attr "length_immediate")
- (if_then_else
- (ior (eq_attr "type" "alu")
- (and (eq_attr "type" "ishift")
- (and (match_operand 2 "const1_operand" "")
- (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
- (const_int 0)))))
- (const_string "0")
- (const_string "*")))
- (set_attr "mode" "SI")])
-
-(define_insn "*ashlsi3_cconly"
- [(set (reg FLAGS_REG)
- (compare
- (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0")
- (match_operand:QI 2 "const_1_to_31_operand" "I"))
- (const_int 0)))
- (clobber (match_scratch:SI 0 "=r"))]
- "(optimize_function_for_size_p (cfun)
- || !TARGET_PARTIAL_FLAG_REG_STALL
- || (operands[2] == const1_rtx
- && (TARGET_SHIFT1
- || TARGET_DOUBLE_WITH_ADD)))
- && ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (ASHIFT, SImode, operands)"
-{
- switch (get_attr_type (insn))
- {
- case TYPE_ALU:
- gcc_assert (operands[2] == const1_rtx);
- return "add{l}\t%0, %0";
-
- default:
- if (REG_P (operands[2]))
- return "sal{l}\t{%b2, %0|%0, %b2}";
- else if (operands[2] == const1_rtx
- && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)))
- return "sal{l}\t%0";
- else
- return "sal{l}\t{%2, %0|%0, %2}";
- }
-}
- [(set (attr "type")
- (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
- (const_int 0))
- (match_operand 0 "register_operand" ""))
- (match_operand 2 "const1_operand" ""))
- (const_string "alu")
- ]
- (const_string "ishift")))
- (set (attr "length_immediate")
- (if_then_else
- (ior (eq_attr "type" "alu")
- (and (eq_attr "type" "ishift")
- (and (match_operand 2 "const1_operand" "")
- (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
- (const_int 0)))))
- (const_string "0")
- (const_string "*")))
- (set_attr "mode" "SI")])
-
-(define_insn "*ashlsi3_cmp_zext"
- [(set (reg FLAGS_REG)
- (compare
- (ashift:SI (match_operand:SI 1 "register_operand" "0")
- (match_operand:QI 2 "const_1_to_31_operand" "I"))
- (const_int 0)))
- (set (match_operand:DI 0 "register_operand" "=r")
- (zero_extend:DI (ashift:SI (match_dup 1) (match_dup 2))))]
- "TARGET_64BIT
- && (optimize_function_for_size_p (cfun)
- || !TARGET_PARTIAL_FLAG_REG_STALL
- || (operands[2] == const1_rtx
- && (TARGET_SHIFT1
- || TARGET_DOUBLE_WITH_ADD)))
- && ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (ASHIFT, SImode, operands)"
-{
- switch (get_attr_type (insn))
- {
- case TYPE_ALU:
- gcc_assert (operands[2] == const1_rtx);
- return "add{l}\t%k0, %k0";
-
- default:
- if (REG_P (operands[2]))
- return "sal{l}\t{%b2, %k0|%k0, %b2}";
- else if (operands[2] == const1_rtx
- && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)))
- return "sal{l}\t%k0";
- else
- return "sal{l}\t{%2, %k0|%k0, %2}";
- }
-}
- [(set (attr "type")
- (cond [(and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
- (const_int 0))
- (match_operand 2 "const1_operand" ""))
- (const_string "alu")
- ]
- (const_string "ishift")))
- (set (attr "length_immediate")
- (if_then_else
- (ior (eq_attr "type" "alu")
- (and (eq_attr "type" "ishift")
- (and (match_operand 2 "const1_operand" "")
- (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
- (const_int 0)))))
- (const_string "0")
- (const_string "*")))
- (set_attr "mode" "SI")])
-
-(define_expand "ashlhi3"
- [(set (match_operand:HI 0 "nonimmediate_operand" "")
- (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "")
- (match_operand:QI 2 "nonmemory_operand" "")))]
- "TARGET_HIMODE_MATH"
- "ix86_expand_binary_operator (ASHIFT, HImode, operands); DONE;")
-
-(define_insn "*ashlhi3_1_lea"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
- (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0,l")
- (match_operand:QI 2 "nonmemory_operand" "cI,M")))
- (clobber (reg:CC FLAGS_REG))]
- "!TARGET_PARTIAL_REG_STALL
- && ix86_binary_operator_ok (ASHIFT, HImode, operands)"
-{
- switch (get_attr_type (insn))
- {
- case TYPE_LEA:
- return "#";
- case TYPE_ALU:
- gcc_assert (operands[2] == const1_rtx);
- return "add{w}\t%0, %0";
-
- default:
- if (REG_P (operands[2]))
- return "sal{w}\t{%b2, %0|%0, %b2}";
- else if (operands[2] == const1_rtx
- && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)))
- return "sal{w}\t%0";
- else
- return "sal{w}\t{%2, %0|%0, %2}";
- }
-}
- [(set (attr "type")
- (cond [(eq_attr "alternative" "1")
- (const_string "lea")
- (and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
- (const_int 0))
- (match_operand 0 "register_operand" ""))
- (match_operand 2 "const1_operand" ""))
- (const_string "alu")
- ]
- (const_string "ishift")))
- (set (attr "length_immediate")
- (if_then_else
- (ior (eq_attr "type" "alu")
- (and (eq_attr "type" "ishift")
- (and (match_operand 2 "const1_operand" "")
- (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
- (const_int 0)))))
- (const_string "0")
- (const_string "*")))
- (set_attr "mode" "HI,SI")])
-
-(define_insn "*ashlhi3_1"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
- (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0")
- (match_operand:QI 2 "nonmemory_operand" "cI")))
- (clobber (reg:CC FLAGS_REG))]
- "TARGET_PARTIAL_REG_STALL
- && ix86_binary_operator_ok (ASHIFT, HImode, operands)"
-{
- switch (get_attr_type (insn))
- {
- case TYPE_ALU:
- gcc_assert (operands[2] == const1_rtx);
- return "add{w}\t%0, %0";
-
- default:
- if (REG_P (operands[2]))
- return "sal{w}\t{%b2, %0|%0, %b2}";
- else if (operands[2] == const1_rtx
- && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)))
- return "sal{w}\t%0";
- else
- return "sal{w}\t{%2, %0|%0, %2}";
- }
-}
- [(set (attr "type")
- (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
- (const_int 0))
- (match_operand 0 "register_operand" ""))
- (match_operand 2 "const1_operand" ""))
- (const_string "alu")
- ]
- (const_string "ishift")))
- (set (attr "length_immediate")
- (if_then_else
- (ior (eq_attr "type" "alu")
- (and (eq_attr "type" "ishift")
- (and (match_operand 2 "const1_operand" "")
- (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
- (const_int 0)))))
- (const_string "0")
- (const_string "*")))
- (set_attr "mode" "HI")])
-
-;; This pattern can't accept a variable shift count, since shifts by
-;; zero don't affect the flags. We assume that shifts by constant
-;; zero are optimized away.
-(define_insn "*ashlhi3_cmp"
- [(set (reg FLAGS_REG)
- (compare
- (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0")
- (match_operand:QI 2 "const_1_to_31_operand" "I"))
- (const_int 0)))
- (set (match_operand:HI 0 "nonimmediate_operand" "=rm")
- (ashift:HI (match_dup 1) (match_dup 2)))]
- "(optimize_function_for_size_p (cfun)
- || !TARGET_PARTIAL_FLAG_REG_STALL
- || (operands[2] == const1_rtx
- && (TARGET_SHIFT1
- || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))
- && ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (ASHIFT, HImode, operands)"
-{
- switch (get_attr_type (insn))
- {
- case TYPE_ALU:
- gcc_assert (operands[2] == const1_rtx);
- return "add{w}\t%0, %0";
-
- default:
- if (REG_P (operands[2]))
- return "sal{w}\t{%b2, %0|%0, %b2}";
- else if (operands[2] == const1_rtx
- && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)))
- return "sal{w}\t%0";
- else
- return "sal{w}\t{%2, %0|%0, %2}";
- }
-}
- [(set (attr "type")
- (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
- (const_int 0))
- (match_operand 0 "register_operand" ""))
- (match_operand 2 "const1_operand" ""))
- (const_string "alu")
- ]
- (const_string "ishift")))
- (set (attr "length_immediate")
- (if_then_else
- (ior (eq_attr "type" "alu")
- (and (eq_attr "type" "ishift")
- (and (match_operand 2 "const1_operand" "")
- (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
- (const_int 0)))))
- (const_string "0")
- (const_string "*")))
- (set_attr "mode" "HI")])
-
-(define_insn "*ashlhi3_cconly"
- [(set (reg FLAGS_REG)
- (compare
- (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0")
- (match_operand:QI 2 "const_1_to_31_operand" "I"))
- (const_int 0)))
- (clobber (match_scratch:HI 0 "=r"))]
- "(optimize_function_for_size_p (cfun)
- || !TARGET_PARTIAL_FLAG_REG_STALL
- || (operands[2] == const1_rtx
- && (TARGET_SHIFT1
- || TARGET_DOUBLE_WITH_ADD)))
- && ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (ASHIFT, HImode, operands)"
-{
- switch (get_attr_type (insn))
- {
- case TYPE_ALU:
- gcc_assert (operands[2] == const1_rtx);
- return "add{w}\t%0, %0";