Use ix86_expand_clear in ix86_split_ashl.
authorRoger Sayle <roger@nextmovesoftware.com>
Wed, 28 Dec 2022 19:27:52 +0000 (19:27 +0000)
committerRoger Sayle <roger@nextmovesoftware.com>
Wed, 28 Dec 2022 19:27:52 +0000 (19:27 +0000)
This patch is a one line change, to call ix86_expand_clear instead of
emit_move_insn with const0_rtx in ix86_split_ashl, allowing the backend
to use an xor instruction to clear a register if appropriate.

The effect is demonstrated with the following function.
__int128 foo(__int128 x, unsigned long long b) {
    return ((__int128)b << 72) + x;
}

previously with -O2, GCC would generate

foo:    movl    $0, %eax
        salq    $8, %rdx
        addq    %rdi, %rax
        adcq    %rsi, %rdx
        ret

with this patch, it now generates

foo:    xorl    %eax, %eax
        salq    $8, %rdx
        addq    %rdi, %rax
        adcq    %rsi, %rdx
        ret

2022-12-28  Roger Sayle  <roger@nextmovesoftware.com>

gcc/ChangeLog
* config/i386/i386-expand.cc (ix86_split_ashl): Call
ix86_expand_clear to generate an xor instruction.

gcc/testsuite/ChangeLog
* gcc.target/i386/ashlti3-1.c: New test case.

gcc/config/i386/i386-expand.cc
gcc/testsuite/gcc.target/i386/ashlti3-1.c [new file with mode: 0644]

index b6cc76d..3eddbc9 100644 (file)
@@ -6211,7 +6211,7 @@ ix86_split_ashl (rtx *operands, rtx scratch, machine_mode mode)
       if (count >= half_width)
        {
          emit_move_insn (high[0], low[1]);
-         emit_move_insn (low[0], const0_rtx);
+         ix86_expand_clear (low[0]);
 
          if (count > half_width)
            ix86_expand_ashl_const (high[0], count - half_width, mode);
diff --git a/gcc/testsuite/gcc.target/i386/ashlti3-1.c b/gcc/testsuite/gcc.target/i386/ashlti3-1.c
new file mode 100644 (file)
index 0000000..1cf1306
--- /dev/null
@@ -0,0 +1,6 @@
+/* { dg-do compile { target int128 } } */
+/* { dg-options "-O2" } */
+__int128 foo(__int128 x, unsigned long long b) {
+    return ((__int128)b << 72) + x;
+}
+/* { dg-final { scan-assembler-not "\tmovl\[ \\t\]+\\\$0," } } */