summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUros Bizjak <uros@gcc.gnu.org>2016-12-26 20:00:47 +0100
committerUros Bizjak <uros@gcc.gnu.org>2016-12-26 20:00:47 +0100
commitecb1129654f793279b3b48c276d6d0c412d545d5 (patch)
treeac5f4047326d63f8b746042d39e44bb160463a20
parentdfcbd6b3da9a9cc08df2339a8c29ade1b3d8368c (diff)
downloadgcc-ecb1129654f793279b3b48c276d6d0c412d545d5.tar.gz
re PR target/78904 (zero-extracts are not effective)
PR target/78904 * config/i386/i386.md (addqi_ext_1): Canonicalize insn pattern w.r.t. zero_extract RTXes. (*addqi_ext_2): Ditto. (testqi_ext_ccno_0): Canonicalize expander w.r.t. zero_extract RTXes. (testqi_ext_1_ccno): Rename from testqi_ext_ccno_0. (*testqi_ext_0): Merge with *testqi_ext_1. (*testqi_ext_1): Canonicalize insn pattern w.r.t. zero_extract RTXes. Update corresponding splitter. (*testqi_ext_2): Canonicalize insn pattern w.r.t. zero_extract RTXes. (*andqi_ext_0): Merge with *andqi_ext_1. (andqi_ext_1): Canonicalize insn pattern w.r.t. zero_extract RTXes. Rename from *andqi_ext_1. Update corresponding splitter and peephole2 patterns. (*andqi_ext_1_cc): Rename from *andqi_ext_0_cc. (*andqi_ext_2): Canonicalize insn pattern w.r.t. zero_extract RTXes. (*<any_or:code>qi_ext_0): Merge with *andqi_ext_1. (*<any_or:code>qi_ext_1): Canonicalize insn pattern w.r.t. zero_extract RTXes. Update corresponding splitter. (*<any_or:code>qi_ext_2): Canonicalize insn pattern w.r.t. zero_extract RTXes. (xorqi_cc_ext_1): Canonicalize expander w.r.t. zero_extract RTXes. (xorqi_ext_1_cc): Rename from xorqi_cc_ext_1. (*xorqi_cc_ext_1): Canonicalize insn pattern w.r.t. zero_extract RTXes. Update corresponding splitter. (*xorqi_ext_1_cc): Rename from *xorqi_cc_ext_1. (isinfxf2): Update calls to renamed expanders. (isinf<mode>2): Ditto. * config/i386/i386.c (ix86_expand_fp_compare): Ditto. (ix86_emit_fp_unordered_jump): Ditto. (ix86_emit_i387_round): Ditto. testsuite/ChangeLog: PR target/78904 * gcc.target/i386/pr78904.c: New test. From-SVN: r243929
-rw-r--r--gcc/ChangeLog37
-rw-r--r--gcc/config/i386/i386.c36
-rw-r--r--gcc/config/i386/i386.md422
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/i386/pr78904.c48
5 files changed, 301 insertions, 247 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index cdb6b5b1b58..e7865bdf7b5 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,37 @@
+2016-12-26 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/78904
+ * config/i386/i386.md (addqi_ext_1): Canonicalize insn pattern w.r.t.
+ zero_extract RTXes.
+ (*addqi_ext_2): Ditto.
+ (testqi_ext_ccno_0): Canonicalize expander w.r.t. zero_extract RTXes.
+ (testqi_ext_1_ccno): Rename from testqi_ext_ccno_0.
+ (*testqi_ext_0): Merge with *testqi_ext_1.
+ (*testqi_ext_1): Canonicalize insn pattern w.r.t. zero_extract RTXes.
+ Update corresponding splitter.
+ (*testqi_ext_2): Canonicalize insn pattern w.r.t. zero_extract RTXes.
+ (*andqi_ext_0): Merge with *andqi_ext_1.
+ (andqi_ext_1): Canonicalize insn pattern w.r.t. zero_extract RTXes.
+ Rename from *andqi_ext_1. Update corresponding splitter and
+ peephole2 patterns.
+ (*andqi_ext_1_cc): Rename from *andqi_ext_0_cc.
+ (*andqi_ext_2): Canonicalize insn pattern w.r.t. zero_extract RTXes.
+ (*<any_or:code>qi_ext_0): Merge with *andqi_ext_1.
+ (*<any_or:code>qi_ext_1): Canonicalize insn pattern w.r.t.
+ zero_extract RTXes. Update corresponding splitter.
+ (*<any_or:code>qi_ext_2): Canonicalize insn pattern w.r.t.
+ zero_extract RTXes.
+ (xorqi_cc_ext_1): Canonicalize expander w.r.t. zero_extract RTXes.
+ (xorqi_ext_1_cc): Rename from xorqi_cc_ext_1.
+ (*xorqi_cc_ext_1): Canonicalize insn pattern w.r.t. zero_extract RTXes.
+ Update corresponding splitter.
+ (*xorqi_ext_1_cc): Rename from *xorqi_cc_ext_1.
+ (isinfxf2): Update calls to renamed expanders.
+ (isinf<mode>2): Ditto.
+ * config/i386/i386.c (ix86_expand_fp_compare): Ditto.
+ (ix86_emit_fp_unordered_jump): Ditto.
+ (ix86_emit_i387_round): Ditto.
+
2016-12-26 Eric Botcazou <ebotcazou@adacore.com>
* doc/invoke.texi (SPARC options): Add missing documentation for -mlra.
@@ -89,7 +123,8 @@
(rs6000_option_optimization_table): Enable -fsched-pressure.
* config/rs6000/rs6000.c (TARGET_COMPUTE_PRESSURE_CLASSES): Define
target hook.
- (rs6000_option_override_internal): Set default -fsched-pressure algorithm.
+ (rs6000_option_override_internal): Set default -fsched-pressure
+ algorithm.
(rs6000_compute_pressure_classes): Implement target hook.
2016-12-21 Bill Seurer <seurer@linux.vnet.ibm.com>
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 792e8ec232d..624f0699e66 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -22585,12 +22585,12 @@ ix86_expand_fp_compare (enum rtx_code code, rtx op0, rtx op1, rtx scratch)
case UNGT:
if (code == GT || !TARGET_IEEE_FP)
{
- emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x45)));
+ emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x45)));
code = EQ;
}
else
{
- emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45)));
+ emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)));
emit_insn (gen_addqi_ext_1 (scratch, scratch, constm1_rtx));
emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x44)));
intcmp_mode = CCmode;
@@ -22601,14 +22601,14 @@ ix86_expand_fp_compare (enum rtx_code code, rtx op0, rtx op1, rtx scratch)
case UNLT:
if (code == LT && TARGET_IEEE_FP)
{
- emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45)));
+ emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)));
emit_insn (gen_cmpqi_ext_3 (scratch, const1_rtx));
intcmp_mode = CCmode;
code = EQ;
}
else
{
- emit_insn (gen_testqi_ext_ccno_0 (scratch, const1_rtx));
+ emit_insn (gen_testqi_ext_1_ccno (scratch, const1_rtx));
code = NE;
}
break;
@@ -22616,13 +22616,13 @@ ix86_expand_fp_compare (enum rtx_code code, rtx op0, rtx op1, rtx scratch)
case UNGE:
if (code == GE || !TARGET_IEEE_FP)
{
- emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x05)));
+ emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x05)));
code = EQ;
}
else
{
- emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45)));
- emit_insn (gen_xorqi_cc_ext_1 (scratch, scratch, const1_rtx));
+ emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)));
+ emit_insn (gen_xorqi_ext_1_cc (scratch, scratch, const1_rtx));
code = NE;
}
break;
@@ -22630,7 +22630,7 @@ ix86_expand_fp_compare (enum rtx_code code, rtx op0, rtx op1, rtx scratch)
case UNLE:
if (code == LE && TARGET_IEEE_FP)
{
- emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45)));
+ emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)));
emit_insn (gen_addqi_ext_1 (scratch, scratch, constm1_rtx));
emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x40)));
intcmp_mode = CCmode;
@@ -22638,7 +22638,7 @@ ix86_expand_fp_compare (enum rtx_code code, rtx op0, rtx op1, rtx scratch)
}
else
{
- emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x45)));
+ emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x45)));
code = NE;
}
break;
@@ -22646,14 +22646,14 @@ ix86_expand_fp_compare (enum rtx_code code, rtx op0, rtx op1, rtx scratch)
case UNEQ:
if (code == EQ && TARGET_IEEE_FP)
{
- emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45)));
+ emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)));
emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x40)));
intcmp_mode = CCmode;
code = EQ;
}
else
{
- emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x40)));
+ emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x40)));
code = NE;
}
break;
@@ -22661,24 +22661,24 @@ ix86_expand_fp_compare (enum rtx_code code, rtx op0, rtx op1, rtx scratch)
case LTGT:
if (code == NE && TARGET_IEEE_FP)
{
- emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45)));
- emit_insn (gen_xorqi_cc_ext_1 (scratch, scratch,
+ emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)));
+ emit_insn (gen_xorqi_ext_1_cc (scratch, scratch,
GEN_INT (0x40)));
code = NE;
}
else
{
- emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x40)));
+ emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x40)));
code = EQ;
}
break;
case UNORDERED:
- emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x04)));
+ emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x04)));
code = NE;
break;
case ORDERED:
- emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x04)));
+ emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x04)));
code = EQ;
break;
@@ -44370,7 +44370,7 @@ ix86_emit_fp_unordered_jump (rtx label)
}
else
{
- emit_insn (gen_testqi_ext_ccno_0 (reg, GEN_INT (0x04)));
+ emit_insn (gen_testqi_ext_1_ccno (reg, GEN_INT (0x04)));
temp = gen_rtx_REG (CCNOmode, FLAGS_REG);
temp = gen_rtx_NE (VOIDmode, temp, const0_rtx);
@@ -44528,7 +44528,7 @@ void ix86_emit_i387_round (rtx op0, rtx op1)
}
/* flags = signbit(a) */
- emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x02)));
+ emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x02)));
/* if (flags) then res = -res */
tmp = gen_rtx_IF_THEN_ELSE (VOIDmode,
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index f50dbab42e9..f3f358326ac 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -1345,7 +1345,6 @@
"cmp{b}\t{%1, %h0|%h0, %1}"
[(set_attr "isa" "*,nox64")
(set_attr "type" "icmp")
- (set_attr "modrm" "1")
(set_attr "mode" "QI")])
(define_insn "*cmpqi_ext_4"
@@ -6082,12 +6081,13 @@
[(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q,Q")
(const_int 8)
(const_int 8))
- (plus:SI
- (zero_extract:SI
- (match_operand 1 "ext_register_operand" "0,0")
- (const_int 8)
- (const_int 8))
- (match_operand:QI 2 "general_x64nomem_operand" "Qn,m")))
+ (subreg:SI
+ (plus:QI
+ (subreg:QI
+ (zero_extract:SI (match_operand 1 "ext_register_operand" "0,0")
+ (const_int 8)
+ (const_int 8)) 0)
+ (match_operand:QI 2 "general_x64nomem_operand" "Qn,m")) 0))
(clobber (reg:CC FLAGS_REG))]
""
{
@@ -6111,23 +6111,23 @@
(if_then_else (match_operand:QI 2 "incdec_operand")
(const_string "incdec")
(const_string "alu")))
- (set_attr "modrm" "1")
(set_attr "mode" "QI")])
(define_insn "*addqi_ext_2"
[(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
(const_int 8)
(const_int 8))
- (plus:SI
- (zero_extract:SI
- (match_operand 1 "ext_register_operand" "%0")
- (const_int 8)
- (const_int 8))
- (zero_extract:SI
- (match_operand 2 "ext_register_operand" "Q")
- (const_int 8)
- (const_int 8))))
- (clobber (reg:CC FLAGS_REG))]
+ (subreg:SI
+ (plus:QI
+ (subreg:QI
+ (zero_extract:SI (match_operand 1 "ext_register_operand" "%0")
+ (const_int 8)
+ (const_int 8)) 0)
+ (subreg:QI
+ (zero_extract:SI (match_operand 2 "ext_register_operand" "Q")
+ (const_int 8)
+ (const_int 8)) 0)) 0))
+ (clobber (reg:CC FLAGS_REG))]
""
"add{b}\t{%h2, %h0|%h0, %h2}"
[(set_attr "type" "alu")
@@ -7870,45 +7870,26 @@
(set_attr "mode" "<MODE>")
(set_attr "pent_pair" "uv,np,uv")])
-(define_expand "testqi_ext_ccno_0"
+(define_expand "testqi_ext_1_ccno"
[(set (reg:CCNO FLAGS_REG)
(compare:CCNO
- (and:SI
- (zero_extract:SI
- (match_operand 0 "ext_register_operand")
- (const_int 8)
- (const_int 8))
- (match_operand 1 "const_int_operand"))
+ (and:QI
+ (subreg:QI
+ (zero_extract:SI (match_operand 0 "ext_register_operand")
+ (const_int 8)
+ (const_int 8)) 0)
+ (match_operand 1 "const_int_operand"))
(const_int 0)))])
-(define_insn "*testqi_ext_0"
- [(set (reg FLAGS_REG)
- (compare
- (and:SI
- (zero_extract:SI
- (match_operand 0 "ext_register_operand" "Q")
- (const_int 8)
- (const_int 8))
- (match_operand 1 "const_int_operand" "n"))
- (const_int 0)))]
- "ix86_match_ccmode (insn, CCNOmode)"
- "test{b}\t{%1, %h0|%h0, %1}"
- [(set_attr "type" "test")
- (set_attr "mode" "QI")
- (set_attr "length_immediate" "1")
- (set_attr "modrm" "1")
- (set_attr "pent_pair" "np")])
-
(define_insn "*testqi_ext_1"
[(set (reg FLAGS_REG)
(compare
- (and:SI
- (zero_extract:SI
- (match_operand 0 "ext_register_operand" "Q,Q")
- (const_int 8)
- (const_int 8))
- (zero_extend:SI
- (match_operand:QI 1 "nonimmediate_x64nomem_operand" "Q,m")))
+ (and:QI
+ (subreg:QI
+ (zero_extract:SI (match_operand 0 "ext_register_operand" "Q,Q")
+ (const_int 8)
+ (const_int 8)) 0)
+ (match_operand:QI 1 "general_x64nomem_operand" "Qn,m"))
(const_int 0)))]
"ix86_match_ccmode (insn, CCNOmode)"
"test{b}\t{%1, %h0|%h0, %1}"
@@ -7919,15 +7900,15 @@
(define_insn "*testqi_ext_2"
[(set (reg FLAGS_REG)
(compare
- (and:SI
- (zero_extract:SI
- (match_operand 0 "ext_register_operand" "Q")
- (const_int 8)
- (const_int 8))
- (zero_extract:SI
- (match_operand 1 "ext_register_operand" "Q")
- (const_int 8)
- (const_int 8)))
+ (and:QI
+ (subreg:QI
+ (zero_extract:SI (match_operand 0 "ext_register_operand" "Q")
+ (const_int 8)
+ (const_int 8)) 0)
+ (subreg:QI
+ (zero_extract:SI (match_operand 1 "ext_register_operand" "Q")
+ (const_int 8)
+ (const_int 8)) 0))
(const_int 0)))]
"ix86_match_ccmode (insn, CCNOmode)"
"test{b}\t{%h1, %h0|%h0, %h1}"
@@ -8029,12 +8010,16 @@
&& !(INTVAL (operands[3]) & ~(127 << 8))))"
[(set (match_dup 0)
(match_op_dup 1
- [(and:SI (zero_extract:SI (match_dup 2) (const_int 8) (const_int 8))
- (match_dup 3))
+ [(and:QI
+ (subreg:QI
+ (zero_extract:SI (match_dup 2)
+ (const_int 8)
+ (const_int 8)) 0)
+ (match_dup 3))
(const_int 0)]))]
{
operands[2] = gen_lowpart (SImode, operands[2]);
- operands[3] = gen_int_mode (INTVAL (operands[3]) >> 8, SImode);
+ operands[3] = gen_int_mode (INTVAL (operands[3]) >> 8, QImode);
})
(define_split
@@ -8308,17 +8293,21 @@
(clobber (reg:CC FLAGS_REG))]
"(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
&& reload_completed"
- [(parallel [(set (zero_extract:SI (match_dup 0)
- (const_int 8)
- (const_int 8))
- (xor:SI
- (zero_extract:SI (match_dup 0)
- (const_int 8)
- (const_int 8))
- (zero_extract:SI (match_dup 0)
- (const_int 8)
- (const_int 8))))
- (clobber (reg:CC FLAGS_REG))])]
+ [(parallel
+ [(set (zero_extract:SI (match_dup 0)
+ (const_int 8)
+ (const_int 8))
+ (subreg:SI
+ (xor:QI
+ (subreg:QI
+ (zero_extract:SI (match_dup 0)
+ (const_int 8)
+ (const_int 8)) 0)
+ (subreg:QI
+ (zero_extract:SI (match_dup 0)
+ (const_int 8)
+ (const_int 8)) 0)) 0))
+ (clobber (reg:CC FLAGS_REG))])]
"operands[0] = gen_lowpart (SImode, operands[0]);")
(define_insn "*anddi_2"
@@ -8418,92 +8407,69 @@
[(set_attr "type" "alu1")
(set_attr "mode" "QI")])
-;; ??? A bug in recog prevents it from recognizing a const_int as an
-;; operand to zero_extend in andqi_ext_1. It was checking explicitly
-;; for a QImode operand, which of course failed.
-(define_insn "andqi_ext_0"
- [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
+(define_insn "andqi_ext_1"
+ [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q,Q")
(const_int 8)
(const_int 8))
- (and:SI
- (zero_extract:SI
- (match_operand 1 "ext_register_operand" "0")
- (const_int 8)
- (const_int 8))
- (match_operand 2 "const_int_operand" "n")))
+ (subreg:SI
+ (and:QI
+ (subreg:QI
+ (zero_extract:SI (match_operand 1 "ext_register_operand" "0,0")
+ (const_int 8)
+ (const_int 8)) 0)
+ (match_operand:QI 2 "general_x64nomem_operand" "Qn,m")) 0))
(clobber (reg:CC FLAGS_REG))]
""
"and{b}\t{%2, %h0|%h0, %2}"
- [(set_attr "type" "alu")
- (set_attr "length_immediate" "1")
- (set_attr "modrm" "1")
+ [(set_attr "isa" "*,nox64")
+ (set_attr "type" "alu")
(set_attr "mode" "QI")])
;; Generated by peephole translating test to and. This shows up
;; often in fp comparisons.
-(define_insn "*andqi_ext_0_cc"
+(define_insn "*andqi_ext_1_cc"
[(set (reg FLAGS_REG)
(compare
- (and:SI
- (zero_extract:SI
- (match_operand 1 "ext_register_operand" "0")
- (const_int 8)
- (const_int 8))
+ (and:QI
+ (subreg:QI
+ (zero_extract:SI (match_operand 1 "ext_register_operand" "0")
+ (const_int 8)
+ (const_int 8)) 0)
(match_operand 2 "const_int_operand" "n"))
(const_int 0)))
(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
(const_int 8)
(const_int 8))
- (and:SI
- (zero_extract:SI
- (match_dup 1)
- (const_int 8)
- (const_int 8))
- (match_dup 2)))]
+ (subreg:SI
+ (and:QI
+ (subreg:QI
+ (zero_extract:SI (match_dup 1)
+ (const_int 8)
+ (const_int 8)) 0)
+ (match_dup 2)) 0))]
"ix86_match_ccmode (insn, CCNOmode)"
"and{b}\t{%2, %h0|%h0, %2}"
[(set_attr "type" "alu")
- (set_attr "length_immediate" "1")
- (set_attr "modrm" "1")
- (set_attr "mode" "QI")])
-
-(define_insn "*andqi_ext_1"
- [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q,Q")
- (const_int 8)
- (const_int 8))
- (and:SI
- (zero_extract:SI
- (match_operand 1 "ext_register_operand" "0,0")
- (const_int 8)
- (const_int 8))
- (zero_extend:SI
- (match_operand:QI 2 "nonimmediate_x64nomem_operand" "Q,m"))))
- (clobber (reg:CC FLAGS_REG))]
- ""
- "and{b}\t{%2, %h0|%h0, %2}"
- [(set_attr "isa" "*,nox64")
- (set_attr "type" "alu")
- (set_attr "length_immediate" "0")
(set_attr "mode" "QI")])
(define_insn "*andqi_ext_2"
[(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
(const_int 8)
(const_int 8))
- (and:SI
- (zero_extract:SI
- (match_operand 1 "ext_register_operand" "%0")
- (const_int 8)
- (const_int 8))
- (zero_extract:SI
- (match_operand 2 "ext_register_operand" "Q")
- (const_int 8)
- (const_int 8))))
+ (subreg:SI
+ (and:QI
+ (subreg:QI
+ (zero_extract:SI (match_operand 1 "ext_register_operand" "%0")
+ (const_int 8)
+ (const_int 8)) 0)
+ (subreg:QI
+ (zero_extract:SI (match_operand 2 "ext_register_operand" "Q")
+ (const_int 8)
+ (const_int 8)) 0)) 0))
(clobber (reg:CC FLAGS_REG))]
""
"and{b}\t{%h2, %h0|%h0, %h2}"
[(set_attr "type" "alu")
- (set_attr "length_immediate" "0")
(set_attr "mode" "QI")])
;; Convert wide AND instructions with immediate operand to shorter QImode
@@ -8519,15 +8485,22 @@
"reload_completed
&& (!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
&& !(~INTVAL (operands[2]) & ~(255 << 8))"
- [(parallel [(set (zero_extract:SI (match_dup 0) (const_int 8) (const_int 8))
- (and:SI (zero_extract:SI (match_dup 1)
- (const_int 8) (const_int 8))
- (match_dup 2)))
- (clobber (reg:CC FLAGS_REG))])]
+ [(parallel
+ [(set (zero_extract:SI (match_dup 0)
+ (const_int 8)
+ (const_int 8))
+ (subreg:SI
+ (and:QI
+ (subreg:QI
+ (zero_extract:SI (match_dup 1)
+ (const_int 8)
+ (const_int 8)) 0)
+ (match_dup 2)) 0))
+ (clobber (reg:CC FLAGS_REG))])]
{
operands[0] = gen_lowpart (SImode, operands[0]);
operands[1] = gen_lowpart (SImode, operands[1]);
- operands[2] = gen_int_mode ((INTVAL (operands[2]) >> 8) & 0xff, SImode);
+ operands[2] = gen_int_mode (INTVAL (operands[2]) >> 8, QImode);
})
;; Since AND can be encoded with sign extended immediate, this is only
@@ -8820,59 +8793,42 @@
[(set_attr "type" "alu")
(set_attr "mode" "<MODE>")])
-(define_insn "*<code>qi_ext_0"
- [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
- (const_int 8)
- (const_int 8))
- (any_or:SI
- (zero_extract:SI
- (match_operand 1 "ext_register_operand" "0")
- (const_int 8)
- (const_int 8))
- (match_operand 2 "const_int_operand" "n")))
- (clobber (reg:CC FLAGS_REG))]
- "!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)"
- "<logic>{b}\t{%2, %h0|%h0, %2}"
- [(set_attr "type" "alu")
- (set_attr "length_immediate" "1")
- (set_attr "modrm" "1")
- (set_attr "mode" "QI")])
-
(define_insn "*<code>qi_ext_1"
[(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q,Q")
(const_int 8)
(const_int 8))
- (any_or:SI
- (zero_extract:SI
- (match_operand 1 "ext_register_operand" "0,0")
- (const_int 8)
- (const_int 8))
- (zero_extend:SI
- (match_operand:QI 2 "nonimmediate_x64nomem_operand" "Q,m"))))
+ (subreg:SI
+ (any_or:QI
+ (subreg:QI
+ (zero_extract:SI (match_operand 1 "ext_register_operand" "0,0")
+ (const_int 8)
+ (const_int 8)) 0)
+ (match_operand:QI 2 "general_x64nomem_operand" "Qn,m")) 0))
(clobber (reg:CC FLAGS_REG))]
"!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)"
"<logic>{b}\t{%2, %h0|%h0, %2}"
[(set_attr "isa" "*,nox64")
(set_attr "type" "alu")
- (set_attr "length_immediate" "0")
(set_attr "mode" "QI")])
(define_insn "*<code>qi_ext_2"
[(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
(const_int 8)
(const_int 8))
- (any_or:SI
- (zero_extract:SI (match_operand 1 "ext_register_operand" "0")
- (const_int 8)
- (const_int 8))
- (zero_extract:SI (match_operand 2 "ext_register_operand" "Q")
- (const_int 8)
- (const_int 8))))
+ (subreg:SI
+ (any_or:QI
+ (subreg:QI
+ (zero_extract:SI (match_operand 1 "ext_register_operand" "%0")
+ (const_int 8)
+ (const_int 8)) 0)
+ (subreg:QI
+ (zero_extract:SI (match_operand 2 "ext_register_operand" "Q")
+ (const_int 8)
+ (const_int 8)) 0)) 0))
(clobber (reg:CC FLAGS_REG))]
"!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)"
"<logic>{b}\t{%h2, %h0|%h0, %h2}"
[(set_attr "type" "alu")
- (set_attr "length_immediate" "0")
(set_attr "mode" "QI")])
;; Convert wide OR instructions with immediate operand to shorter QImode
@@ -8888,15 +8844,22 @@
"reload_completed
&& (!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
&& !(INTVAL (operands[2]) & ~(255 << 8))"
- [(parallel [(set (zero_extract:SI (match_dup 0) (const_int 8) (const_int 8))
- (any_or:SI (zero_extract:SI (match_dup 1)
- (const_int 8) (const_int 8))
- (match_dup 2)))
- (clobber (reg:CC FLAGS_REG))])]
+ [(parallel
+ [(set (zero_extract:SI (match_dup 0)
+ (const_int 8)
+ (const_int 8))
+ (subreg:SI
+ (any_or:QI
+ (subreg:QI
+ (zero_extract:SI (match_dup 1)
+ (const_int 8)
+ (const_int 8)) 0)
+ (match_dup 2)) 0))
+ (clobber (reg:CC FLAGS_REG))])]
{
operands[0] = gen_lowpart (SImode, operands[0]);
operands[1] = gen_lowpart (SImode, operands[1]);
- operands[2] = gen_int_mode ((INTVAL (operands[2]) >> 8) & 0xff, SImode);
+ operands[2] = gen_int_mode (INTVAL (operands[2]) >> 8, QImode);
})
;; Since OR can be encoded with sign extended immediate, this is only
@@ -8920,51 +8883,52 @@
operands[2] = gen_lowpart (QImode, operands[2]);
})
-(define_expand "xorqi_cc_ext_1"
+(define_expand "xorqi_ext_1_cc"
[(parallel [
(set (reg:CCNO FLAGS_REG)
(compare:CCNO
- (xor:SI
- (zero_extract:SI
- (match_operand 1 "ext_register_operand")
- (const_int 8)
- (const_int 8))
- (match_operand:QI 2 "const_int_operand"))
+ (xor:QI
+ (subreg:QI
+ (zero_extract:SI (match_operand 1 "ext_register_operand")
+ (const_int 8)
+ (const_int 8)) 0)
+ (match_operand 2 "const_int_operand"))
(const_int 0)))
(set (zero_extract:SI (match_operand 0 "ext_register_operand")
(const_int 8)
(const_int 8))
- (xor:SI
- (zero_extract:SI
- (match_dup 1)
- (const_int 8)
- (const_int 8))
- (match_dup 2)))])])
-
-(define_insn "*xorqi_cc_ext_1"
+ (subreg:SI
+ (xor:QI
+ (subreg:QI
+ (zero_extract:SI (match_dup 1)
+ (const_int 8)
+ (const_int 8)) 0)
+ (match_dup 2)) 0))])])
+
+(define_insn "*xorqi_ext_1_cc"
[(set (reg FLAGS_REG)
(compare
- (xor:SI
- (zero_extract:SI
- (match_operand 1 "ext_register_operand" "0,0")
- (const_int 8)
- (const_int 8))
+ (xor:QI
+ (subreg:QI
+ (zero_extract:SI (match_operand 1 "ext_register_operand" "0,0")
+ (const_int 8)
+ (const_int 8)) 0)
(match_operand:QI 2 "general_x64nomem_operand" "Qn,m"))
(const_int 0)))
(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q,Q")
(const_int 8)
(const_int 8))
- (xor:SI
- (zero_extract:SI
- (match_dup 1)
- (const_int 8)
- (const_int 8))
- (match_dup 2)))]
+ (subreg:SI
+ (xor:QI
+ (subreg:QI
+ (zero_extract:SI (match_dup 1)
+ (const_int 8)
+ (const_int 8)) 0)
+ (match_dup 2)) 0))]
"ix86_match_ccmode (insn, CCNOmode)"
"xor{b}\t{%2, %h0|%h0, %2}"
[(set_attr "isa" "*,nox64")
(set_attr "type" "alu")
- (set_attr "modrm" "1")
(set_attr "mode" "QI")])
;; Negation instructions
@@ -16098,7 +16062,7 @@
emit_insn (gen_fxamxf2_i387 (scratch, operands[1]));
- emit_insn (gen_andqi_ext_0 (scratch, scratch, mask));
+ emit_insn (gen_andqi_ext_1 (scratch, scratch, mask));
emit_insn (gen_cmpqi_ext_3 (scratch, val));
ix86_expand_setcc (res, EQ,
gen_rtx_REG (CCmode, FLAGS_REG), const0_rtx);
@@ -16130,7 +16094,7 @@
emit_insn (gen_fxam<mode>2_i387_with_temp (scratch, temp));
}
- emit_insn (gen_andqi_ext_0 (scratch, scratch, mask));
+ emit_insn (gen_andqi_ext_1 (scratch, scratch, mask));
emit_insn (gen_cmpqi_ext_3 (scratch, val));
ix86_expand_setcc (res, EQ,
gen_rtx_REG (CCmode, FLAGS_REG), const0_rtx);
@@ -17851,35 +17815,37 @@
(define_peephole2
[(set (match_operand 0 "flags_reg_operand")
(match_operator 1 "compare_operator"
- [(and:SI
- (zero_extract:SI
- (match_operand 2 "QIreg_operand")
- (const_int 8)
- (const_int 8))
+ [(and:QI
+ (subreg:QI
+ (zero_extract:SI (match_operand 2 "QIreg_operand")
+ (const_int 8)
+ (const_int 8)) 0)
(match_operand 3 "const_int_operand"))
(const_int 0)]))]
"! TARGET_PARTIAL_REG_STALL
&& ix86_match_ccmode (insn, CCNOmode)
&& REGNO (operands[2]) != AX_REG
&& peep2_reg_dead_p (1, operands[2])"
- [(parallel [(set (match_dup 0)
- (match_op_dup 1
- [(and:SI
- (zero_extract:SI
- (match_dup 2)
- (const_int 8)
- (const_int 8))
- (match_dup 3))
- (const_int 0)]))
- (set (zero_extract:SI (match_dup 2)
- (const_int 8)
- (const_int 8))
- (and:SI
- (zero_extract:SI
- (match_dup 2)
- (const_int 8)
- (const_int 8))
- (match_dup 3)))])])
+ [(parallel
+ [(set (match_dup 0)
+ (match_op_dup 1
+ [(and:QI
+ (subreg:QI
+ (zero_extract:SI (match_dup 2)
+ (const_int 8)
+ (const_int 8)) 0)
+ (match_dup 3))
+ (const_int 0)]))
+ (set (zero_extract:SI (match_dup 2)
+ (const_int 8)
+ (const_int 8))
+ (subreg:SI
+ (and:QI
+ (subreg:QI
+ (zero_extract:SI (match_dup 2)
+ (const_int 8)
+ (const_int 8)) 0)
+ (match_dup 3)) 0))])])
;; Don't do logical operations with memory inputs.
(define_peephole2
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 969c896af40..31f0e434583 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2016-12-26 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/78904
+ * gcc.target/i386/pr78904.c: New test.
+
2016-12-23 Andre Vehreschild <vehre@gcc.gnu.org>
* gfortran.dg/class_assign_1.f08: New test.
diff --git a/gcc/testsuite/gcc.target/i386/pr78904.c b/gcc/testsuite/gcc.target/i386/pr78904.c
new file mode 100644
index 00000000000..d27d7fd651d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr78904.c
@@ -0,0 +1,48 @@
+/* PR target/78904 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -masm=att" } */
+/* { dg-final { scan-assembler-not "movzbl" } } */
+/* { dg-final { scan-assembler-not "movb" } } */
+
+struct S1
+{
+ unsigned char pad1;
+ unsigned char val;
+ unsigned short pad2;
+};
+
+struct S1 test_and (struct S1 a, struct S1 b)
+{
+ a.val &= b.val;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]andb" } } */
+
+struct S1 test_or (struct S1 a, struct S1 b)
+{
+ a.val |= b.val;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]orb" } } */
+
+struct S1 test_xor (struct S1 a, struct S1 b)
+{
+ a.val ^= b.val;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]xorb" } } */
+
+struct S1 test_add (struct S1 a, struct S1 b)
+{
+ a.val += b.val;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]addb" } } */