Skip to content

Suboptimal instruction sequence when operands are reordered #57255

Open
@hiraditya

Description

@hiraditya
int foo(int t) {
    return t - (1 - 5 * t);
}

int bar(int t) {
    return t - 1 + 5 * t;
}

int baz(int t) {
    return t + 5 * t - 1;
}

$ riscv64-clang -O3

        .text
        .attribute      4, 16
        .attribute      5, "rv64i2p0_m2p0_a2p0_f2p0_d2p0_c2p0"
        .file   "example.c"
        .globl  foo                             # -- Begin function foo
        .p2align        1
        .type   foo,@function
foo:                                    # @foo
# %bb.0:
        slliw   a1, a0, 2
        addw    a1, a1, a0
        addw    a0, a0, a1
        addiw   a0, a0, -1
        ret
.Lfunc_end0:
        .size   foo, .Lfunc_end0-foo
                                        # -- End function
        .globl  bar                             # -- Begin function bar
        .p2align        1
        .type   bar,@function
bar:                                    # @bar
# %bb.0:
        slliw   a1, a0, 2
        addw    a1, a1, a0
        addw    a0, a0, a1
        addiw   a0, a0, -1
        ret
.Lfunc_end1:
        .size   bar, .Lfunc_end1-bar
                                        # -- End function
        .globl  baz                             # -- Begin function baz
        .p2align        1
        .type   baz,@function
baz:                                    # @baz
# %bb.0:
        li      a1, 6
        mulw    a0, a0, a1
        addiw   a0, a0, -1
        ret
.Lfunc_end2:
        .size   baz, .Lfunc_end2-baz
                                        # -- End function
        .ident  "clang version 16.0.0 (https://github.com/llvm/llvm-project.git 06c02d5dbb13f6d2a10eaa75c236f3c61cdf5b91)"
        .section        ".note.GNU-stack","",@progbits
        .addrsig

In the last case mulw is generated.

Aarch64 also has this issue

$ arm64-clang -O3

        .text
        .file   "example.c"
        .globl  foo                             // -- Begin function foo
        .p2align        2
        .type   foo,@function
foo:                                    // @foo
        .cfi_startproc
// %bb.0:
        add     w8, w0, w0, lsl #2
        add     w8, w8, w0
        sub     w0, w8, #1
        ret
.Lfunc_end0:
        .size   foo, .Lfunc_end0-foo
        .cfi_endproc
                                        // -- End function
        .globl  bar                             // -- Begin function bar
        .p2align        2
        .type   bar,@function
bar:                                    // @bar
        .cfi_startproc
// %bb.0:
        add     w8, w0, w0, lsl #2
        add     w8, w0, w8
        sub     w0, w8, #1
        ret
.Lfunc_end1:
        .size   bar, .Lfunc_end1-bar
        .cfi_endproc
                                        // -- End function
        .globl  baz                             // -- Begin function baz
        .p2align        2
        .type   baz,@function
baz:                                    // @baz
        .cfi_startproc
// %bb.0:
        mov     w8, #6
        mul     w8, w0, w8
        sub     w0, w8, #1
        ret
.Lfunc_end2:
        .size   baz, .Lfunc_end2-baz
        .cfi_endproc
                                        // -- End function
        .ident  "clang version 16.0.0 (https://github.com/llvm/llvm-project.git 06c02d5dbb13f6d2a10eaa75c236f3c61cdf5b91)"
        .section        ".note.GNU-stack","",@progbits
        .addrsig

In the last case mul is generated.

However, X86 generates the same instruction sequence for all three

        .text
        .intel_syntax noprefix
        .file   "example.c"
        .globl  foo                             # -- Begin function foo
        .p2align        4, 0x90
        .type   foo,@function
foo:                                    # @foo
        .cfi_startproc
# %bb.0:
                                        # kill: def $edi killed $edi def $rdi
        lea     eax, [rdi + 4*rdi]
        add     eax, edi
        dec     eax
        ret
.Lfunc_end0:
        .size   foo, .Lfunc_end0-foo
        .cfi_endproc
                                        # -- End function
        .globl  bar                             # -- Begin function bar
        .p2align        4, 0x90
        .type   bar,@function
bar:                                    # @bar
        .cfi_startproc
# %bb.0:
                                        # kill: def $edi killed $edi def $rdi
        lea     eax, [rdi + 4*rdi]
        add     eax, edi
        dec     eax
        ret
.Lfunc_end1:
        .size   bar, .Lfunc_end1-bar
        .cfi_endproc
                                        # -- End function
        .globl  baz                             # -- Begin function baz
        .p2align        4, 0x90
        .type   baz,@function
baz:                                    # @baz
        .cfi_startproc
# %bb.0:
                                        # kill: def $edi killed $edi def $rdi
        lea     eax, [rdi + 2*rdi]
        add     eax, eax
        dec     eax
        ret
.Lfunc_end2:
        .size   baz, .Lfunc_end2-baz
        .cfi_endproc
                                        # -- End function
        .ident  "clang version 16.0.0 (https://github.com/llvm/llvm-project.git 06c02d5dbb13f6d2a10eaa75c236f3c61cdf5b91)"
        .section        ".note.GNU-stack","",@progbits
        .addrsig

Metadata

Metadata

Assignees

Labels

good first issuehttps://github.com/llvm/llvm-project/contributellvm:instcombineCovers the InstCombine, InstSimplify and AggressiveInstCombine passes

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions