| ; RUN: opt < %s -disable-output -passes='no-op-module,loop-rotate,simplifycfg,print<assumptions>,hotcoldsplit' 2>&1 | FileCheck %s | |
| ; Check that we don't crash on deletion from a stale assumption cache. | |
| ; | |
| ; The initial module pass initialises the assumption cache, while the SSA | |
| ; updater in `loop-rotate` invalidates it with a call to `Use::set()`. After | |
| ; simplifying the CFG, we're left with a `hotcoldsplit` candidate, leading to a | |
| ; call to `removeAffectedValues()` on a stale cache. | |
| define void @dont_crash(i1 %cond.1, ptr %ptr) { | |
| ; CHECK-LABEL: Cached assumptions for function: dont_crash | |
| ; CHECK-NEXT: [ "nonnull"(ptr %ptr) ] | |
| ; CHECK-NEXT: [ "dereferenceable"(ptr %ptr, i64 8) ] | |
| entry: | |
| br i1 %cond.1, label %loop.cond, label %assume | |
| loop.cond: | |
| %phi = phi ptr [ null, %loop.body ], [ %ptr, %entry ] | |
| %cond.2 = phi i1 [ false, %loop.body ], [ true, %entry ] | |
| br i1 %cond.2, label %loop.body, label %dead | |
| loop.body: | |
| call void @llvm.assume(i1 true) [ "nonnull"(ptr %phi) ] | |
| ; Lengthen code sequence so that `hotcoldsplit` fires (causing the deletion). | |
| call void @noise() | |
| call void @noise() | |
| call void @noise() | |
| call void @noise() | |
| br label %loop.cond | |
| assume: | |
| call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %ptr, i64 8) ] | |
| ret void | |
| dead: | |
| unreachable | |
| } | |
| declare void @llvm.assume(i1 noundef) | |
| declare void @noise() |