swiftlang / swift

The Swift Programming Language
https://swift.org
Apache License 2.0
67.32k stars 10.34k forks source link

[SR-11640] Multiplying doubles from struct #54051

Open zoecarver opened 4 years ago

zoecarver commented 4 years ago
Previous ID SR-11640
Radar None
Original Reporter @zoecarver
Type Improvement
Additional Detail from JIRA | | | |------------------|-----------------| |Votes | 0 | |Component/s | Compiler | |Labels | Improvement, CodeGen, Optimizer, Performance | |Assignee | None | |Priority | Medium | md5: 833dd33d195d879e7d8fc3c9618b65e2

Issue Description:

struct X {
    let x : Double = 2
    let y : Double = 2
    let z : Double = 2
}

func test(numbers: [X]) -> Double {
    var x = 1.0
    for num in numbers {
        x *= num.x
        x *= num.y
        x *= num.z
    }
    return x
}

assert(test(numbers: [X(), X(), X(), X(), X()]) != 0)

The following generates 9 different `fmul` instructions. It should only generate 3. It also generates 31 `getelementptr` instructions when it certainly doesn't need that many, and theoretically could only generate 4.

An equivalent program in C++ takes about 1/4th of the time to run. Here is a comparison of the codegen from swift and clang.

If others agree this is an issue, I will start working on a patch to try to resolve it.

belkadan commented 4 years ago

I only see three fmul instructions in the optimized code. Are you looking at unoptimized code?

zoecarver commented 4 years ago

Yes, I am looking at the optimized code. Take a look at the assembly or the IR gen in the link above.

belkadan commented 4 years ago

Ah, I thought you meant LLVM IR. The nine instructions are from loop unrolling; if you use -Osize instead of -O you get the three you originally expected.

zoecarver commented 4 years ago

Ah, you're right! That's probably not the slow part. I tried removing the conditional fails which made it a little faster but, not much. Any other ideas?