aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/i386/i386-expand.c7
-rw-r--r--gcc/config/i386/i386.md12
-rw-r--r--gcc/testsuite/gcc.target/i386/pr99600.c16
3 files changed, 32 insertions, 3 deletions
diff --git a/gcc/config/i386/i386-expand.c b/gcc/config/i386/i386-expand.c
index 33b8822..ac69eed 100644
--- a/gcc/config/i386/i386-expand.c
+++ b/gcc/config/i386/i386-expand.c
@@ -1348,9 +1348,10 @@ ix86_split_lea_for_addr (rtx_insn *insn, rtx operands[], machine_mode mode)
if (regno0 != regno2)
emit_insn (gen_rtx_SET (target, parts.index));
- /* Use shift for scaling. */
- ix86_emit_binop (ASHIFT, mode, target,
- GEN_INT (exact_log2 (parts.scale)));
+ /* Use shift for scaling, but emit it as MULT instead
+ to avoid it being immediately peephole2 optimized back
+ into lea. */
+ ix86_emit_binop (MULT, mode, target, GEN_INT (parts.scale));
if (parts.base)
ix86_emit_binop (PLUS, mode, target, parts.base);
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 2820f6d..9ff35d9 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -5219,6 +5219,18 @@
DONE;
})
+
+;; ix86_split_lea_for_addr emits the shifts as MULT to avoid it from being
+;; peephole2 optimized back into a lea. Split that into the shift during
+;; the following split pass.
+(define_split
+ [(set (match_operand:SWI48 0 "general_reg_operand")
+ (mult:SWI48 (match_dup 0) (match_operand:SWI48 1 "const1248_operand")))
+ (clobber (reg:CC FLAGS_REG))]
+ "reload_completed"
+ [(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])));")
;; Add instructions
diff --git a/gcc/testsuite/gcc.target/i386/pr99600.c b/gcc/testsuite/gcc.target/i386/pr99600.c
new file mode 100644
index 0000000..c2f2b22
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr99600.c
@@ -0,0 +1,16 @@
+/* PR target/99600 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=atom" } */
+
+char a, b;
+long c;
+
+long
+foo (void)
+{
+ if (a)
+ c = b == 1 ? 1 << 3 : 1 << 2;
+ else
+ c = 0;
+ return 0;
+}