<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/79477>79477</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            Misoptimized Unrolling
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          Rexicon226
      </td>
    </tr>
</table>

<pre>
    I don't know exactly what to title this issue to be honest, but I *think* it's something to do with unrolling. However I am in no way a LLVM expert. Please correct me with the title.

Here was the original test case presented:
```zig
const std = @import("std");

const State = union(enum) { idle, busy };

pub fn main() !void {
    var array = [_]State{ .idle, .idle };

    for (0..2) |_| {
        foo(&array);
        bar(&array);
 }
}

fn foo(data: []State) void {
    for (data) |*s| {
 if (s.* == .idle) {
            std.debug.print("1", .{});
 s.* = .busy;
        }
    }
}

fn bar(data: []State) void {
    for (data) |*s| {
        if (s.* == .busy) {
 std.debug.print("2", .{});
            s.* = .idle;
        }
 }
}
```
it would behave differently in different optimization modes. 
I have reduced it down to this IR repro:
```ir
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

@var_1 = global [2 x i8] c"1\00"
@var_2 = global [2 x i8] c"2\00"

define void @_start() {
Entry:
  unreachable
}

define void @start.posixCallMainAndExit() {
Entry:
  tail call fastcc void @test.main()
  %0 = tail call i64 asm sideeffect "syscall", "={rax},{rax},{rdi},~{rcx},~{r11},~{memory},~{dirflag},~{fpsr},~{flags}"(i64 231, i64 0)
  unreachable
}

define fastcc void @test.main() {
Then3.i:
  %0 = alloca [4 x i8], i32 0, align 4
  %1 = alloca [4 x i8], i32 0, align 4
  %.sroa.5 = alloca i8, i32 0, align 1
  store i32 2, ptr %1, align 4
  %2 = call fastcc i16 @"print"(ptr %1, ptr @var_1)
  %3 = call fastcc i16 @"print"(ptr %1, ptr @var_1)
  store i8 -1, ptr %.sroa.5, align 1
  store i32 2, ptr %0, align 4
  %4 = call fastcc i16 @"print"(ptr %0, ptr @var_2)
 %.sroa.5.0..sroa.5.0..sroa.5.0..sroa.5.0..sroa.5.1.20.pre = load i1, ptr %.sroa.5, align 1
  br i1 %.sroa.5.0..sroa.5.0..sroa.5.0..sroa.5.0..sroa.5.1.20.pre, label %Then3.1.i3, label %Then3.i.1

Then3.1.i3:                                       ; preds = %Then3.i
  %5 = call fastcc i16 @"print"(ptr %0, ptr @var_2)
 store i8 0, ptr %.sroa.5, align 1
  br label %Then3.i.1

Then3.i.1: ; preds = %Then3.1.i3, %Then3.i
 %6 = call fastcc i16 @"print"(ptr %1, ptr @var_1)
 %.sroa.5.0..sroa.5.0..sroa.5.0..sroa.5.0..sroa.5.1..1.pre = load i1, ptr %.sroa.5, align 1
  br i1 %.sroa.5.0..sroa.5.0..sroa.5.0..sroa.5.0..sroa.5.1..1.pre, label %Then3.i11.1, label %Then3.1.i.1

Then3.1.i.1: ; preds = %Then3.i.1
  %7 = call fastcc i16 @"print"(ptr %1, ptr @var_1)
  store i8 1, ptr %.sroa.5, align 1
  br label %Then3.i11.1

Then3.i11.1:                                      ; preds = %Then3.1.i.1, %Then3.i.1
  %8 = call fastcc i16 @"print"(ptr %0, ptr @var_2)
  %.sroa.5.0..sroa.5.0..sroa.5.0..sroa.5.0..sroa.5.1.20.1.pre = load i1, ptr %.sroa.5, align 1
  br i1 %.sroa.5.0..sroa.5.0..sroa.5.0..sroa.5.0..sroa.5.1.20.1.pre, label %Then3.1.i3.1, label %test.bar.exit.1
Then3.1.i3.1: ; preds = %Then3.i11.1
  %9 = call fastcc i16 @"print"(ptr %0, ptr @var_2)
  ret void

test.bar.exit.1: ; preds = %Then3.i11.1
  ret void
}

define fastcc i16 @"print"(ptr %0, ptr %1) {
Entry:
  %.sroa.04.0.copyload = load i32, ptr %0, align 4
  %2 = sext i32 %.sroa.04.0.copyload to i64
  %3 = ptrtoint ptr %1 to i64
  %4 = tail call i64 asm sideeffect "syscall", "={rax},{rax},{rdi},{rsi},{rdx},~{rcx},~{r11},~{memory},~{dirflag},~{fpsr},~{flags}"(i64 1, i64 %2, i64 %3, i64 1)
  ret i16 0
}

; uselistorder directives
uselistorder ptr @"print", { 7, 6, 5, 4, 3, 2, 1, 0 }
```


## How to repro

simply compile the above IR with `llc` in either `-O0` mode (correct behaviour) or any other optimization mode (incorrect behaviour)
this is the expected behaviour from the code:
```
# llc reduced.ll -O0
# zig run reduced.s
11221122
```

unexpected:
```
# llc reduced.ll -O1
# zig run reduced.s
11212
```

---
Here's another incorrect optimization I found that may be somehow related:

```
# opt -S -O1 reduced.ll > optimized.ll
```

This will produce a simply wrong optimization of:
```
  %0 = alloca [0 x [4 x i8]], align 4
 store i32 2, ptr %0, align 4
  %1 = tail call i64 asm sideeffect "syscall", "={rax},{rax},{rdi},{rsi},{rdx},~{rcx},~{r11},~{memory},~{dirflag},~{fpsr},~{flags}"(i64 1, i64 2, i64 ptrtoint (ptr @var_1 to i64), i64 1) #2
  %2 = tail call i64 asm sideeffect "syscall", "={rax},{rax},{rdi},{rsi},{rdx},~{rcx},~{r11},~{memory},~{dirflag},~{fpsr},~{flags}"(i64 1, i64 2, i64 ptrtoint (ptr @var_1 to i64), i64 1) #2
  store i8 -1, ptr %0, align 4
  store i32 2, ptr %0, align 4
  %3 = tail call i64 asm sideeffect "syscall", "={rax},{rax},{rdi},{rsi},{rdx},~{rcx},~{r11},~{memory},~{dirflag},~{fpsr},~{flags}"(i64 1, i64 2, i64 ptrtoint (ptr @var_2 to i64), i64 1) #2
  %4 = tail call i64 asm sideeffect "syscall", "={rax},{rax},{rdi},{rsi},{rdx},~{rcx},~{r11},~{memory},~{dirflag},~{fpsr},~{flags}"(i64 1, i64 2, i64 ptrtoint (ptr @var_1 to i64), i64 1) #2
  %5 = tail call i64 asm sideeffect "syscall", "={rax},{rax},{rdi},{rsi},{rdx},~{rcx},~{r11},~{memory},~{dirflag},~{fpsr},~{flags}"(i64 1, i64 2, i64 ptrtoint (ptr @var_1 to i64), i64 1) #2
  store i8 1, ptr %0, align 4
  %.sroa.04.0.copyload.i7 = load i32, ptr %0, align 4
  %6 = sext i32 %.sroa.04.0.copyload.i7 to i64
  %7 = tail call i64 asm sideeffect "syscall", "={rax},{rax},{rdi},{rsi},{rdx},~{rcx},~{r11},~{memory},~{dirflag},~{fpsr},~{flags}"(i64 1, i64 %6, i64 ptrtoint (ptr @var_2 to i64), i64 1) #2
  %8 = sext i32 %.sroa.04.0.copyload.i7 to i64
  %9 = tail call i64 asm sideeffect "syscall", "={rax},{rax},{rdi},{rsi},{rdx},~{rcx},~{r11},~{memory},~{dirflag},~{fpsr},~{flags}"(i64 1, i64 %8, i64 ptrtoint (ptr @var_2 to i64), i64 1) #2
  ret void
```
you can see `var_1`, `var_1`, `var_2` `var_1`. As mentioned previously the correct behaviour for the program is `1122-`

## Extra Information

This still occurs on any platform I can test it on currently. It also happens when running with a zig 0.10 binary, which used LLVM 15, so it was happening as far back as that.

Here's my commit hash for a more solid issue: 6009708b4367171ccdbf4b5905cb6a803753fe18

</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzsWkuP2zgS_jXsS8ECRdmSfOhDPxJMAzPYxWR2rwElURY3FCmQVNvOYX_7oijZll89TrY3h-w0EjVf9fpYLFWxxZ2TKy3EPVk8ksXzHe99Y-z972IjS6MZS-8KU23vX6AymrDMwxdt1iA2vPRqC-uGe_AGvPRKgG-kA-lcL3CsENAYLZwn7AmK3sMLEPbgG6m_EPYA0hOWOXCmFTi2QpLKwFr6BnptjVJSryL4xazFq7DwArwFqUEbWPMtcPj113_-BmLTCesj-LsS3AkojbWi9NCKgY9vxKBaROgzoQ_D8xdhBay5C9PGypXUXIEXzkOJXDornNBeVCQZKUhKh39f5WoYKY12HpyvgCTPQOZUtp2xnrCcMOZ8RRgjbEmSx6nggeiT514Esl5LBDUXum8JWwLJHkFWSgyAuS2Q7PmERdcXUGtoudRB1hIIi1-NrJB4WAIA8MotcGv5dlBv8fiZLJ6DYJQR7YSExgUpyKI2FgjLaRSxQbenzyR7OhYzrDNBkzTImxq9W1Fwe20Fih7k7hvhWeuRb8U9J8kDDN45WMCWcG7xqG5YP6hL2IM71ljWuMRF6H4keUZoRiiW53bhj_NVVImiX0WdlXrc3Tjs7RNESJI9H9mz5w0RbuAZFHszjzrnxg-Qvavx488lDIKqRxhcNJy9YfgUtAMGAdzrGFwAYHfQhq70sDa9qqAQDX8VUMm6FlZoDD1SH7pgOi9b-ZV7aTS0phIugoHFCwRKK6q-FBVID5VZ6xCzMFq9_A5WdNacH3VphwHP7Up4QGwV35reD0eKMTFrSfIgZh3LKEkeEhYe2I2Pu9hK5-Exk7tGnSNRzPKZzrGR7mjS-exTHPA-ku-t7JTYyd7k6ed0Pus1RmM9U1L3m9lK93uq8Tmnr9x-jgPZSpmCK3QmBhuQOVk8Qxn8efFE6YFyoGFv0rATmvCsRC21GN1zTj87z8eIOHGtD9rb7R5twFAveNnwQomLh-GEaeAZdcbJzRNX6jcu9YOuPmzknwryXCoouVJQc-fLcs8SA390CKi79YQtaMDgQCjTOXDXgpOVEHWNbxqM9luHs-PhwF_JM8keLd-EQ_J02q7k0P43dsrNpBPHh04rWmO3h34lba346jBQd85OeoqvXOgywnJUlCUx6oNNOjHrRrzfxuiA8h-N0EkkJzjvceNKmZKj78x3vhMUShgq9ARcyZWG-YQu_k66yFnDo8WUWuYXaOIdjfPGijAb9qzzNoi_zH04CVPPkXGKoBDGxuiImE-ZhPZ49o5dKnk3ZqMNOcziiQ0jFDfbfAXR-TepSU_UZAc1DypFNLqtFUeMRp0dYp0yvAJ5m4WFBRn_NxKRp-KFUMhk8Ow4ksmFYRnF00MzWZscvQvf-CHJI2aalRtj-o7zZBcW77ULe1-htwJ5i704iNnJZUN2yJ1ZRtgifa9T8F2bHcU_2r0GiZf8KI6j-LLbXfGwNzHfEwX3yd4_1tyM1EU7zz0oDN96ZK472oDhFRjy9zpF3x1afri_7WReCWgnLhde7gW3kdhIv4PuaPUbHnfY2IDP8t3AtsKH9GPqNaea3qjXCau3Ep7btA2n5Y1cc79pdB7RqDTdNmz8wQOSG97BQ97hxMaHt_YVnt5gineWYXTeeiO13-t7vnD-P81use0m7WrzQ7Lefc6LAE7aya4dn7gYbji96BjoWb0TSmL0q4SFSlpRevkq3LDgaHL04iPHCeU3ZNhI8RFO-RwfQZ2wIihM4VoFfPRkCWEJ_GLWuJlD2TqZdrLt1BZK03YyXMYJ4IV5FVjjhtswklKlSpJSrJ2F9I2wODb7G4oLVTMQlu_u0ELJLU1v0dONBa63YALNWbGNZFJfIhyP7XAvGFQSm06UXlSHZVBb04a50lTivBDfGw9KlbtCPlIKUPH93Fe5Atvr_fy4R3HMGP5_A9xe73T6JtnxLbLjtwTPZrPDhWS4DOV6QPgA5hHWL1CbXlfgG-6h5VsoRLg_bcwarFD8yIRrhpjOw-wTGjC1hyQfdrLCwBtq_4G7uZZKQWcNMgAOo--trdGrY51NfQ3Vi6Uihc1x5TcUf8fR8ZtKmfinDnP7GLcP-Lv31e7qZ4z7bDmNgEBYws7eNX-BdB2ky-X2JZ_7Ju9M_q-BZ7d558-dqbzTEV78BdKtR_jPTvDlVDuS2Tdm8OktGTyyPcvNs596MxGa94kM-XcjvPzZEc7fAeGTwvk4f9uaHkquwQmBZcRwZ5SGo3C5y7DMmExF8OCgFRrzRFFhFY_1gFPbsRg4KSfCXzlxprNmZXmLFQVJKWb3s9N6aaiUPmy85fCia2PbkI2epbHOYx5ryrK3DowORU6nuEcKeAnmhe8CpMfZsrfDHx8jePHAlTPQ8K4T2sG6ERprAC31aqi2eCgLaBRTKKTmdotIrBtZNlhVVsP3C3EoCZ1BAWvuRnbIgzuouYWCl18gfKrA_dlHDKFmaEPJ10oPDXdNAIlDi5HOGSWr4XsMkjxASukyo3kxT9IszuKyrIp6XiyWdFEWKc9pki2SWsT5wP-uuk-qZbLkd-I-zmjK6IJm-V1zn1TpohRJJqq8pElME7osKKdlnS7LOMnTO3nPKJvTmC3ibBHHeVQX1TLPF3OWZXyepAWZU9FyqSKlXtvI2NVd0PE-W86z7C5cS7nwOQpjWqxHAxgji-c7e480s6JfOTKnWH27A5fwpcf9b9LtCxn4x-5DkrveqvvG-85hOcI-EvZxJX3TF1FpWsI-IpPx16yz5l-i9IR9DKIdYR-Dav8JAAD__55Cr3A">