Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lower assume(false) to an unreachable terminator #122610

Closed
wants to merge 1 commit into from

Conversation

saethlin
Copy link
Member

@saethlin saethlin commented Mar 16, 2024

This turns IR like:

  call void @llvm.assume(i1 false)
  call void @core::hint::unreachable_unchecked::precondition_check() #7
  br label %bb3

Into just:

  unreachable

I'm not sure why LLVM needs its hand held like this, but also this is a chance to emit less IR so even if the optimization is fixed in LLVM we still come out ahead.

The only part of this PR I'm not happy with is the complexity in the loop that iterates over the MIR blocks. The structure of it was a bit subtle before, and now it's just out of control. Please help?

@saethlin saethlin linked an issue Mar 16, 2024 that may be closed by this pull request
@rustbot
Copy link
Collaborator

rustbot commented Mar 16, 2024

r? @estebank

rustbot has assigned @estebank.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Mar 16, 2024
@saethlin
Copy link
Member Author

Unlucky roll, I think.

r? nnethercote

@rustbot rustbot assigned nnethercote and unassigned estebank Mar 16, 2024
@rust-log-analyzer

This comment has been minimized.

@saethlin saethlin marked this pull request as ready for review March 17, 2024 00:13
@matthiaskrgr

This comment was marked as duplicate.

@matthiaskrgr
Copy link
Member

@bors try @rust-timer queue

@rust-timer

This comment has been minimized.

@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Mar 17, 2024
bors added a commit to rust-lang-ci/rust that referenced this pull request Mar 17, 2024
Lower assume(false) to an unreachable terminator

This turns the IR pattern:
```
  call void `@llvm.assume(i1` false)
  call void `@core::hint::unreachable_unchecked::precondition_check()` rust-lang#7
  br label %bb3
```
Into just:
```
  unreachable
```
I'm not sure why LLVM needs its hand held like this, but also this is a chance to emit less IR so even if the optimization is fixed in LLVM we still come out ahead.

The only part of this PR I'm not happy with is the complexity in the loop that iterates over the MIR blocks. The structure of it was a bit subtle before, and now it's just out of control. Please help?
@bors
Copy link
Contributor

bors commented Mar 17, 2024

⌛ Trying commit 9cc67c5 with merge 04d1404...

@bors
Copy link
Contributor

bors commented Mar 17, 2024

☀️ Try build successful - checks-actions
Build commit: 04d1404 (04d1404e95852ca1daf95ab4997467c9115ed67c)

@rust-timer

This comment has been minimized.

@DianQK
Copy link
Member

DianQK commented Mar 17, 2024

I can't pass this test locally. I don't know why this is happening.
LLVM can successfully optimize it if I add a redundant statement: https://llvm.godbolt.org/z/3dWGnfM85.
Of course, this is a missing optimization: https://alive2.llvm.org/ce/z/pduoBd.

@DianQK
Copy link
Member

DianQK commented Mar 17, 2024

The only part of this PR I'm not happy with is the complexity in the loop that iterates over the MIR blocks. The structure of it was a bit subtle before, and now it's just out of control. Please help?

Perhaps it's time to add a post-mono optimization phase? We can know all the facts at the phase.

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (04d1404): comparison URL.

Overall result: ❌✅ regressions and improvements - no action needed

Benchmarking this pull request likely means that it is perf-sensitive, so we're automatically marking it as not fit for rolling up. While you can manually mark this PR as fit for rollup, we strongly recommend not doing so since this PR may lead to changes in compiler perf.

@bors rollup=never
@rustbot label: -S-waiting-on-perf -perf-regression

Instruction count

This is a highly reliable metric that was used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
3.2% [3.2%, 3.2%] 1
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-6.1% [-6.1%, -6.1%] 1
All ❌✅ (primary) - - 0

Max RSS (memory usage)

Results

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
2.4% [2.4%, 2.4%] 1
Regressions ❌
(secondary)
3.8% [1.0%, 6.1%] 3
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-4.6% [-4.6%, -4.6%] 1
All ❌✅ (primary) 2.4% [2.4%, 2.4%] 1

Cycles

Results

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
1.2% [1.0%, 1.4%] 5
Regressions ❌
(secondary)
1.2% [1.2%, 1.2%] 1
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-7.9% [-8.8%, -6.8%] 6
All ❌✅ (primary) 1.2% [1.0%, 1.4%] 5

Binary size

This benchmark run did not return any relevant results for this metric.

Bootstrap: 670.532s -> 669.93s (-0.09%)
Artifact size: 312.75 MiB -> 312.74 MiB (-0.00%)

@rustbot rustbot removed the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Mar 17, 2024
@saethlin
Copy link
Member Author

I can't pass this test locally.

I don't know what this sentence means. What are you seeing locally?

break;
} else {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't need the else after break.

&mut self,
bx: &mut Bx,
statement: &mir::Statement<'tcx>,
) -> ControlFlow<()> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A brief comment about the meaning of the return value would be helpful.

@@ -0,0 +1,23 @@
//@ compile-flags: -O
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A brief comment about the point of this test would be helpful.

@nnethercote
Copy link
Contributor

Looks ok to me, though I'm not an expert on this code even though I have modified it before :)

Just a couple of nits, r=me after fixing them. Might be worth waiting for more information from @DianQK about the local test failure.

@rust-log-analyzer

This comment has been minimized.

@DianQK
Copy link
Member

DianQK commented Mar 18, 2024

I can't pass this test locally.

I don't know what this sentence means. What are you seeing locally?

Details

--- stderr -------------------------------
/home/dianqk/rust/rust/tests/codegen/discriminant-swap.rs:22:16: error: CHECK-NEXT: is not on the line after the previous match
// CHECK-NEXT: store i8 1, ptr %s, align 1
               ^
/home/dianqk/rust/rust/build/x86_64-unknown-linux-gnu/test/codegen/discriminant-swap/discriminant-swap.ll:18:2: note: 'next' match was here
 store i8 1, ptr %s, align 1
 ^
/home/dianqk/rust/rust/build/x86_64-unknown-linux-gnu/test/codegen/discriminant-swap/discriminant-swap.ll:10:6: note: previous match ended here
start:
     ^
/home/dianqk/rust/rust/build/x86_64-unknown-linux-gnu/test/codegen/discriminant-swap/discriminant-swap.ll:11:1: note: non-matching line after previous match is here
 %src.sroa.2 = alloca [753 x i8], align 1
^

Input file: /home/dianqk/rust/rust/build/x86_64-unknown-linux-gnu/test/codegen/discriminant-swap/discriminant-swap.ll
Check file: /home/dianqk/rust/rust/tests/codegen/discriminant-swap.rs

-dump-input=help explains the following input dump.

Input was:
<<<<<<
         1: ; ModuleID = 'discriminant_swap.d00c7f70130bcab2-cgu.0'
         2: source_filename = "discriminant_swap.d00c7f70130bcab2-cgu.0"
         3: target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
         4: target triple = "x86_64-unknown-linux-gnu"
         5:
         6: %State = type { i8, [753 x i8] }
         7:
         8: ; Function Attrs: mustprogress nofree norecurse nosync nounwind nonlazybind willreturn memory(argmem: readwrite) uwtable
         9: define void @init(ptr nocapture noundef %s) unnamed_addr #0 {
        10: start:
        11:  %src.sroa.2 = alloca [753 x i8], align 1
        12:  %_3 = alloca %State, align 1
        13:  call void @llvm.lifetime.start.p0(i64 754, ptr nonnull %_3)
        14:  call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(754) %_3, ptr noundef nonnull align 1 dereferenceable(754) %s, i64 754, i1 false)
        15:  %0 = getelementptr inbounds i8, ptr %_3, i64 1
        16:  call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(753) %src.sroa.2, ptr noundef nonnull align 1 dereferenceable(753) %0, i64 753, i1 false)
        17:  call void @llvm.lifetime.end.p0(i64 754, ptr nonnull %_3)
        18:  store i8 1, ptr %s, align 1
next:22      !~~~~~~~~~~~~~~~~~~~~~~~~~~  error: match on wrong line
        19:  %src.sroa.2.0.s.sroa_idx = getelementptr inbounds i8, ptr %s, i64 1
        20:  call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(753) %src.sroa.2.0.s.sroa_idx, ptr noundef nonnull align 1 dereferenceable(753) %src.sroa.2, i64 753, i1 false)
        21:  ret void
        22: }
        23:
        24: ; Function Attrs: mustprogress nocallback nofree nounwind willreturn memory(argmem: readwrite)
        25: declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg) #1
        26:
        27: ; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
        28: declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #2
        29:
        30: ; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
        31: declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #2
        32:
        33: attributes #0 = { mustprogress nofree norecurse nosync nounwind nonlazybind willreturn memory(argmem: readwrite) uwtable "probe-stack"="inline-asm" "target-cpu"="x86-64" }
        34: attributes #1 = { mustprogress nocallback nofree nounwind willreturn memory(argmem: readwrite) }
        35: attributes #2 = { mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
        36:
        37: !llvm.module.flags = !{!0, !1}
        38: !llvm.ident = !{!2}
        39:
        40: !0 = !{i32 8, !"PIC Level", i32 2}
        41: !1 = !{i32 2, !"RtLibUseGOT", i32 1}
        42: !2 = !{!"rustc version 1.78.0-dev"}
>>>>>>
------------------------------------------



failures:
    [codegen] tests/codegen/discriminant-swap.rs

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 608 filtered out; finished in 20.14ms

Some tests failed in compiletest suite=codegen mode=codegen host=x86_64-unknown-linux-gnu target=x86_64-unknown-linux-gnu
Build completed unsuccessfully in 0:00:31

config.toml

      profile = "compiler"
      change-id = 121278

      [build]
      patch-binaries-for-nix = true
      gdb = "gdb"
      python = "python"
      submodules = false
      build = "x86_64-unknown-linux-gnu"

      [llvm]
      ccache = "sccache"

      [rust]
      incremental = false
      debug-logging = true
      deny-warnings = false
      llvm-tools = true

Maybe it's just my local environment (NixOS?), I've had similar problems before. I don't think this should affect this PR.

Copy link
Member

@DianQK DianQK left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can ignore it if the CI is good. 🤯

@saethlin
Copy link
Member Author

Ah, the problem is that -Cdebuginfo=2 which is the default for the compiler profile, disables some optimizations. In this case, ptr::read has been denied some useful MIR optimizations.

If you add

[rust]
debuginfo-level = 1

the test should pass. Setting -Cdebuginfo=1 in the test doesn't help, because the optimization problem is in the precompiled standard library.

@DianQK
Copy link
Member

DianQK commented Mar 18, 2024

Ah, the problem is that -Cdebuginfo=2 which is the default for the compiler profile, disables some optimizations. In this case, ptr::read has been denied some useful MIR optimizations.

If you add

[rust]
debuginfo-level = 1

the test should pass. Setting -Cdebuginfo=1 in the test doesn't help, because the optimization problem is in the precompiled standard library.

It's not working, even If I set to debuginfo-level=0. I downloaded 04d1404 still getting the same result.

`rustc +04d1404e95852ca1daf95ab4997467c9115ed67c discriminant-swap.rs -O --emit=llvm-ir -C no-prepopulate-passes`

; ModuleID = 'discriminant_swap.9e637175484fe1de-cgu.0'
source_filename = "discriminant_swap.9e637175484fe1de-cgu.0"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

%State = type { i8, [753 x i8] }

@alloc_1eb6f53a157dccb32488e066ad957e6d = private unnamed_addr constant <{ [82 x i8] }> <{ [82 x i8] c"unsafe precondition(s) violated: hint::unreachable_unchecked must never be reached" }>, align 1

; core::hint::unreachable_unchecked::precondition_check
; Function Attrs: inlinehint nounwind nonlazybind uwtable
define internal void @_ZN4core4hint21unreachable_unchecked18precondition_check17h10b11a7859d8bb49E() unnamed_addr #0 {
start:
; call core::panicking::panic_nounwind
  call void @_ZN4core9panicking14panic_nounwind17hc33628e8262d0458E(ptr noalias noundef nonnull readonly align 1 @alloc_1eb6f53a157dccb32488e066ad957e6d, i64 noundef 82) #5
  unreachable
}

; Function Attrs: nonlazybind uwtable
define void @init(ptr noundef %s) unnamed_addr #1 {
start:
  %src = alloca %State, align 1
  %_3 = alloca %State, align 1
  %v = alloca [753 x i8], align 1
  call void @llvm.lifetime.start.p0(i64 754, ptr %_3)
  call void @llvm.memcpy.p0.p0.i64(ptr align 1 %_3, ptr align 1 %s, i64 754, i1 false)
  %0 = load i8, ptr %_3, align 1, !range !3, !noundef !4
  %1 = trunc i8 %0 to i1
  %_5 = zext i1 %1 to i64
  switch i64 %_5, label %bb3 [
    i64 0, label %bb1
    i64 1, label %bb2
  ]

bb3:                                              ; preds = %start
  unreachable

bb1:                                              ; preds = %start
  %2 = getelementptr inbounds i8, ptr %_3, i64 1
  call void @llvm.memcpy.p0.p0.i64(ptr align 1 %v, ptr align 1 %2, i64 753, i1 false)
  call void @llvm.lifetime.end.p0(i64 754, ptr %_3)
  %3 = getelementptr inbounds i8, ptr %src, i64 1
  call void @llvm.memcpy.p0.p0.i64(ptr align 1 %3, ptr align 1 %v, i64 753, i1 false)
  store i8 1, ptr %src, align 1
  call void @llvm.memcpy.p0.p0.i64(ptr align 1 %s, ptr align 1 %src, i64 754, i1 false)
  ret void

bb2:                                              ; preds = %start
  call void @llvm.lifetime.end.p0(i64 754, ptr %_3)
  unreachable
}

; core::panicking::panic_nounwind
; Function Attrs: cold noinline noreturn nounwind nonlazybind uwtable
declare void @_ZN4core9panicking14panic_nounwind17hc33628e8262d0458E(ptr noalias noundef nonnull readonly align 1, i64 noundef) unnamed_addr #2

; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite)
declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg) #3

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #4

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #4

attributes #0 = { inlinehint nounwind nonlazybind uwtable "probe-stack"="inline-asm" "target-cpu"="x86-64" }
attributes #1 = { nonlazybind uwtable "probe-stack"="inline-asm" "target-cpu"="x86-64" }
attributes #2 = { cold noinline noreturn nounwind nonlazybind uwtable "probe-stack"="inline-asm" "target-cpu"="x86-64" }
attributes #3 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
attributes #4 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
attributes #5 = { noreturn nounwind }

!llvm.module.flags = !{!0, !1}
!llvm.ident = !{!2}

!0 = !{i32 8, !"PIC Level", i32 2}
!1 = !{i32 2, !"RtLibUseGOT", i32 1}
!2 = !{!"rustc version 1.79.0-nightly (04d1404e9 2024-03-17)"}
!3 = !{i8 0, i8 2}
!4 = !{}

`rustc +04d1404e95852ca1daf95ab4997467c9115ed67c discriminant-swap.rs -O --emit=llvm-ir`

; ModuleID = 'discriminant_swap.9e637175484fe1de-cgu.0'
source_filename = "discriminant_swap.9e637175484fe1de-cgu.0"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

%State = type { i8, [753 x i8] }

; Function Attrs: mustprogress nofree norecurse nosync nounwind nonlazybind willreturn memory(argmem: readwrite) uwtable
define void @init(ptr nocapture noundef %s) unnamed_addr #0 {
start:
  %src.sroa.2 = alloca [753 x i8], align 1
  %_3 = alloca %State, align 1
  call void @llvm.lifetime.start.p0(i64 754, ptr nonnull %_3)
  call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(754) %_3, ptr noundef nonnull align 1 dereferenceable(754) %s, i64 754, i1 false)
  %0 = getelementptr inbounds i8, ptr %_3, i64 1
  call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(753) %src.sroa.2, ptr noundef nonnull align 1 dereferenceable(753) %0, i64 753, i1 false)
  call void @llvm.lifetime.end.p0(i64 754, ptr nonnull %_3)
  store i8 1, ptr %s, align 1
  %src.sroa.2.0.s.sroa_idx = getelementptr inbounds i8, ptr %s, i64 1
  call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(753) %src.sroa.2.0.s.sroa_idx, ptr noundef nonnull align 1 dereferenceable(753) %src.sroa.2, i64 753, i1 false)
  ret void
}

; Function Attrs: mustprogress nocallback nofree nounwind willreturn memory(argmem: readwrite)
declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg) #1

; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #2

; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #2

attributes #0 = { mustprogress nofree norecurse nosync nounwind nonlazybind willreturn memory(argmem: readwrite) uwtable "probe-stack"="inline-asm" "target-cpu"="x86-64" }
attributes #1 = { mustprogress nocallback nofree nounwind willreturn memory(argmem: readwrite) }
attributes #2 = { mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }

!llvm.module.flags = !{!0, !1}
!llvm.ident = !{!2}

!0 = !{i32 8, !"PIC Level", i32 2}
!1 = !{i32 2, !"RtLibUseGOT", i32 1}
!2 = !{!"rustc version 1.79.0-nightly (04d1404e9 2024-03-17)"}

self.codegen_statement(bx, statement);
if let ControlFlow::Break(()) = self.codegen_statement(bx, statement) {
replaced_terminator = true;
break;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, can you use a loop label and use it to break out of the outer loop? Avoiding the need for replaced_terminator entirely.

@DianQK
Copy link
Member

DianQK commented Mar 18, 2024

@saethlin
Copy link
Member Author

That's possible but I swear I got the test to pass locally. Now it seems to be failing, which is very strange.

In any case, this should definitely be a better test that doesn't rely on so much other code.

@DianQK
Copy link
Member

DianQK commented Mar 18, 2024

LLVM can successfully optimize it if I add a redundant statement: https://llvm.godbolt.org/z/3dWGnfM85. Of course, this is a missing optimization: https://alive2.llvm.org/ce/z/pduoBd.

I think this is a fragile optimization per this result.

@DianQK
Copy link
Member

DianQK commented Mar 22, 2024

Could you remove the switch instruction that has only one branch? memcpy will be eliminated when you remove the switch instruction: https://llvm.godbolt.org/z/r8Er7fKcn.
However, I prefer to perform such transformations in rustc_mir_transform.

The key point here is that the load instruction triggered the SROA transformation, which led to the final transformation. However, SimplifyCFG removed this load instruction: https://llvm.godbolt.org/z/6PoWz3bd8 or https://llvm.godbolt.org/z/f993Ph6rY. I'm still unsure where to add this optimization, as I'm not yet familiar with MemCpyOpt.

@saethlin
Copy link
Member Author

saethlin commented Mar 22, 2024

Eliminating the switch would eliminate the information that it is providing about the value of the switched-on value. If we eliminate the switch, we don't know that %_5 is 0 anymore. That's harmless here, but I'm sure it removes useful information if we do this optimization in every function.

@DianQK
Copy link
Member

DianQK commented Mar 22, 2024

We can add assume on the switch-on value while eliminating the switch.

@saethlin
Copy link
Member Author

Ah, I see! I think if you simplify NullOp::UbChecks and put it before UnreachablePropagation, that pass might already do the transform you need here.

@saethlin saethlin added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Mar 23, 2024
@DianQK
Copy link
Member

DianQK commented Mar 24, 2024

Ah, I see! I think if you simplify NullOp::UbChecks and put it before UnreachablePropagation, that pass might already do the transform you need here.

Yes. We need to fine-tune the pipeline.

@saethlin
Copy link
Member Author

As far as I can tell, there is no optimization value to this change; what I saw before was just poking around an unstable part of the LLVM pipeline and getting lucky.

I'm wary of adding more cleverness to codegen that is not justified, so since there's no demonstrated upside at all to this change I'm closing this.

@saethlin saethlin closed this Apr 16, 2024
@saethlin saethlin deleted the assume-const branch April 16, 2024 00:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Discriminant update fails to optimize
10 participants