| ; RUN: opt -S --passes="ipsccp<func-spec>" -funcspec-for-literal-constant=false < %s | FileCheck %s | |
| define dso_local i32 @p0(i32 noundef %x) { | |
| entry: | |
| %add = add nsw i32 %x, 1 | |
| ret i32 %add | |
| } | |
| define dso_local i32 @p1(i32 noundef %x) { | |
| entry: | |
| %sub = add nsw i32 %x, -1 | |
| ret i32 %sub | |
| } | |
| ; CHECK-LABEL: define dso_local i32 @f0 | |
| ; CHECK: tail call fastcc i32 @g.specialized.[[#A:]]({{.*}}@p0) | |
| ; | |
| define dso_local i32 @f0(i32 noundef %x) { | |
| entry: | |
| %call = tail call fastcc i32 @g(i32 noundef %x, ptr noundef nonnull @p0) | |
| ret i32 %call | |
| } | |
| ; CHECK-LABEL: define dso_local i32 @f1 | |
| ; CHECK: tail call fastcc i32 @g.specialized.[[#B:]]({{.*}}@p1) | |
| ; | |
| define dso_local i32 @f1(i32 noundef %x) { | |
| entry: | |
| %call = tail call fastcc i32 @g(i32 noundef %x, ptr noundef nonnull @p1) | |
| ret i32 %call | |
| } | |
| ; @g gets fully specialized | |
| ; CHECK-NOT: define internal fastcc i32 @g( | |
| define internal fastcc i32 @g(i32 noundef %x, ptr nocapture noundef readonly %p) noinline { | |
| entry: | |
| %pcall = tail call i32 %p(i32 noundef %x) | |
| %fcall = tail call fastcc i32 @f(i32 noundef %pcall, ptr noundef nonnull %p) | |
| ret i32 %fcall | |
| } | |
| ; CHECK-LABEL: define dso_local i32 @g0 | |
| ; CHECK: tail call fastcc i32 @f.specialized.[[#C:]]({{.*}}@p0) | |
| ; | |
| define dso_local i32 @g0(i32 noundef %x) { | |
| entry: | |
| %call = tail call fastcc i32 @f(i32 noundef %x, ptr noundef nonnull @p0) | |
| ret i32 %call | |
| } | |
| define internal fastcc i32 @f(i32 noundef %x, ptr nocapture noundef readonly %p) noinline { | |
| entry: | |
| %call = tail call i32 %p(i32 noundef %x) | |
| %add = add nsw i32 %call, %x | |
| ret i32 %add | |
| } | |
| ; CHECK-LABEL: define dso_local i32 @g1 | |
| ; CHECK: tail call fastcc i32 @f.specialized.[[#D:]]({{.*}}@p1) | |
| ; | |
| define dso_local i32 @g1(i32 noundef %x) { | |
| entry: | |
| %call = tail call fastcc i32 @f(i32 noundef %x, ptr noundef nonnull @p1) | |
| ret i32 %call | |
| } | |
| define dso_local i32 @g2(i32 noundef %x) { | |
| entry: | |
| %call = tail call fastcc i32 @f(i32 noundef %x, ptr poison) | |
| ret i32 %call | |
| } | |
| ; Check that a single argument, that cannot be used for specialisation, does not | |
| ; prevent specialisation based on other arguments. | |
| ; | |
| ; Also check that for callsites which reside in the body of newly created | |
| ; (specialized) functions, the lattice value of the arguments is known. | |
| ; | |
| ; CHECK-DAG: define internal fastcc i32 @g.specialized.[[#A]] | |
| ; CHECK-DAG: define internal fastcc i32 @g.specialized.[[#B]] | |
| ; CHECK-DAG: define internal fastcc i32 @f.specialized.[[#C]] | |
| ; CHECK-DAG: define internal fastcc i32 @f.specialized.[[#D]] |