Auto merge of #114148 - cuviper:drop-llvm-14, r=nikic

Update the minimum external LLVM to 15

With this change, we'll have stable support for LLVM 15 through 17 (pending release).
For reference, the previous increase to LLVM 14 was #107573.
This commit is contained in:
bors 2023-07-29 14:57:47 +00:00
commit 4c96822796
96 changed files with 293 additions and 472 deletions

View File

@ -55,7 +55,7 @@ jobs:
- name: mingw-check-tidy
os: ubuntu-20.04-16core-64gb
env: {}
- name: x86_64-gnu-llvm-14
- name: x86_64-gnu-llvm-15
os: ubuntu-20.04-16core-64gb
env: {}
- name: x86_64-gnu-tools
@ -293,10 +293,6 @@ jobs:
env:
RUST_BACKTRACE: 1
os: ubuntu-20.04-8core-32gb
- name: x86_64-gnu-llvm-14
env:
RUST_BACKTRACE: 1
os: ubuntu-20.04-8core-32gb
- name: x86_64-gnu-nopt
os: ubuntu-20.04-4core-16gb
env: {}

View File

@ -363,50 +363,44 @@ pub fn from_fn_attrs<'ll, 'tcx>(
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::ALLOCATOR)
|| codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::ALLOCATOR_ZEROED)
{
if llvm_util::get_version() >= (15, 0, 0) {
to_add.push(create_alloc_family_attr(cx.llcx));
// apply to argument place instead of function
let alloc_align = AttributeKind::AllocAlign.create_attr(cx.llcx);
attributes::apply_to_llfn(llfn, AttributePlace::Argument(1), &[alloc_align]);
to_add.push(llvm::CreateAllocSizeAttr(cx.llcx, 0));
let mut flags = AllocKindFlags::Alloc | AllocKindFlags::Aligned;
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::ALLOCATOR) {
flags |= AllocKindFlags::Uninitialized;
} else {
flags |= AllocKindFlags::Zeroed;
}
to_add.push(llvm::CreateAllocKindAttr(cx.llcx, flags));
to_add.push(create_alloc_family_attr(cx.llcx));
// apply to argument place instead of function
let alloc_align = AttributeKind::AllocAlign.create_attr(cx.llcx);
attributes::apply_to_llfn(llfn, AttributePlace::Argument(1), &[alloc_align]);
to_add.push(llvm::CreateAllocSizeAttr(cx.llcx, 0));
let mut flags = AllocKindFlags::Alloc | AllocKindFlags::Aligned;
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::ALLOCATOR) {
flags |= AllocKindFlags::Uninitialized;
} else {
flags |= AllocKindFlags::Zeroed;
}
to_add.push(llvm::CreateAllocKindAttr(cx.llcx, flags));
// apply to return place instead of function (unlike all other attributes applied in this function)
let no_alias = AttributeKind::NoAlias.create_attr(cx.llcx);
attributes::apply_to_llfn(llfn, AttributePlace::ReturnValue, &[no_alias]);
}
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::REALLOCATOR) {
if llvm_util::get_version() >= (15, 0, 0) {
to_add.push(create_alloc_family_attr(cx.llcx));
to_add.push(llvm::CreateAllocKindAttr(
cx.llcx,
AllocKindFlags::Realloc | AllocKindFlags::Aligned,
));
// applies to argument place instead of function place
let allocated_pointer = AttributeKind::AllocatedPointer.create_attr(cx.llcx);
attributes::apply_to_llfn(llfn, AttributePlace::Argument(0), &[allocated_pointer]);
// apply to argument place instead of function
let alloc_align = AttributeKind::AllocAlign.create_attr(cx.llcx);
attributes::apply_to_llfn(llfn, AttributePlace::Argument(2), &[alloc_align]);
to_add.push(llvm::CreateAllocSizeAttr(cx.llcx, 3));
}
to_add.push(create_alloc_family_attr(cx.llcx));
to_add.push(llvm::CreateAllocKindAttr(
cx.llcx,
AllocKindFlags::Realloc | AllocKindFlags::Aligned,
));
// applies to argument place instead of function place
let allocated_pointer = AttributeKind::AllocatedPointer.create_attr(cx.llcx);
attributes::apply_to_llfn(llfn, AttributePlace::Argument(0), &[allocated_pointer]);
// apply to argument place instead of function
let alloc_align = AttributeKind::AllocAlign.create_attr(cx.llcx);
attributes::apply_to_llfn(llfn, AttributePlace::Argument(2), &[alloc_align]);
to_add.push(llvm::CreateAllocSizeAttr(cx.llcx, 3));
let no_alias = AttributeKind::NoAlias.create_attr(cx.llcx);
attributes::apply_to_llfn(llfn, AttributePlace::ReturnValue, &[no_alias]);
}
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::DEALLOCATOR) {
if llvm_util::get_version() >= (15, 0, 0) {
to_add.push(create_alloc_family_attr(cx.llcx));
to_add.push(llvm::CreateAllocKindAttr(cx.llcx, AllocKindFlags::Free));
// applies to argument place instead of function place
let allocated_pointer = AttributeKind::AllocatedPointer.create_attr(cx.llcx);
attributes::apply_to_llfn(llfn, AttributePlace::Argument(0), &[allocated_pointer]);
}
to_add.push(create_alloc_family_attr(cx.llcx));
to_add.push(llvm::CreateAllocKindAttr(cx.llcx, AllocKindFlags::Free));
// applies to argument place instead of function place
let allocated_pointer = AttributeKind::AllocatedPointer.create_attr(cx.llcx);
attributes::apply_to_llfn(llfn, AttributePlace::Argument(0), &[allocated_pointer]);
}
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::CMSE_NONSECURE_ENTRY) {
to_add.push(llvm::CreateAttrString(cx.llcx, "cmse_nonsecure_entry"));

View File

@ -507,8 +507,6 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str
.features
.split(',')
.filter(|v| !v.is_empty() && backend_feature_name(v).is_some())
// Drop +atomics-32 feature introduced in LLVM 15.
.filter(|v| *v != "+atomics-32" || get_version() >= (15, 0, 0))
.map(String::from),
);

View File

@ -92,10 +92,8 @@ enum LLVMRustAttribute {
NoCfCheck = 35,
ShadowCallStack = 36,
AllocSize = 37,
#if LLVM_VERSION_GE(15, 0)
AllocatedPointer = 38,
AllocAlign = 39,
#endif
SanitizeSafeStack = 40,
};

View File

@ -801,9 +801,6 @@ LLVMRustOptimize(
OptimizerLastEPCallbacks.push_back(
[SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) {
auto CompileKernel = SanitizerOptions->SanitizeKernelAddress;
#if LLVM_VERSION_LT(15, 0)
MPM.addPass(RequireAnalysisPass<ASanGlobalsMetadataAnalysis, Module>());
#endif
AddressSanitizerOptions opts = AddressSanitizerOptions{
CompileKernel,
SanitizerOptions->SanitizeAddressRecover

View File

@ -277,12 +277,10 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
return Attribute::ShadowCallStack;
case AllocSize:
return Attribute::AllocSize;
#if LLVM_VERSION_GE(15, 0)
case AllocatedPointer:
return Attribute::AllocatedPointer;
case AllocAlign:
return Attribute::AllocAlign;
#endif
case SanitizeSafeStack:
return Attribute::SafeStack;
}
@ -340,20 +338,12 @@ extern "C" LLVMAttributeRef LLVMRustCreateStructRetAttr(LLVMContextRef C, LLVMTy
}
extern "C" LLVMAttributeRef LLVMRustCreateElementTypeAttr(LLVMContextRef C, LLVMTypeRef Ty) {
#if LLVM_VERSION_GE(15, 0)
return wrap(Attribute::get(*unwrap(C), Attribute::ElementType, unwrap(Ty)));
#else
report_fatal_error("Should not be needed on LLVM < 15");
#endif
}
extern "C" LLVMAttributeRef LLVMRustCreateUWTableAttr(LLVMContextRef C, bool Async) {
#if LLVM_VERSION_LT(15, 0)
return wrap(Attribute::get(*unwrap(C), Attribute::UWTable));
#else
return wrap(Attribute::getWithUWTableKind(
*unwrap(C), Async ? UWTableKind::Async : UWTableKind::Sync));
#endif
}
extern "C" LLVMAttributeRef LLVMRustCreateAllocSizeAttr(LLVMContextRef C, uint32_t ElementSizeArg) {
@ -366,8 +356,6 @@ extern "C" LLVMAttributeRef LLVMRustCreateAllocSizeAttr(LLVMContextRef C, uint32
));
}
#if LLVM_VERSION_GE(15, 0)
// These values **must** match ffi::AllocKindFlags.
// It _happens_ to match the LLVM values of llvm::AllocFnKind,
// but that's happenstance and we do explicit conversions before
@ -411,16 +399,10 @@ static llvm::AllocFnKind allocKindFromRust(LLVMRustAllocKindFlags F) {
}
return AFK;
}
#endif
extern "C" LLVMAttributeRef LLVMRustCreateAllocKindAttr(LLVMContextRef C, uint64_t AllocKindArg) {
#if LLVM_VERSION_GE(15, 0)
return wrap(Attribute::get(*unwrap(C), Attribute::AllocKind,
static_cast<uint64_t>(allocKindFromRust(static_cast<LLVMRustAllocKindFlags>(AllocKindArg)))));
#else
report_fatal_error(
"allockind attributes are new in LLVM 15 and should not be used on older LLVMs");
#endif
}
// Simplified representation of `MemoryEffects` across the FFI boundary.
@ -517,14 +499,9 @@ LLVMRustInlineAsm(LLVMTypeRef Ty, char *AsmString, size_t AsmStringLen,
extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty, char *Constraints,
size_t ConstraintsLen) {
#if LLVM_VERSION_LT(15, 0)
return InlineAsm::Verify(unwrap<FunctionType>(Ty),
StringRef(Constraints, ConstraintsLen));
#else
// llvm::Error converts to true if it is an error.
return !llvm::errorToBool(InlineAsm::verify(
unwrap<FunctionType>(Ty), StringRef(Constraints, ConstraintsLen)));
#endif
}
typedef DIBuilder *LLVMRustDIBuilderRef;
@ -1649,19 +1626,11 @@ extern "C" bool LLVMRustConstInt128Get(LLVMValueRef CV, bool sext, uint64_t *hig
auto C = unwrap<llvm::ConstantInt>(CV);
if (C->getBitWidth() > 128) { return false; }
APInt AP;
#if LLVM_VERSION_GE(15, 0)
if (sext) {
AP = C->getValue().sext(128);
} else {
AP = C->getValue().zext(128);
}
#else
if (sext) {
AP = C->getValue().sextOrSelf(128);
} else {
AP = C->getValue().zextOrSelf(128);
}
#endif
*low = AP.getLoBits(64).getZExtValue();
*high = AP.getHiBits(64).getZExtValue();
return true;
@ -2037,16 +2006,7 @@ extern "C" void LLVMRustGetMangledName(LLVMValueRef V, RustStringRef Str) {
Mangler().getNameWithPrefix(OS, GV, true);
}
// LLVMGetAggregateElement was added in LLVM 15. For earlier LLVM versions just
// use its implementation.
#if LLVM_VERSION_LT(15, 0)
extern "C" LLVMValueRef LLVMGetAggregateElement(LLVMValueRef C, unsigned Idx) {
return wrap(unwrap<Constant>(C)->getAggregateElement(Idx));
}
#endif
extern "C" int32_t LLVMRustGetElementTypeArgIndex(LLVMValueRef CallSite) {
#if LLVM_VERSION_GE(15, 0)
auto *CB = unwrap<CallBase>(CallSite);
switch (CB->getIntrinsicID()) {
case Intrinsic::arm_ldrex:
@ -2054,7 +2014,6 @@ extern "C" int32_t LLVMRustGetElementTypeArgIndex(LLVMValueRef CallSite) {
case Intrinsic::arm_strex:
return 1;
}
#endif
return -1;
}

View File

@ -525,11 +525,11 @@ fn check_llvm_version(builder: &Builder<'_>, llvm_config: &Path) {
let version = output(cmd.arg("--version"));
let mut parts = version.split('.').take(2).filter_map(|s| s.parse::<u32>().ok());
if let (Some(major), Some(_minor)) = (parts.next(), parts.next()) {
if major >= 14 {
if major >= 15 {
return;
}
}
panic!("\n\nbad LLVM version: {}, need >=14.0\n\n", version)
panic!("\n\nbad LLVM version: {}, need >=15.0\n\n", version)
}
fn configure_cmake(

View File

@ -1,54 +0,0 @@
FROM ubuntu:22.04
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y --no-install-recommends \
g++ \
gcc-multilib \
make \
ninja-build \
file \
curl \
ca-certificates \
python3.11 \
git \
cmake \
sudo \
gdb \
llvm-14-tools \
llvm-14-dev \
libedit-dev \
libssl-dev \
pkg-config \
zlib1g-dev \
xz-utils \
nodejs \
mingw-w64 \
&& rm -rf /var/lib/apt/lists/*
# Install powershell (universal package) so we can test x.ps1 on Linux
RUN curl -sL "https://github.com/PowerShell/PowerShell/releases/download/v7.3.1/powershell_7.3.1-1.deb_amd64.deb" > powershell.deb && \
dpkg -i powershell.deb && \
rm -f powershell.deb
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
# We are disabling CI LLVM since this builder is intentionally using a host
# LLVM, rather than the typical src/llvm-project LLVM.
ENV NO_DOWNLOAD_CI_LLVM 1
# This is not the latest LLVM version, so some components required by tests may
# be missing.
ENV IS_NOT_LATEST_LLVM 1
# Using llvm-link-shared due to libffi issues -- see #34486
ENV RUST_CONFIGURE_ARGS \
--build=x86_64-unknown-linux-gnu \
--llvm-root=/usr/lib/llvm-14 \
--enable-llvm-link-shared \
--set rust.thin-lto-import-instr-limit=10
COPY host-x86_64/x86_64-gnu-llvm-14/script.sh /tmp/
ENV SCRIPT /tmp/script.sh

View File

@ -1,4 +1,4 @@
FROM ubuntu:22.10
FROM ubuntu:22.04
ARG DEBIAN_FRONTEND=noninteractive
@ -10,7 +10,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
file \
curl \
ca-certificates \
python3 \
python3.11 \
git \
cmake \
sudo \
@ -49,20 +49,6 @@ ENV RUST_CONFIGURE_ARGS \
--enable-llvm-link-shared \
--set rust.thin-lto-import-instr-limit=10
# NOTE: intentionally uses all of `x.py`, `x`, and `x.ps1` to make sure they all work on Linux.
ENV SCRIPT ../x.py --stage 2 test --exclude src/tools/tidy && \
# Run the `mir-opt` tests again but this time for a 32-bit target.
# This enforces that tests using `// EMIT_MIR_FOR_EACH_BIT_WIDTH` have
# both 32-bit and 64-bit outputs updated by the PR author, before
# the PR is approved and tested for merging.
# It will also detect tests lacking `// EMIT_MIR_FOR_EACH_BIT_WIDTH`,
# despite having different output on 32-bit vs 64-bit targets.
../x --stage 2 test tests/mir-opt \
--host='' --target=i686-unknown-linux-gnu && \
# Run the UI test suite again, but in `--pass=check` mode
#
# This is intended to make sure that both `--pass=check` continues to
# work.
#
../x.ps1 --stage 2 test tests/ui --pass=check \
--host='' --target=i686-unknown-linux-gnu
COPY host-x86_64/x86_64-gnu-llvm-15/script.sh /tmp/
ENV SCRIPT /tmp/script.sh

View File

@ -45,20 +45,6 @@ ENV RUST_CONFIGURE_ARGS \
--enable-llvm-link-shared \
--set rust.thin-lto-import-instr-limit=10
# NOTE: intentionally uses all of `x.py`, `x`, and `x.ps1` to make sure they all work on Linux.
ENV SCRIPT ../x.py --stage 2 test --exclude src/tools/tidy && \
# Run the `mir-opt` tests again but this time for a 32-bit target.
# This enforces that tests using `// EMIT_MIR_FOR_EACH_BIT_WIDTH` have
# both 32-bit and 64-bit outputs updated by the PR author, before
# the PR is approved and tested for merging.
# It will also detect tests lacking `// EMIT_MIR_FOR_EACH_BIT_WIDTH`,
# despite having different output on 32-bit vs 64-bit targets.
../x --stage 2 test tests/mir-opt \
--host='' --target=i686-unknown-linux-gnu && \
# Run the UI test suite again, but in `--pass=check` mode
#
# This is intended to make sure that both `--pass=check` continues to
# work.
#
../x.ps1 --stage 2 test tests/ui --pass=check \
--host='' --target=i686-unknown-linux-gnu
COPY host-x86_64/x86_64-gnu-llvm-15/script.sh /tmp/
ENV SCRIPT /tmp/script.sh

View File

@ -323,7 +323,7 @@ jobs:
- name: mingw-check-tidy
<<: *job-linux-16c
- name: x86_64-gnu-llvm-14
- name: x86_64-gnu-llvm-15
<<: *job-linux-16c
- name: x86_64-gnu-tools
@ -469,11 +469,6 @@ jobs:
RUST_BACKTRACE: 1
<<: *job-linux-8c
- name: x86_64-gnu-llvm-14
env:
RUST_BACKTRACE: 1
<<: *job-linux-8c
- name: x86_64-gnu-nopt
<<: *job-linux-4c

View File

@ -1,5 +1,4 @@
// assembly-output: emit-asm
// min-llvm-version: 15.0
// only-x86_64
// ignore-sgx
// revisions: opt-speed opt-size

View File

@ -3,7 +3,6 @@
// [LIN] only-linux
// assembly-output: emit-asm
// compile-flags: --crate-type=lib -O -C llvm-args=-x86-asm-syntax=intel
// min-llvm-version: 14
// only-x86_64
// ignore-sgx
// ignore-debug

View File

@ -2,7 +2,6 @@
// compile-flags: -Copt-level=1
// only-x86_64
// ignore-sgx
// min-llvm-version: 15.0
#![crate_type = "rlib"]
// CHECK-LABEL: old_style

View File

@ -7,4 +7,4 @@
fn main() {
}
// CHECK: define{{( hidden)?}} i32 @main(i32{{( %0)?}}, {{i8\*\*|ptr}}{{( %1)?}})
// CHECK: define{{( hidden)?}} i32 @main(i32{{( %0)?}}, ptr{{( %1)?}})

View File

@ -1,5 +1,4 @@
// compile-flags: -C opt-level=3 -C no-prepopulate-passes
// min-llvm-version: 15.0 (for opaque pointers)
#![crate_type = "lib"]

View File

@ -13,9 +13,9 @@ pub fn helper(_: usize) {
pub fn no_op_slice_adjustment(x: &[u8]) -> &[u8] {
// We used to generate an extra alloca and memcpy for the block's trailing expression value, so
// check that we copy directly to the return value slot
// CHECK: %0 = insertvalue { {{\[0 x i8\]\*|ptr}}, [[USIZE]] } poison, {{\[0 x i8\]\*|ptr}} %x.0, 0
// CHECK: %1 = insertvalue { {{\[0 x i8\]\*|ptr}}, [[USIZE]] } %0, [[USIZE]] %x.1, 1
// CHECK: ret { {{\[0 x i8\]\*|ptr}}, [[USIZE]] } %1
// CHECK: %0 = insertvalue { ptr, [[USIZE]] } poison, ptr %x.0, 0
// CHECK: %1 = insertvalue { ptr, [[USIZE]] } %0, [[USIZE]] %x.1, 1
// CHECK: ret { ptr, [[USIZE]] } %1
{ x }
}

View File

@ -20,7 +20,7 @@ pub struct Nested64 {
#[no_mangle]
pub fn align64(a: u32) -> Align64 {
// CHECK: %a64 = alloca %Align64, align 64
// CHECK: call void @llvm.memcpy.{{.*}}({{i8\*|ptr}} align 64 %{{.*}}, {{i8\*|ptr}} align 64 %{{.*}}, i{{[0-9]+}} 64, i1 false)
// CHECK: call void @llvm.memcpy.{{.*}}(ptr align 64 %{{.*}}, ptr align 64 %{{.*}}, i{{[0-9]+}} 64, i1 false)
let a64 = Align64::A(a);
a64
}

View File

@ -1,5 +1,4 @@
// compile-flags: -O
// min-llvm-version: 15.0 (because we're using opaque pointers)
// ignore-debug (debug assertions in `slice::from_raw_parts` block optimizations)
#![crate_type = "lib"]

View File

@ -32,7 +32,7 @@ pub enum Enum64 {
#[no_mangle]
pub fn align64(i : i32) -> Align64 {
// CHECK: %a64 = alloca %Align64, align 64
// CHECK: call void @llvm.memcpy.{{.*}}({{i8\*|ptr}} align 64 %{{.*}}, {{i8\*|ptr}} align 64 %{{.*}}, i{{[0-9]+}} 64, i1 false)
// CHECK: call void @llvm.memcpy.{{.*}}(ptr align 64 %{{.*}}, ptr align 64 %{{.*}}, i{{[0-9]+}} 64, i1 false)
let a64 = Align64(i);
a64
}
@ -42,7 +42,7 @@ pub fn align64(i : i32) -> Align64 {
// CHECK-LABEL: @align64_load
#[no_mangle]
pub fn align64_load(a: Align64) -> i32 {
// CHECK: {{%.*}} = load i32, {{i32\*|ptr}} {{%.*}}, align 64
// CHECK: {{%.*}} = load i32, ptr {{%.*}}, align 64
a.0
}

View File

@ -1,5 +1,4 @@
// compile-flags: -O -C no-prepopulate-passes
// min-llvm-version: 15.0 (for opaque pointers)
#![crate_type = "lib"]

View File

@ -16,8 +16,8 @@
#[no_mangle]
pub fn array_eq_ref(a: &[u16; 3], b: &[u16; 3]) -> bool {
// CHECK: start:
// CHECK: load i48, {{i48\*|ptr}} %{{.+}}, align 2
// CHECK: load i48, {{i48\*|ptr}} %{{.+}}, align 2
// CHECK: load i48, ptr %{{.+}}, align 2
// CHECK: load i48, ptr %{{.+}}, align 2
// CHECK: icmp eq i48
// CHECK-NEXT: ret
a == b
@ -27,7 +27,7 @@
#[no_mangle]
pub fn array_eq_value_still_passed_by_pointer(a: [u16; 9], b: [u16; 9]) -> bool {
// CHECK-NEXT: start:
// CHECK: %[[CMP:.+]] = tail call i32 @{{bcmp|memcmp}}({{i8\*|ptr}} {{.*}} dereferenceable(18) %{{.+}}, {{i8\*|ptr}} {{.*}} dereferenceable(18) %{{.+}}, i64 18)
// CHECK: %[[CMP:.+]] = tail call i32 @{{bcmp|memcmp}}(ptr {{.*}} dereferenceable(18) %{{.+}}, ptr {{.*}} dereferenceable(18) %{{.+}}, i64 18)
// CHECK-NEXT: %[[EQ:.+]] = icmp eq i32 %[[CMP]], 0
// CHECK-NEXT: ret i1 %[[EQ]]
a == b
@ -37,7 +37,7 @@
#[no_mangle]
pub fn array_eq_long(a: &[u16; 1234], b: &[u16; 1234]) -> bool {
// CHECK-NEXT: start:
// CHECK: %[[CMP:.+]] = tail call i32 @{{bcmp|memcmp}}({{i8\*|ptr}} {{.*}} dereferenceable(2468) %{{.+}}, {{i8\*|ptr}} {{.*}} dereferenceable(2468) %{{.+}}, i64 2468)
// CHECK: %[[CMP:.+]] = tail call i32 @{{bcmp|memcmp}}(ptr {{.*}} dereferenceable(2468) %{{.+}}, ptr {{.*}} dereferenceable(2468) %{{.+}}, i64 2468)
// CHECK-NEXT: %[[EQ:.+]] = icmp eq i32 %[[CMP]], 0
// CHECK-NEXT: ret i1 %[[EQ]]
a == b

View File

@ -7,37 +7,37 @@
// CHECK-LABEL: @compare_exchange
#[no_mangle]
pub fn compare_exchange(a: &AtomicI32) {
// CHECK: cmpxchg {{i32\*|ptr}} %{{.*}}, i32 0, i32 10 monotonic monotonic
// CHECK: cmpxchg {{i32\*|ptr}} %{{.*}}, i32 0, i32 11 monotonic acquire
// CHECK: cmpxchg {{i32\*|ptr}} %{{.*}}, i32 0, i32 12 monotonic seq_cst
// CHECK: cmpxchg ptr %{{.*}}, i32 0, i32 10 monotonic monotonic
// CHECK: cmpxchg ptr %{{.*}}, i32 0, i32 11 monotonic acquire
// CHECK: cmpxchg ptr %{{.*}}, i32 0, i32 12 monotonic seq_cst
let _ = a.compare_exchange(0, 10, Relaxed, Relaxed);
let _ = a.compare_exchange(0, 11, Relaxed, Acquire);
let _ = a.compare_exchange(0, 12, Relaxed, SeqCst);
// CHECK: cmpxchg {{i32\*|ptr}} %{{.*}}, i32 0, i32 20 release monotonic
// CHECK: cmpxchg {{i32\*|ptr}} %{{.*}}, i32 0, i32 21 release acquire
// CHECK: cmpxchg {{i32\*|ptr}} %{{.*}}, i32 0, i32 22 release seq_cst
// CHECK: cmpxchg ptr %{{.*}}, i32 0, i32 20 release monotonic
// CHECK: cmpxchg ptr %{{.*}}, i32 0, i32 21 release acquire
// CHECK: cmpxchg ptr %{{.*}}, i32 0, i32 22 release seq_cst
let _ = a.compare_exchange(0, 20, Release, Relaxed);
let _ = a.compare_exchange(0, 21, Release, Acquire);
let _ = a.compare_exchange(0, 22, Release, SeqCst);
// CHECK: cmpxchg {{i32\*|ptr}} %{{.*}}, i32 0, i32 30 acquire monotonic
// CHECK: cmpxchg {{i32\*|ptr}} %{{.*}}, i32 0, i32 31 acquire acquire
// CHECK: cmpxchg {{i32\*|ptr}} %{{.*}}, i32 0, i32 32 acquire seq_cst
// CHECK: cmpxchg ptr %{{.*}}, i32 0, i32 30 acquire monotonic
// CHECK: cmpxchg ptr %{{.*}}, i32 0, i32 31 acquire acquire
// CHECK: cmpxchg ptr %{{.*}}, i32 0, i32 32 acquire seq_cst
let _ = a.compare_exchange(0, 30, Acquire, Relaxed);
let _ = a.compare_exchange(0, 31, Acquire, Acquire);
let _ = a.compare_exchange(0, 32, Acquire, SeqCst);
// CHECK: cmpxchg {{i32\*|ptr}} %{{.*}}, i32 0, i32 40 acq_rel monotonic
// CHECK: cmpxchg {{i32\*|ptr}} %{{.*}}, i32 0, i32 41 acq_rel acquire
// CHECK: cmpxchg {{i32\*|ptr}} %{{.*}}, i32 0, i32 42 acq_rel seq_cst
// CHECK: cmpxchg ptr %{{.*}}, i32 0, i32 40 acq_rel monotonic
// CHECK: cmpxchg ptr %{{.*}}, i32 0, i32 41 acq_rel acquire
// CHECK: cmpxchg ptr %{{.*}}, i32 0, i32 42 acq_rel seq_cst
let _ = a.compare_exchange(0, 40, AcqRel, Relaxed);
let _ = a.compare_exchange(0, 41, AcqRel, Acquire);
let _ = a.compare_exchange(0, 42, AcqRel, SeqCst);
// CHECK: cmpxchg {{i32\*|ptr}} %{{.*}}, i32 0, i32 50 seq_cst monotonic
// CHECK: cmpxchg {{i32\*|ptr}} %{{.*}}, i32 0, i32 51 seq_cst acquire
// CHECK: cmpxchg {{i32\*|ptr}} %{{.*}}, i32 0, i32 52 seq_cst seq_cst
// CHECK: cmpxchg ptr %{{.*}}, i32 0, i32 50 seq_cst monotonic
// CHECK: cmpxchg ptr %{{.*}}, i32 0, i32 51 seq_cst acquire
// CHECK: cmpxchg ptr %{{.*}}, i32 0, i32 52 seq_cst seq_cst
let _ = a.compare_exchange(0, 50, SeqCst, Relaxed);
let _ = a.compare_exchange(0, 51, SeqCst, Acquire);
let _ = a.compare_exchange(0, 52, SeqCst, SeqCst);
@ -46,37 +46,37 @@ pub fn compare_exchange(a: &AtomicI32) {
// CHECK-LABEL: @compare_exchange_weak
#[no_mangle]
pub fn compare_exchange_weak(w: &AtomicI32) {
// CHECK: cmpxchg weak {{i32\*|ptr}} %{{.*}}, i32 1, i32 10 monotonic monotonic
// CHECK: cmpxchg weak {{i32\*|ptr}} %{{.*}}, i32 1, i32 11 monotonic acquire
// CHECK: cmpxchg weak {{i32\*|ptr}} %{{.*}}, i32 1, i32 12 monotonic seq_cst
// CHECK: cmpxchg weak ptr %{{.*}}, i32 1, i32 10 monotonic monotonic
// CHECK: cmpxchg weak ptr %{{.*}}, i32 1, i32 11 monotonic acquire
// CHECK: cmpxchg weak ptr %{{.*}}, i32 1, i32 12 monotonic seq_cst
let _ = w.compare_exchange_weak(1, 10, Relaxed, Relaxed);
let _ = w.compare_exchange_weak(1, 11, Relaxed, Acquire);
let _ = w.compare_exchange_weak(1, 12, Relaxed, SeqCst);
// CHECK: cmpxchg weak {{i32\*|ptr}} %{{.*}}, i32 1, i32 20 release monotonic
// CHECK: cmpxchg weak {{i32\*|ptr}} %{{.*}}, i32 1, i32 21 release acquire
// CHECK: cmpxchg weak {{i32\*|ptr}} %{{.*}}, i32 1, i32 22 release seq_cst
// CHECK: cmpxchg weak ptr %{{.*}}, i32 1, i32 20 release monotonic
// CHECK: cmpxchg weak ptr %{{.*}}, i32 1, i32 21 release acquire
// CHECK: cmpxchg weak ptr %{{.*}}, i32 1, i32 22 release seq_cst
let _ = w.compare_exchange_weak(1, 20, Release, Relaxed);
let _ = w.compare_exchange_weak(1, 21, Release, Acquire);
let _ = w.compare_exchange_weak(1, 22, Release, SeqCst);
// CHECK: cmpxchg weak {{i32\*|ptr}} %{{.*}}, i32 1, i32 30 acquire monotonic
// CHECK: cmpxchg weak {{i32\*|ptr}} %{{.*}}, i32 1, i32 31 acquire acquire
// CHECK: cmpxchg weak {{i32\*|ptr}} %{{.*}}, i32 1, i32 32 acquire seq_cst
// CHECK: cmpxchg weak ptr %{{.*}}, i32 1, i32 30 acquire monotonic
// CHECK: cmpxchg weak ptr %{{.*}}, i32 1, i32 31 acquire acquire
// CHECK: cmpxchg weak ptr %{{.*}}, i32 1, i32 32 acquire seq_cst
let _ = w.compare_exchange_weak(1, 30, Acquire, Relaxed);
let _ = w.compare_exchange_weak(1, 31, Acquire, Acquire);
let _ = w.compare_exchange_weak(1, 32, Acquire, SeqCst);
// CHECK: cmpxchg weak {{i32\*|ptr}} %{{.*}}, i32 1, i32 40 acq_rel monotonic
// CHECK: cmpxchg weak {{i32\*|ptr}} %{{.*}}, i32 1, i32 41 acq_rel acquire
// CHECK: cmpxchg weak {{i32\*|ptr}} %{{.*}}, i32 1, i32 42 acq_rel seq_cst
// CHECK: cmpxchg weak ptr %{{.*}}, i32 1, i32 40 acq_rel monotonic
// CHECK: cmpxchg weak ptr %{{.*}}, i32 1, i32 41 acq_rel acquire
// CHECK: cmpxchg weak ptr %{{.*}}, i32 1, i32 42 acq_rel seq_cst
let _ = w.compare_exchange_weak(1, 40, AcqRel, Relaxed);
let _ = w.compare_exchange_weak(1, 41, AcqRel, Acquire);
let _ = w.compare_exchange_weak(1, 42, AcqRel, SeqCst);
// CHECK: cmpxchg weak {{i32\*|ptr}} %{{.*}}, i32 1, i32 50 seq_cst monotonic
// CHECK: cmpxchg weak {{i32\*|ptr}} %{{.*}}, i32 1, i32 51 seq_cst acquire
// CHECK: cmpxchg weak {{i32\*|ptr}} %{{.*}}, i32 1, i32 52 seq_cst seq_cst
// CHECK: cmpxchg weak ptr %{{.*}}, i32 1, i32 50 seq_cst monotonic
// CHECK: cmpxchg weak ptr %{{.*}}, i32 1, i32 51 seq_cst acquire
// CHECK: cmpxchg weak ptr %{{.*}}, i32 1, i32 52 seq_cst seq_cst
let _ = w.compare_exchange_weak(1, 50, SeqCst, Relaxed);
let _ = w.compare_exchange_weak(1, 51, SeqCst, Acquire);
let _ = w.compare_exchange_weak(1, 52, SeqCst, SeqCst);

View File

@ -94,7 +94,7 @@ pub extern "C" fn test() {
// Validate that we can codegen transmutes between data ptrs and fn ptrs.
// CHECK: define{{.+}}{{void \(\) addrspace\(1\)\*|ptr addrspace\(1\)}} @transmute_data_ptr_to_fn({{\{\}\*|ptr}}{{.*}} %x)
// CHECK: define{{.+}}ptr addrspace(1) @transmute_data_ptr_to_fn(ptr{{.*}} %x)
#[no_mangle]
pub unsafe fn transmute_data_ptr_to_fn(x: *const ()) -> fn() {
// It doesn't matter precisely how this is codegenned (through memory or an addrspacecast),
@ -102,7 +102,7 @@ pub unsafe fn transmute_data_ptr_to_fn(x: *const ()) -> fn() {
transmute(x)
}
// CHECK: define{{.+}}{{\{\}\*|ptr}} @transmute_fn_ptr_to_data({{void \(\) addrspace\(1\)\*|ptr addrspace\(1\)}}{{.*}} %x)
// CHECK: define{{.+}}ptr @transmute_fn_ptr_to_data(ptr addrspace(1){{.*}} %x)
#[no_mangle]
pub unsafe fn transmute_fn_ptr_to_data(x: fn()) -> *const () {
// It doesn't matter precisely how this is codegenned (through memory or an addrspacecast),
@ -116,7 +116,7 @@ pub enum Either<T, U> { A(T), B(U) }
// with the `ptr` field representing both `&i32` and `fn()` depending on the variant.
// This is incorrect, because `fn()` should be `ptr addrspace(1)`, not `ptr`.
// CHECK: define{{.+}}void @should_not_combine_addrspace({{.+\*|ptr}}{{.+}}sret{{.+}}%_0, {{.+\*|ptr}}{{.+}}%x)
// CHECK: define{{.+}}void @should_not_combine_addrspace(ptr{{.+}}sret{{.+}}%_0, ptr{{.+}}%x)
#[no_mangle]
#[inline(never)]
pub fn should_not_combine_addrspace(x: Either<&i32, fn()>) -> Either<&i32, fn()> {

View File

@ -1,5 +1,4 @@
// compile-flags: -O
// min-llvm-version: 15.0
#![crate_type = "lib"]
use std::mem::MaybeUninit;

View File

@ -1,5 +1,4 @@
// compile-flags: -C opt-level=1 -Z merge-functions=disabled
// min-llvm-version: 15.0
// only-x86_64
#![crate_type = "lib"]

View File

@ -3,7 +3,6 @@
// in the operators for such a type all optimize away.
// compile-flags: -C opt-level=1
// min-llvm-version: 15.0
#![crate_type = "lib"]

View File

@ -1,5 +1,4 @@
// compile-flags: -C no-prepopulate-passes
// min-llvm-version: 15.0 (for opaque pointers)
#![crate_type = "lib"]

View File

@ -7,9 +7,9 @@
use std::marker::PhantomPinned;
// CHECK: define internal void @{{.*}}core{{.*}}ptr{{.*}}drop_in_place{{.*}}StructUnpin{{.*}}({{.*\*|ptr}} noalias noundef align 4 dereferenceable(12) %{{.+}})
// CHECK: define internal void @{{.*}}core{{.*}}ptr{{.*}}drop_in_place{{.*}}StructUnpin{{.*}}(ptr noalias noundef align 4 dereferenceable(12) %{{.+}})
// CHECK: define internal void @{{.*}}core{{.*}}ptr{{.*}}drop_in_place{{.*}}StructNotUnpin{{.*}}({{.*\*|ptr}} noundef nonnull align 4 %{{.+}})
// CHECK: define internal void @{{.*}}core{{.*}}ptr{{.*}}drop_in_place{{.*}}StructNotUnpin{{.*}}(ptr noundef nonnull align 4 %{{.+}})
pub struct StructUnpin {
a: i32,

View File

@ -19,7 +19,7 @@ pub mod tests {
#[no_mangle]
pub extern "fastcall" fn f1(_: i32, _: i32, _: i32) {}
// CHECK: @f2({{i32\*|ptr}} inreg noundef %_1, {{i32\*|ptr}} inreg noundef %_2, {{i32\*|ptr}} noundef %_3)
// CHECK: @f2(ptr inreg noundef %_1, ptr inreg noundef %_2, ptr noundef %_3)
#[no_mangle]
pub extern "fastcall" fn f2(_: *const i32, _: *const i32, _: *const i32) {}

View File

@ -23,13 +23,13 @@ pub fn boolean_call(x: bool, f: fn(bool) -> bool) -> bool {
f(x)
}
// CHECK: align 4 {{i32\*|ptr}} @borrow({{i32\*|ptr}} align 4 %x)
// CHECK: align 4 ptr @borrow(ptr align 4 %x)
#[no_mangle]
pub fn borrow(x: &i32) -> &i32 {
x
}
// CHECK: align 4 {{i32\*|ptr}} @borrow_mut({{i32\*|ptr}} align 4 %x)
// CHECK: align 4 ptr @borrow_mut(ptr align 4 %x)
#[no_mangle]
pub fn borrow_mut(x: &mut i32) -> &mut i32 {
x
@ -38,11 +38,11 @@ pub fn borrow_mut(x: &mut i32) -> &mut i32 {
// CHECK-LABEL: @borrow_call
#[no_mangle]
pub fn borrow_call(x: &i32, f: fn(&i32) -> &i32) -> &i32 {
// CHECK: call align 4 {{i32\*|ptr}} %f({{i32\*|ptr}} align 4 %x)
// CHECK: call align 4 ptr %f(ptr align 4 %x)
f(x)
}
// CHECK: void @struct_({{%S\*|ptr}} sret(%S) align 4{{( %_0)?}}, {{%S\*|ptr}} align 4 %x)
// CHECK: void @struct_(ptr sret(%S) align 4{{( %_0)?}}, ptr align 4 %x)
#[no_mangle]
pub fn struct_(x: S) -> S {
x
@ -51,7 +51,7 @@ pub fn struct_(x: S) -> S {
// CHECK-LABEL: @struct_call
#[no_mangle]
pub fn struct_call(x: S, f: fn(S) -> S) -> S {
// CHECK: call void %f({{%S\*|ptr}} sret(%S) align 4{{( %_0)?}}, {{%S\*|ptr}} align 4 %{{.+}})
// CHECK: call void %f(ptr sret(%S) align 4{{( %_0)?}}, ptr align 4 %{{.+}})
f(x)
}

View File

@ -80,95 +80,95 @@ pub fn option_nonzero_int(x: Option<NonZeroU64>) -> Option<NonZeroU64> {
x
}
// CHECK: @readonly_borrow({{i32\*|ptr}} noalias noundef readonly align 4 dereferenceable(4) %_1)
// CHECK: @readonly_borrow(ptr noalias noundef readonly align 4 dereferenceable(4) %_1)
// FIXME #25759 This should also have `nocapture`
#[no_mangle]
pub fn readonly_borrow(_: &i32) {
}
// CHECK: noundef align 4 dereferenceable(4) {{i32\*|ptr}} @readonly_borrow_ret()
// CHECK: noundef align 4 dereferenceable(4) ptr @readonly_borrow_ret()
#[no_mangle]
pub fn readonly_borrow_ret() -> &'static i32 {
loop {}
}
// CHECK: @static_borrow({{i32\*|ptr}} noalias noundef readonly align 4 dereferenceable(4) %_1)
// CHECK: @static_borrow(ptr noalias noundef readonly align 4 dereferenceable(4) %_1)
// static borrow may be captured
#[no_mangle]
pub fn static_borrow(_: &'static i32) {
}
// CHECK: @named_borrow({{i32\*|ptr}} noalias noundef readonly align 4 dereferenceable(4) %_1)
// CHECK: @named_borrow(ptr noalias noundef readonly align 4 dereferenceable(4) %_1)
// borrow with named lifetime may be captured
#[no_mangle]
pub fn named_borrow<'r>(_: &'r i32) {
}
// CHECK: @unsafe_borrow({{i16\*|ptr}} noundef nonnull align 2 %_1)
// CHECK: @unsafe_borrow(ptr noundef nonnull align 2 %_1)
// unsafe interior means this isn't actually readonly and there may be aliases ...
#[no_mangle]
pub fn unsafe_borrow(_: &UnsafeInner) {
}
// CHECK: @mutable_unsafe_borrow({{i16\*|ptr}} noalias noundef align 2 dereferenceable(2) %_1)
// CHECK: @mutable_unsafe_borrow(ptr noalias noundef align 2 dereferenceable(2) %_1)
// ... unless this is a mutable borrow, those never alias
#[no_mangle]
pub fn mutable_unsafe_borrow(_: &mut UnsafeInner) {
}
// CHECK: @mutable_borrow({{i32\*|ptr}} noalias noundef align 4 dereferenceable(4) %_1)
// CHECK: @mutable_borrow(ptr noalias noundef align 4 dereferenceable(4) %_1)
// FIXME #25759 This should also have `nocapture`
#[no_mangle]
pub fn mutable_borrow(_: &mut i32) {
}
// CHECK: noundef align 4 dereferenceable(4) {{i32\*|ptr}} @mutable_borrow_ret()
// CHECK: noundef align 4 dereferenceable(4) ptr @mutable_borrow_ret()
#[no_mangle]
pub fn mutable_borrow_ret() -> &'static mut i32 {
loop {}
}
#[no_mangle]
// CHECK: @mutable_notunpin_borrow({{i32\*|ptr}} noundef nonnull align 4 %_1)
// CHECK: @mutable_notunpin_borrow(ptr noundef nonnull align 4 %_1)
// This one is *not* `noalias` because it might be self-referential.
// It is also not `dereferenceable` due to
// <https://github.com/rust-lang/unsafe-code-guidelines/issues/381>.
pub fn mutable_notunpin_borrow(_: &mut NotUnpin) {
}
// CHECK: @notunpin_borrow({{i32\*|ptr}} noalias noundef readonly align 4 dereferenceable(4) %_1)
// CHECK: @notunpin_borrow(ptr noalias noundef readonly align 4 dereferenceable(4) %_1)
// But `&NotUnpin` behaves perfectly normal.
#[no_mangle]
pub fn notunpin_borrow(_: &NotUnpin) {
}
// CHECK: @indirect_struct({{%S\*|ptr}} noalias nocapture noundef readonly align 4 dereferenceable(32) %_1)
// CHECK: @indirect_struct(ptr noalias nocapture noundef readonly align 4 dereferenceable(32) %_1)
#[no_mangle]
pub fn indirect_struct(_: S) {
}
// CHECK: @borrowed_struct({{%S\*|ptr}} noalias noundef readonly align 4 dereferenceable(32) %_1)
// CHECK: @borrowed_struct(ptr noalias noundef readonly align 4 dereferenceable(32) %_1)
// FIXME #25759 This should also have `nocapture`
#[no_mangle]
pub fn borrowed_struct(_: &S) {
}
// CHECK: @option_borrow({{i32\*|ptr}} noalias noundef readonly align 4 dereferenceable_or_null(4) %x)
// CHECK: @option_borrow(ptr noalias noundef readonly align 4 dereferenceable_or_null(4) %x)
#[no_mangle]
pub fn option_borrow(x: Option<&i32>) {
}
// CHECK: @option_borrow_mut({{i32\*|ptr}} noalias noundef align 4 dereferenceable_or_null(4) %x)
// CHECK: @option_borrow_mut(ptr noalias noundef align 4 dereferenceable_or_null(4) %x)
#[no_mangle]
pub fn option_borrow_mut(x: Option<&mut i32>) {
}
// CHECK: @raw_struct({{%S\*|ptr}} noundef %_1)
// CHECK: @raw_struct(ptr noundef %_1)
#[no_mangle]
pub fn raw_struct(_: *const S) {
}
// CHECK: @raw_option_nonnull_struct({{i32\*|ptr}} noundef %_1)
// CHECK: @raw_option_nonnull_struct(ptr noundef %_1)
#[no_mangle]
pub fn raw_option_nonnull_struct(_: Option<NonNull<S>>) {
}
@ -176,19 +176,19 @@ pub fn raw_option_nonnull_struct(_: Option<NonNull<S>>) {
// `Box` can get deallocated during execution of the function, so it should
// not get `dereferenceable`.
// CHECK: noundef nonnull align 4 {{i32\*|ptr}} @_box({{i32\*|ptr}} noalias noundef nonnull align 4 %x)
// CHECK: noundef nonnull align 4 ptr @_box(ptr noalias noundef nonnull align 4 %x)
#[no_mangle]
pub fn _box(x: Box<i32>) -> Box<i32> {
x
}
// CHECK: noundef nonnull align 4 {{i32\*|ptr}} @notunpin_box({{i32\*|ptr}} noundef nonnull align 4 %x)
// CHECK: noundef nonnull align 4 ptr @notunpin_box(ptr noundef nonnull align 4 %x)
#[no_mangle]
pub fn notunpin_box(x: Box<NotUnpin>) -> Box<NotUnpin> {
x
}
// CHECK: @struct_return({{%S\*|ptr}} noalias nocapture noundef sret(%S) align 4 dereferenceable(32){{( %_0)?}})
// CHECK: @struct_return(ptr noalias nocapture noundef sret(%S) align 4 dereferenceable(32){{( %_0)?}})
#[no_mangle]
pub fn struct_return() -> S {
S {
@ -202,68 +202,68 @@ pub fn struct_return() -> S {
pub fn helper(_: usize) {
}
// CHECK: @slice({{\[0 x i8\]\*|ptr}} noalias noundef nonnull readonly align 1 %_1.0, [[USIZE]] noundef %_1.1)
// CHECK: @slice(ptr noalias noundef nonnull readonly align 1 %_1.0, [[USIZE]] noundef %_1.1)
// FIXME #25759 This should also have `nocapture`
#[no_mangle]
pub fn slice(_: &[u8]) {
}
// CHECK: @mutable_slice({{\[0 x i8\]\*|ptr}} noalias noundef nonnull align 1 %_1.0, [[USIZE]] noundef %_1.1)
// CHECK: @mutable_slice(ptr noalias noundef nonnull align 1 %_1.0, [[USIZE]] noundef %_1.1)
// FIXME #25759 This should also have `nocapture`
#[no_mangle]
pub fn mutable_slice(_: &mut [u8]) {
}
// CHECK: @unsafe_slice({{\[0 x i16\]\*|ptr}} noundef nonnull align 2 %_1.0, [[USIZE]] noundef %_1.1)
// CHECK: @unsafe_slice(ptr noundef nonnull align 2 %_1.0, [[USIZE]] noundef %_1.1)
// unsafe interior means this isn't actually readonly and there may be aliases ...
#[no_mangle]
pub fn unsafe_slice(_: &[UnsafeInner]) {
}
// CHECK: @raw_slice({{\[0 x i8\]\*|ptr}} noundef %_1.0, [[USIZE]] noundef %_1.1)
// CHECK: @raw_slice(ptr noundef %_1.0, [[USIZE]] noundef %_1.1)
#[no_mangle]
pub fn raw_slice(_: *const [u8]) {
}
// CHECK: @str({{\[0 x i8\]\*|ptr}} noalias noundef nonnull readonly align 1 %_1.0, [[USIZE]] noundef %_1.1)
// CHECK: @str(ptr noalias noundef nonnull readonly align 1 %_1.0, [[USIZE]] noundef %_1.1)
// FIXME #25759 This should also have `nocapture`
#[no_mangle]
pub fn str(_: &[u8]) {
}
// CHECK: @trait_borrow({{\{\}\*|ptr}} noundef nonnull align 1 %_1.0, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}) %_1.1)
// CHECK: @trait_borrow(ptr noundef nonnull align 1 %_1.0, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}) %_1.1)
// FIXME #25759 This should also have `nocapture`
#[no_mangle]
pub fn trait_borrow(_: &dyn Drop) {
}
// CHECK: @option_trait_borrow({{i8\*|ptr}} noundef align 1 %x.0, {{i8\*|ptr}} %x.1)
// CHECK: @option_trait_borrow(ptr noundef align 1 %x.0, ptr %x.1)
#[no_mangle]
pub fn option_trait_borrow(x: Option<&dyn Drop>) {
}
// CHECK: @option_trait_borrow_mut({{i8\*|ptr}} noundef align 1 %x.0, {{i8\*|ptr}} %x.1)
// CHECK: @option_trait_borrow_mut(ptr noundef align 1 %x.0, ptr %x.1)
#[no_mangle]
pub fn option_trait_borrow_mut(x: Option<&mut dyn Drop>) {
}
// CHECK: @trait_raw({{\{\}\*|ptr}} noundef %_1.0, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}) %_1.1)
// CHECK: @trait_raw(ptr noundef %_1.0, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}) %_1.1)
#[no_mangle]
pub fn trait_raw(_: *const dyn Drop) {
}
// CHECK: @trait_box({{\{\}\*|ptr}} noalias noundef nonnull align 1{{( %0)?}}, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}){{( %1)?}})
// CHECK: @trait_box(ptr noalias noundef nonnull align 1{{( %0)?}}, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}){{( %1)?}})
#[no_mangle]
pub fn trait_box(_: Box<dyn Drop + Unpin>) {
}
// CHECK: { {{i8\*|ptr}}, {{i8\*|ptr}} } @trait_option({{i8\*|ptr}} noalias noundef align 1 %x.0, {{i8\*|ptr}} %x.1)
// CHECK: { ptr, ptr } @trait_option(ptr noalias noundef align 1 %x.0, ptr %x.1)
#[no_mangle]
pub fn trait_option(x: Option<Box<dyn Drop + Unpin>>) -> Option<Box<dyn Drop + Unpin>> {
x
}
// CHECK: { {{\[0 x i16\]\*|ptr}}, [[USIZE]] } @return_slice({{\[0 x i16\]\*|ptr}} noalias noundef nonnull readonly align 2 %x.0, [[USIZE]] noundef %x.1)
// CHECK: { ptr, [[USIZE]] } @return_slice(ptr noalias noundef nonnull readonly align 2 %x.0, [[USIZE]] noundef %x.1)
#[no_mangle]
pub fn return_slice(x: &[u16]) -> &[u16] {
x
@ -281,7 +281,7 @@ pub fn enum_id_2(x: Option<u8>) -> Option<u8> {
x
}
// CHECK: { {{\{\}\*|ptr}}, {{.+}} } @dyn_star({{\{\}\*|ptr}} noundef %x.0, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}) %x.1)
// CHECK: { ptr, {{.+}} } @dyn_star(ptr noundef %x.0, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}) %x.1)
// Expect an ABI something like `{ {}*, [3 x i64]* }`, but that's hard to match on generically,
// so do like the `trait_box` test and just match on `{{.+}}` for the vtable.
#[no_mangle]

View File

@ -7,6 +7,6 @@
#[no_mangle]
pub fn mask_ptr(ptr: *const u16, mask: usize) -> *const u16 {
// CHECK: call
// CHECK-SAME: @llvm.ptrmask.{{p0|p0i8}}.[[WORD]]({{ptr|i8\*}} {{%ptr|%1}}, [[WORD]] %mask)
// CHECK-SAME: @llvm.ptrmask.{{p0|p0i8}}.[[WORD]](ptr {{%ptr|%1}}, [[WORD]] %mask)
core::intrinsics::ptr_mask(ptr, mask)
}

View File

@ -6,7 +6,7 @@
#[no_mangle]
pub fn a(a: &mut u32, b: u32) {
// CHECK-LABEL: define{{.*}}void @a
// CHECK: store i32 %b, {{i32\*|ptr}} %a, align 4, !nontemporal
// CHECK: store i32 %b, ptr %a, align 4, !nontemporal
unsafe {
std::intrinsics::nontemporal_store(a, b);
}

View File

@ -1,5 +1,4 @@
// compile-flags: -O -C no-prepopulate-passes
// min-llvm-version: 15.0 (because we're using opaque pointers)
#![crate_type = "lib"]
#![feature(core_intrinsics)]

View File

@ -2,7 +2,6 @@
// [OPT] compile-flags: -C opt-level=3 -C no-prepopulate-passes
// [DBG] compile-flags: -C opt-level=0 -C no-prepopulate-passes
// only-64bit (so I don't need to worry about usize)
// min-llvm-version: 15.0 # this test assumes `ptr`s
#![crate_type = "lib"]

View File

@ -1,6 +1,5 @@
// compile-flags: -O -C no-prepopulate-passes
// only-x86_64 (it's using arch-specific types)
// min-llvm-version: 15.0 # this test assumes `ptr`s
#![crate_type = "lib"]

View File

@ -1,6 +1,5 @@
// compile-flags: -O -C no-prepopulate-passes
// only-64bit (so I don't need to worry about usize)
// min-llvm-version: 15.0 # this test assumes `ptr`s
#![crate_type = "lib"]
#![feature(core_intrinsics)]

View File

@ -1,6 +1,5 @@
// compile-flags: --crate-type=lib -O -Cdebuginfo=2 -Cno-prepopulate-passes -Zmir-enable-passes=-ScalarReplacementOfAggregates
// MIR SROA will decompose the closure
// min-llvm-version: 15.0 # this test uses opaque pointer notation
#![feature(stmt_expr_attributes)]
pub struct S([usize; 8]);
@ -16,8 +15,8 @@ pub fn outer_function(x: S, y: S) -> usize {
// Check that we do not attempt to load from the spilled arg before it is assigned to
// when generating debuginfo.
// CHECK-LABEL: @outer_function
// CHECK: [[spill:%.*]] = alloca %"[closure@{{.*.rs}}:10:23: 10:25]"
// CHECK-NOT: [[ptr_tmp:%.*]] = getelementptr inbounds %"[closure@{{.*.rs}}:10:23: 10:25]", ptr [[spill]]
// CHECK: [[spill:%.*]] = alloca %"[closure@{{.*.rs}}:9:23: 9:25]"
// CHECK-NOT: [[ptr_tmp:%.*]] = getelementptr inbounds %"[closure@{{.*.rs}}:9:23: 9:25]", ptr [[spill]]
// CHECK-NOT: [[load:%.*]] = load ptr, ptr
// CHECK: call void @llvm.lifetime.start{{.*}}({{.*}}, ptr [[spill]])
// CHECK: [[inner:%.*]] = getelementptr inbounds %"{{.*}}", ptr [[spill]]

View File

@ -12,11 +12,11 @@
pub fn is_empty_1(xs: Iter<f32>) -> bool {
// CHECK-LABEL: @is_empty_1(
// CHECK-NEXT: start:
// CHECK-NEXT: [[A:%.*]] = icmp ne {{i32\*|ptr}} {{%xs.0|%xs.1}}, null
// CHECK-NEXT: [[A:%.*]] = icmp ne ptr {{%xs.0|%xs.1}}, null
// CHECK-NEXT: tail call void @llvm.assume(i1 [[A]])
// The order between %xs.0 and %xs.1 on the next line doesn't matter
// and different LLVM versions produce different order.
// CHECK-NEXT: [[B:%.*]] = icmp eq {{i32\*|ptr}} {{%xs.0, %xs.1|%xs.1, %xs.0}}
// CHECK-NEXT: [[B:%.*]] = icmp eq ptr {{%xs.0, %xs.1|%xs.1, %xs.0}}
// CHECK-NEXT: ret i1 [[B:%.*]]
{xs}.next().is_none()
}
@ -25,11 +25,11 @@ pub fn is_empty_1(xs: Iter<f32>) -> bool {
pub fn is_empty_2(xs: Iter<f32>) -> bool {
// CHECK-LABEL: @is_empty_2
// CHECK-NEXT: start:
// CHECK-NEXT: [[C:%.*]] = icmp ne {{i32\*|ptr}} {{%xs.0|%xs.1}}, null
// CHECK-NEXT: [[C:%.*]] = icmp ne ptr {{%xs.0|%xs.1}}, null
// CHECK-NEXT: tail call void @llvm.assume(i1 [[C]])
// The order between %xs.0 and %xs.1 on the next line doesn't matter
// and different LLVM versions produce different order.
// CHECK-NEXT: [[D:%.*]] = icmp eq {{i32\*|ptr}} {{%xs.0, %xs.1|%xs.1, %xs.0}}
// CHECK-NEXT: [[D:%.*]] = icmp eq ptr {{%xs.0, %xs.1|%xs.1, %xs.0}}
// CHECK-NEXT: ret i1 [[D:%.*]]
xs.map(|&x| x).next().is_none()
}

View File

@ -11,7 +11,7 @@ pub struct Foo<T> {
// The load from bar.1 should have alignment 4. Not checking
// other loads here, as the alignment will be platform-dependent.
// CHECK: %{{.+}} = load i32, {{i32\*|ptr}} %{{.+}}, align 4
// CHECK: %{{.+}} = load i32, ptr %{{.+}}, align 4
#[no_mangle]
pub fn test(x: Foo<(i32, i32)>) -> (i32, i32) {
x.bar

View File

@ -11,7 +11,7 @@ pub struct Foo<T> {
// The store writing to bar.1 should have alignment 4. Not checking
// other stores here, as the alignment will be platform-dependent.
// CHECK: store i32 [[TMP1:%.+]], {{i32\*|ptr}} [[TMP2:%.+]], align 4
// CHECK: store i32 [[TMP1:%.+]], ptr [[TMP2:%.+]], align 4
#[no_mangle]
pub fn test(x: (i32, i32)) -> Foo<(i32, i32)> {
Foo { foo: 0, bar: x }

View File

@ -8,10 +8,10 @@ pub struct S {
}
// CHECK-LABEL: @test1
// CHECK: store i32 0, {{i32\*|ptr}} %{{.+}}, align 16
// CHECK: store i32 1, {{i32\*|ptr}} %{{.+}}, align 4
// CHECK: store i32 2, {{i32\*|ptr}} %{{.+}}, align 8
// CHECK: store i32 3, {{i32\*|ptr}} %{{.+}}, align 4
// CHECK: store i32 0, ptr %{{.+}}, align 16
// CHECK: store i32 1, ptr %{{.+}}, align 4
// CHECK: store i32 2, ptr %{{.+}}, align 8
// CHECK: store i32 3, ptr %{{.+}}, align 4
#[no_mangle]
pub fn test1(s: &mut S) {
s.arr[0] = 0;
@ -21,7 +21,7 @@ pub fn test1(s: &mut S) {
}
// CHECK-LABEL: @test2
// CHECK: store i32 4, {{i32\*|ptr}} %{{.+}}, align 4
// CHECK: store i32 4, ptr %{{.+}}, align 4
#[allow(unconditional_panic)]
#[no_mangle]
pub fn test2(s: &mut S) {
@ -29,14 +29,14 @@ pub fn test2(s: &mut S) {
}
// CHECK-LABEL: @test3
// CHECK: store i32 5, {{i32\*|ptr}} %{{.+}}, align 4
// CHECK: store i32 5, ptr %{{.+}}, align 4
#[no_mangle]
pub fn test3(s: &mut S, i: usize) {
s.arr[i] = 5;
}
// CHECK-LABEL: @test4
// CHECK: store i32 6, {{i32\*|ptr}} %{{.+}}, align 4
// CHECK: store i32 6, ptr %{{.+}}, align 4
#[no_mangle]
pub fn test4(s: &mut S) {
s.arr = [6; 4];

View File

@ -16,6 +16,6 @@
// Ensure that emit arguments of the correct type.
pub unsafe fn test_call_variadic() {
// CHECK: call void (i32, ...) @variadic_fn(i32 0, i8 {{.*}}, {{%Bar\*|ptr}} {{.*}})
// CHECK: call void (i32, ...) @variadic_fn(i32 0, i8 {{.*}}, ptr {{.*}})
variadic_fn(0, Foo(0), Bar(0, 0, 0))
}

View File

@ -1,4 +1,3 @@
// min-llvm-version: 15.0.0
// compile-flags: -O
#![crate_type = "lib"]

View File

@ -1,4 +1,3 @@
// min-llvm-version: 15.0
// only-64bit llvm appears to use stores instead of memset on 32bit
// compile-flags: -C opt-level=3 -Z merge-functions=disabled

View File

@ -1,4 +1,3 @@
// min-llvm-version: 15.0
// compile-flags: -O
#![crate_type = "lib"]

View File

@ -3,7 +3,6 @@
// in some situations, see https://github.com/rust-lang/rust/issues/96497#issuecomment-1112865218
// compile-flags: -O
// min-llvm-version: 15.0
#![crate_type="lib"]

View File

@ -1,4 +1,3 @@
// min-llvm-version: 15.0.0
// ignore-debug: The debug assertions get in the way
// compile-flags: -O

View File

@ -8,7 +8,7 @@ pub fn test() {
let a = 0u8;
&a; // keep variable in an alloca
// CHECK: call void @llvm.lifetime.start{{.*}}(i{{[0-9 ]+}}, {{i8\*|ptr}} %a)
// CHECK: call void @llvm.lifetime.start{{.*}}(i{{[0-9 ]+}}, ptr %a)
{
let b = &Some(a);
@ -26,9 +26,9 @@ pub fn test() {
let c = 1u8;
&c; // keep variable in an alloca
// CHECK: call void @llvm.lifetime.start{{.*}}(i{{[0-9 ]+}}, {{i8\*|ptr}} %c)
// CHECK: call void @llvm.lifetime.start{{.*}}(i{{[0-9 ]+}}, ptr %c)
// CHECK: call void @llvm.lifetime.end{{.*}}(i{{[0-9 ]+}}, {{i8\*|ptr}} %c)
// CHECK: call void @llvm.lifetime.end{{.*}}(i{{[0-9 ]+}}, ptr %c)
// CHECK: call void @llvm.lifetime.end{{.*}}(i{{[0-9 ]+}}, {{i8\*|ptr}} %a)
// CHECK: call void @llvm.lifetime.end{{.*}}(i{{[0-9 ]+}}, ptr %a)
}

View File

@ -28,22 +28,22 @@ pub fn ptr_alignment_helper(x: &&()) {}
// CHECK-LABEL: @load_ref
#[no_mangle]
pub fn load_ref<'a>(x: &&'a i32) -> &'a i32 {
// CHECK: load {{i32\*|ptr}}, {{i32\*\*|ptr}} %x, align [[PTR_ALIGNMENT]], !nonnull !{{[0-9]+}}, !align ![[ALIGN_4_META:[0-9]+]], !noundef !{{[0-9]+}}
// CHECK: load ptr, ptr %x, align [[PTR_ALIGNMENT]], !nonnull !{{[0-9]+}}, !align ![[ALIGN_4_META:[0-9]+]], !noundef !{{[0-9]+}}
*x
}
// CHECK-LABEL: @load_ref_higher_alignment
#[no_mangle]
pub fn load_ref_higher_alignment<'a>(x: &&'a Align16) -> &'a Align16 {
// CHECK: load {{%Align16\*|i128\*|ptr}}, {{%Align16\*\*|i128\*\*|ptr}} %x, align [[PTR_ALIGNMENT]], !nonnull !{{[0-9]+}}, !align ![[ALIGN_16_META:[0-9]+]], !noundef !{{[0-9]+}}
// CHECK: load ptr, ptr %x, align [[PTR_ALIGNMENT]], !nonnull !{{[0-9]+}}, !align ![[ALIGN_16_META:[0-9]+]], !noundef !{{[0-9]+}}
*x
}
// CHECK-LABEL: @load_scalar_pair
#[no_mangle]
pub fn load_scalar_pair<'a>(x: &(&'a i32, &'a Align16)) -> (&'a i32, &'a Align16) {
// CHECK: load {{i32\*|ptr}}, {{i32\*\*|ptr}} %{{.+}}, align [[PTR_ALIGNMENT]], !nonnull !{{[0-9]+}}, !align ![[ALIGN_4_META]], !noundef !{{[0-9]+}}
// CHECK: load {{i64\*|ptr}}, {{i64\*\*|ptr}} %{{.+}}, align [[PTR_ALIGNMENT]], !nonnull !{{[0-9]+}}, !align ![[ALIGN_16_META]], !noundef !{{[0-9]+}}
// CHECK: load ptr, ptr %{{.+}}, align [[PTR_ALIGNMENT]], !nonnull !{{[0-9]+}}, !align ![[ALIGN_4_META]], !noundef !{{[0-9]+}}
// CHECK: load ptr, ptr %{{.+}}, align [[PTR_ALIGNMENT]], !nonnull !{{[0-9]+}}, !align ![[ALIGN_16_META]], !noundef !{{[0-9]+}}
*x
}
@ -51,70 +51,70 @@ pub fn load_scalar_pair<'a>(x: &(&'a i32, &'a Align16)) -> (&'a i32, &'a Align16
#[no_mangle]
pub fn load_raw_pointer<'a>(x: &*const i32) -> *const i32 {
// loaded raw pointer should not have !nonnull or !align metadata
// CHECK: load {{i32\*|ptr}}, {{i32\*\*|ptr}} %x, align [[PTR_ALIGNMENT]], !noundef ![[NOUNDEF:[0-9]+]]{{$}}
// CHECK: load ptr, ptr %x, align [[PTR_ALIGNMENT]], !noundef ![[NOUNDEF:[0-9]+]]{{$}}
*x
}
// CHECK-LABEL: @load_box
#[no_mangle]
pub fn load_box<'a>(x: Box<Box<i32>>) -> Box<i32> {
// CHECK: load {{i32\*|ptr}}, {{i32\*\*|ptr}} %{{.*}}, align [[PTR_ALIGNMENT]], !nonnull !{{[0-9]+}}, !align ![[ALIGN_4_META]], !noundef !{{[0-9]+}}
// CHECK: load ptr, ptr %{{.*}}, align [[PTR_ALIGNMENT]], !nonnull !{{[0-9]+}}, !align ![[ALIGN_4_META]], !noundef !{{[0-9]+}}
*x
}
// CHECK-LABEL: @load_bool
#[no_mangle]
pub fn load_bool(x: &bool) -> bool {
// CHECK: load i8, {{i8\*|ptr}} %x, align 1, !range ![[BOOL_RANGE:[0-9]+]], !noundef !{{[0-9]+}}
// CHECK: load i8, ptr %x, align 1, !range ![[BOOL_RANGE:[0-9]+]], !noundef !{{[0-9]+}}
*x
}
// CHECK-LABEL: @load_maybeuninit_bool
#[no_mangle]
pub fn load_maybeuninit_bool(x: &MaybeUninit<bool>) -> MaybeUninit<bool> {
// CHECK: load i8, {{i8\*|ptr}} %x, align 1{{$}}
// CHECK: load i8, ptr %x, align 1{{$}}
*x
}
// CHECK-LABEL: @load_enum_bool
#[no_mangle]
pub fn load_enum_bool(x: &MyBool) -> MyBool {
// CHECK: load i8, {{i8\*|ptr}} %x, align 1, !range ![[BOOL_RANGE]], !noundef !{{[0-9]+}}
// CHECK: load i8, ptr %x, align 1, !range ![[BOOL_RANGE]], !noundef !{{[0-9]+}}
*x
}
// CHECK-LABEL: @load_maybeuninit_enum_bool
#[no_mangle]
pub fn load_maybeuninit_enum_bool(x: &MaybeUninit<MyBool>) -> MaybeUninit<MyBool> {
// CHECK: load i8, {{i8\*|ptr}} %x, align 1{{$}}
// CHECK: load i8, ptr %x, align 1{{$}}
*x
}
// CHECK-LABEL: @load_int
#[no_mangle]
pub fn load_int(x: &u16) -> u16 {
// CHECK: load i16, {{i16\*|ptr}} %x, align 2, !noundef ![[NOUNDEF]]{{$}}
// CHECK: load i16, ptr %x, align 2, !noundef ![[NOUNDEF]]{{$}}
*x
}
// CHECK-LABEL: @load_nonzero_int
#[no_mangle]
pub fn load_nonzero_int(x: &NonZeroU16) -> NonZeroU16 {
// CHECK: load i16, {{i16\*|ptr}} %x, align 2, !range ![[NONZEROU16_RANGE:[0-9]+]], !noundef !{{[0-9]+}}
// CHECK: load i16, ptr %x, align 2, !range ![[NONZEROU16_RANGE:[0-9]+]], !noundef !{{[0-9]+}}
*x
}
// CHECK-LABEL: @load_option_nonzero_int
#[no_mangle]
pub fn load_option_nonzero_int(x: &Option<NonZeroU16>) -> Option<NonZeroU16> {
// CHECK: load i16, {{i16\*|ptr}} %x, align 2, !noundef ![[NOUNDEF]]{{$}}
// CHECK: load i16, ptr %x, align 2, !noundef ![[NOUNDEF]]{{$}}
*x
}
// CHECK-LABEL: @borrow
#[no_mangle]
pub fn borrow(x: &i32) -> &i32 {
// CHECK: load {{i32\*|ptr}}, {{i32\*\*|ptr}} %x{{.*}}, !nonnull
// CHECK: load ptr, ptr %x{{.*}}, !nonnull
&x; // keep variable in an alloca
x
}
@ -122,7 +122,7 @@ pub fn borrow(x: &i32) -> &i32 {
// CHECK-LABEL: @_box
#[no_mangle]
pub fn _box(x: Box<i32>) -> i32 {
// CHECK: load {{i32\*|ptr}}, {{i32\*\*|ptr}} %x{{.*}}, align [[PTR_ALIGNMENT]]
// CHECK: load ptr, ptr %x{{.*}}, align [[PTR_ALIGNMENT]]
*x
}
@ -131,7 +131,7 @@ pub fn _box(x: Box<i32>) -> i32 {
// dependent alignment
#[no_mangle]
pub fn small_array_alignment(x: [i8; 4]) -> [i8; 4] {
// CHECK: [[VAR:%[0-9]+]] = load i32, {{i32\*|ptr}} %{{.*}}, align 1
// CHECK: [[VAR:%[0-9]+]] = load i32, ptr %{{.*}}, align 1
// CHECK: ret i32 [[VAR]]
x
}
@ -141,7 +141,7 @@ pub fn _box(x: Box<i32>) -> i32 {
// dependent alignment
#[no_mangle]
pub fn small_struct_alignment(x: Bytes) -> Bytes {
// CHECK: [[VAR:%[0-9]+]] = load i32, {{i32\*|ptr}} %{{.*}}, align 1
// CHECK: [[VAR:%[0-9]+]] = load i32, ptr %{{.*}}, align 1
// CHECK: ret i32 [[VAR]]
x
}

View File

@ -20,13 +20,13 @@ pub fn exhaustive_match(e: E) -> u8 {
// CHECK-NEXT: unreachable
//
// CHECK: [[A]]:
// CHECK-NEXT: store i8 0, {{i8\*|ptr}} %_0, align 1
// CHECK-NEXT: store i8 0, ptr %_0, align 1
// CHECK-NEXT: br label %[[EXIT:[a-zA-Z0-9_]+]]
// CHECK: [[B]]:
// CHECK-NEXT: store i8 1, {{i8\*|ptr}} %_0, align 1
// CHECK-NEXT: store i8 1, ptr %_0, align 1
// CHECK-NEXT: br label %[[EXIT]]
// CHECK: [[C]]:
// CHECK-NEXT: store i8 2, {{i8\*|ptr}} %_0, align 1
// CHECK-NEXT: store i8 2, ptr %_0, align 1
// CHECK-NEXT: br label %[[EXIT]]
match e {
E::A => 0,

View File

@ -25,9 +25,9 @@ pub fn replace_big(dst: &mut Big, src: Big) -> Big {
// For a large type, we expect exactly three `memcpy`s
// CHECK-LABEL: define internal void @{{.+}}mem{{.+}}replace{{.+}}sret(%Big)
// CHECK-NOT: call void @llvm.memcpy
// CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 8 %result, {{i8\*|ptr}} align 8 %dest, i{{.*}} 56, i1 false)
// CHECK: call void @llvm.memcpy.{{.+}}(ptr align 8 %result, ptr align 8 %dest, i{{.*}} 56, i1 false)
// CHECK-NOT: call void @llvm.memcpy
// CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 8 %dest, {{i8\*|ptr}} align 8 %src, i{{.*}} 56, i1 false)
// CHECK: call void @llvm.memcpy.{{.+}}(ptr align 8 %dest, ptr align 8 %src, i{{.*}} 56, i1 false)
// CHECK-NOT: call void @llvm.memcpy
// CHECK-NOT: call void @llvm.memcpy

View File

@ -1,5 +1,4 @@
// compile-flags: -O -C no-prepopulate-passes
// min-llvm-version: 15.0 (for opaque pointers)
// only-x86_64 (to not worry about usize differing)
// ignore-debug (the debug assertions get in the way)

View File

@ -7,7 +7,7 @@
#[no_mangle]
pub fn f(a: T, b: fn(_: T, _: T)) {
// CHECK: call void @llvm.memcpy.{{.*}}({{i8\*|ptr}} align 1 %{{.*}}, {{i8\*|ptr}} align 1 %{{.*}}, {{.*}} 256, i1 false)
// CHECK-NOT: call void @llvm.memcpy.{{.*}}({{i8\*|ptr}} align 1 %{{.*}}, {{i8\*|ptr}} align 1 %{{.*}}, {{.*}} 256, i1 false)
// CHECK: call void @llvm.memcpy.{{.*}}(ptr align 1 %{{.*}}, ptr align 1 %{{.*}}, {{.*}} 256, i1 false)
// CHECK-NOT: call void @llvm.memcpy.{{.*}}(ptr align 1 %{{.*}}, ptr align 1 %{{.*}}, {{.*}} 256, i1 false)
b(a, a)
}

View File

@ -32,7 +32,7 @@ pub fn non_zero_signed_eq(l: Option<NonZeroI64>, r: Option<NonZeroI64>) -> bool
#[no_mangle]
pub fn non_null_eq(l: Option<NonNull<u8>>, r: Option<NonNull<u8>>) -> bool {
// CHECK: start:
// CHECK-NEXT: icmp eq {{(i8\*|ptr)}}
// CHECK-NEXT: icmp eq ptr
// CHECK-NEXT: ret i1
l == r
}

View File

@ -18,8 +18,8 @@ pub struct Packed2 {
// CHECK-LABEL: @write_pkd1
#[no_mangle]
pub fn write_pkd1(pkd: &mut Packed1) -> u32 {
// CHECK: %{{.*}} = load i32, {{i32\*|ptr}} %{{.*}}, align 1
// CHECK: store i32 42, {{i32\*|ptr}} %{{.*}}, align 1
// CHECK: %{{.*}} = load i32, ptr %{{.*}}, align 1
// CHECK: store i32 42, ptr %{{.*}}, align 1
let result = pkd.data;
pkd.data = 42;
result
@ -28,8 +28,8 @@ pub fn write_pkd1(pkd: &mut Packed1) -> u32 {
// CHECK-LABEL: @write_pkd2
#[no_mangle]
pub fn write_pkd2(pkd: &mut Packed2) -> u32 {
// CHECK: %{{.*}} = load i32, {{i32\*|ptr}} %{{.*}}, align 2
// CHECK: store i32 42, {{i32\*|ptr}} %{{.*}}, align 2
// CHECK: %{{.*}} = load i32, ptr %{{.*}}, align 2
// CHECK: store i32 42, ptr %{{.*}}, align 2
let result = pkd.data;
pkd.data = 42;
result
@ -52,8 +52,8 @@ pub struct BigPacked2 {
#[no_mangle]
pub fn call_pkd1(f: fn() -> Array) -> BigPacked1 {
// CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca %Array
// CHECK: call void %{{.*}}({{%Array\*|ptr}} noalias nocapture noundef sret{{.*}} dereferenceable(32) [[ALLOCA]])
// CHECK: call void @llvm.memcpy.{{.*}}({{i8\*|ptr}} align 1 %{{.*}}, {{i8\*|ptr}} align 4 %{{.*}}, i{{[0-9]+}} 32, i1 false)
// CHECK: call void %{{.*}}(ptr noalias nocapture noundef sret{{.*}} dereferenceable(32) [[ALLOCA]])
// CHECK: call void @llvm.memcpy.{{.*}}(ptr align 1 %{{.*}}, ptr align 4 %{{.*}}, i{{[0-9]+}} 32, i1 false)
// check that calls whose destination is a field of a packed struct
// go through an alloca rather than calling the function with an
// unaligned destination.
@ -64,8 +64,8 @@ pub fn call_pkd1(f: fn() -> Array) -> BigPacked1 {
#[no_mangle]
pub fn call_pkd2(f: fn() -> Array) -> BigPacked2 {
// CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca %Array
// CHECK: call void %{{.*}}({{%Array\*|ptr}} noalias nocapture noundef sret{{.*}} dereferenceable(32) [[ALLOCA]])
// CHECK: call void @llvm.memcpy.{{.*}}({{i8\*|ptr}} align 2 %{{.*}}, {{i8\*|ptr}} align 4 %{{.*}}, i{{[0-9]+}} 32, i1 false)
// CHECK: call void %{{.*}}(ptr noalias nocapture noundef sret{{.*}} dereferenceable(32) [[ALLOCA]])
// CHECK: call void @llvm.memcpy.{{.*}}(ptr align 2 %{{.*}}, ptr align 4 %{{.*}}, i{{[0-9]+}} 32, i1 false)
// check that calls whose destination is a field of a packed struct
// go through an alloca rather than calling the function with an
// unaligned destination.
@ -73,9 +73,9 @@ pub fn call_pkd2(f: fn() -> Array) -> BigPacked2 {
}
// CHECK-LABEL: @write_packed_array1
// CHECK: store i32 0, {{i32\*|ptr}} %{{.+}}, align 1
// CHECK: store i32 1, {{i32\*|ptr}} %{{.+}}, align 1
// CHECK: store i32 2, {{i32\*|ptr}} %{{.+}}, align 1
// CHECK: store i32 0, ptr %{{.+}}, align 1
// CHECK: store i32 1, ptr %{{.+}}, align 1
// CHECK: store i32 2, ptr %{{.+}}, align 1
#[no_mangle]
pub fn write_packed_array1(p: &mut BigPacked1) {
p.data.0[0] = 0;
@ -84,9 +84,9 @@ pub fn write_packed_array1(p: &mut BigPacked1) {
}
// CHECK-LABEL: @write_packed_array2
// CHECK: store i32 0, {{i32\*|ptr}} %{{.+}}, align 2
// CHECK: store i32 1, {{i32\*|ptr}} %{{.+}}, align 2
// CHECK: store i32 2, {{i32\*|ptr}} %{{.+}}, align 2
// CHECK: store i32 0, ptr %{{.+}}, align 2
// CHECK: store i32 1, ptr %{{.+}}, align 2
// CHECK: store i32 2, ptr %{{.+}}, align 2
#[no_mangle]
pub fn write_packed_array2(p: &mut BigPacked2) {
p.data.0[0] = 0;
@ -95,14 +95,14 @@ pub fn write_packed_array2(p: &mut BigPacked2) {
}
// CHECK-LABEL: @repeat_packed_array1
// CHECK: store i32 42, {{i32\*|ptr}} %{{.+}}, align 1
// CHECK: store i32 42, ptr %{{.+}}, align 1
#[no_mangle]
pub fn repeat_packed_array1(p: &mut BigPacked1) {
p.data.0 = [42; 8];
}
// CHECK-LABEL: @repeat_packed_array2
// CHECK: store i32 42, {{i32\*|ptr}} %{{.+}}, align 2
// CHECK: store i32 42, ptr %{{.+}}, align 2
#[no_mangle]
pub fn repeat_packed_array2(p: &mut BigPacked2) {
p.data.0 = [42; 8];
@ -119,14 +119,14 @@ pub fn repeat_packed_array2(p: &mut BigPacked2) {
// CHECK-LABEL: @pkd1_pair
#[no_mangle]
pub fn pkd1_pair(pair1: &mut Packed1Pair, pair2: &mut Packed1Pair) {
// CHECK: call void @llvm.memcpy.{{.*}}({{i8\*|ptr}} align 1 %{{.*}}, {{i8\*|ptr}} align 1 %{{.*}}, i{{[0-9]+}} 5, i1 false)
// CHECK: call void @llvm.memcpy.{{.*}}(ptr align 1 %{{.*}}, ptr align 1 %{{.*}}, i{{[0-9]+}} 5, i1 false)
*pair2 = *pair1;
}
// CHECK-LABEL: @pkd2_pair
#[no_mangle]
pub fn pkd2_pair(pair1: &mut Packed2Pair, pair2: &mut Packed2Pair) {
// CHECK: call void @llvm.memcpy.{{.*}}({{i8\*|ptr}} align 2 %{{.*}}, {{i8\*|ptr}} align 2 %{{.*}}, i{{[0-9]+}} 6, i1 false)
// CHECK: call void @llvm.memcpy.{{.*}}(ptr align 2 %{{.*}}, ptr align 2 %{{.*}}, i{{[0-9]+}} 6, i1 false)
*pair2 = *pair1;
}
@ -141,13 +141,13 @@ pub fn pkd2_pair(pair1: &mut Packed2Pair, pair2: &mut Packed2Pair) {
// CHECK-LABEL: @pkd1_nested_pair
#[no_mangle]
pub fn pkd1_nested_pair(pair1: &mut Packed1NestedPair, pair2: &mut Packed1NestedPair) {
// CHECK: call void @llvm.memcpy.{{.*}}({{i8\*|ptr}} align 1 %{{.*}}, {{i8\*|ptr}} align 1 %{{.*}}, i{{[0-9]+}} 8, i1 false)
// CHECK: call void @llvm.memcpy.{{.*}}(ptr align 1 %{{.*}}, ptr align 1 %{{.*}}, i{{[0-9]+}} 8, i1 false)
*pair2 = *pair1;
}
// CHECK-LABEL: @pkd2_nested_pair
#[no_mangle]
pub fn pkd2_nested_pair(pair1: &mut Packed2NestedPair, pair2: &mut Packed2NestedPair) {
// CHECK: call void @llvm.memcpy.{{.*}}({{i8\*|ptr}} align 2 %{{.*}}, {{i8\*|ptr}} align 2 %{{.*}}, i{{[0-9]+}} 8, i1 false)
// CHECK: call void @llvm.memcpy.{{.*}}(ptr align 2 %{{.*}}, ptr align 2 %{{.*}}, i{{[0-9]+}} 8, i1 false)
*pair2 = *pair1;
}

View File

@ -22,7 +22,7 @@ pub fn test() {
let _s = S;
// Check that the personality slot alloca gets a lifetime start in each cleanup block, not just
// in the first one.
// CHECK: [[SLOT:%[0-9]+]] = alloca { {{i8\*|ptr}}, i32 }
// CHECK: [[SLOT:%[0-9]+]] = alloca { ptr, i32 }
// CHECK-LABEL: cleanup:
// CHECK: call void @llvm.lifetime.start.{{.*}}({{.*}})
// CHECK-LABEL: cleanup1:

View File

@ -13,9 +13,9 @@ pub fn helper(_: usize) {
pub fn ref_dst(s: &[u8]) {
// We used to generate an extra alloca and memcpy to ref the dst, so check that we copy
// directly to the alloca for "x"
// CHECK: [[X0:%[0-9]+]] = getelementptr inbounds { {{\[0 x i8\]\*|ptr}}, [[USIZE]] }, {{.*}} %x, i32 0, i32 0
// CHECK: store {{\[0 x i8\]\*|ptr}} %s.0, {{.*}} [[X0]]
// CHECK: [[X1:%[0-9]+]] = getelementptr inbounds { {{\[0 x i8\]\*|ptr}}, [[USIZE]] }, {{.*}} %x, i32 0, i32 1
// CHECK: [[X0:%[0-9]+]] = getelementptr inbounds { ptr, [[USIZE]] }, {{.*}} %x, i32 0, i32 0
// CHECK: store ptr %s.0, {{.*}} [[X0]]
// CHECK: [[X1:%[0-9]+]] = getelementptr inbounds { ptr, [[USIZE]] }, {{.*}} %x, i32 0, i32 1
// CHECK: store [[USIZE]] %s.1, {{.*}} [[X1]]
let x = &*s;

View File

@ -8,13 +8,13 @@
// CHECK-LABEL: @repeat_take_collect
#[no_mangle]
pub fn repeat_take_collect() -> Vec<u8> {
// CHECK: call void @llvm.memset.{{.+}}({{i8\*|ptr}} {{.*}}align 1{{.*}} %{{.*}}, i8 42, i{{[0-9]+}} 100000, i1 false)
// CHECK: call void @llvm.memset.{{.+}}(ptr {{.*}}align 1{{.*}} %{{.*}}, i8 42, i{{[0-9]+}} 100000, i1 false)
iter::repeat(42).take(100000).collect()
}
// CHECK-LABEL: @repeat_with_take_collect
#[no_mangle]
pub fn repeat_with_take_collect() -> Vec<u8> {
// CHECK: call void @llvm.memset.{{.+}}({{i8\*|ptr}} {{.*}}align 1{{.*}} %{{.*}}, i8 13, i{{[0-9]+}} 12345, i1 false)
// CHECK: call void @llvm.memset.{{.+}}(ptr {{.*}}align 1{{.*}} %{{.*}}, i8 13, i{{[0-9]+}} 12345, i1 false)
iter::repeat_with(|| 13).take(12345).collect()
}

View File

@ -36,19 +36,19 @@ pub enum TeBigS {
Variant(BigS),
}
// CHECK: define{{.*}}void @test_BigS({{%BigS\*|ptr}} [[BIGS_RET_ATTRS1:.*]] sret(%BigS) [[BIGS_RET_ATTRS2:.*]], {{%BigS\*|ptr}} [[BIGS_ARG_ATTRS1:.*]] byval(%BigS) [[BIGS_ARG_ATTRS2:.*]])
// CHECK: define{{.*}}void @test_BigS(ptr [[BIGS_RET_ATTRS1:.*]] sret(%BigS) [[BIGS_RET_ATTRS2:.*]], ptr [[BIGS_ARG_ATTRS1:.*]] byval(%BigS) [[BIGS_ARG_ATTRS2:.*]])
#[no_mangle]
pub extern "C" fn test_BigS(_: BigS) -> BigS { loop {} }
// CHECK: define{{.*}}void @test_TsBigS({{%TsBigS\*|ptr}} [[BIGS_RET_ATTRS1]] sret(%TsBigS) [[BIGS_RET_ATTRS2]], {{%TsBigS\*|ptr}} [[BIGS_ARG_ATTRS1]] byval(%TsBigS) [[BIGS_ARG_ATTRS2:.*]])
// CHECK: define{{.*}}void @test_TsBigS(ptr [[BIGS_RET_ATTRS1]] sret(%TsBigS) [[BIGS_RET_ATTRS2]], ptr [[BIGS_ARG_ATTRS1]] byval(%TsBigS) [[BIGS_ARG_ATTRS2:.*]])
#[no_mangle]
pub extern "C" fn test_TsBigS(_: TsBigS) -> TsBigS { loop {} }
// CHECK: define{{.*}}void @test_TuBigS({{%TuBigS\*|ptr}} [[BIGS_RET_ATTRS1]] sret(%TuBigS) [[BIGS_RET_ATTRS2]], {{%TuBigS\*|ptr}} [[BIGS_ARG_ATTRS1]] byval(%TuBigS) [[BIGS_ARG_ATTRS2:.*]])
// CHECK: define{{.*}}void @test_TuBigS(ptr [[BIGS_RET_ATTRS1]] sret(%TuBigS) [[BIGS_RET_ATTRS2]], ptr [[BIGS_ARG_ATTRS1]] byval(%TuBigS) [[BIGS_ARG_ATTRS2:.*]])
#[no_mangle]
pub extern "C" fn test_TuBigS(_: TuBigS) -> TuBigS { loop {} }
// CHECK: define{{.*}}void @test_TeBigS({{%"TeBigS::Variant"\*|ptr}} [[BIGS_RET_ATTRS1]] sret(%"TeBigS::Variant") [[BIGS_RET_ATTRS2]], {{%"TeBigS::Variant"\*|ptr}} [[BIGS_ARG_ATTRS1]] byval(%"TeBigS::Variant") [[BIGS_ARG_ATTRS2]])
// CHECK: define{{.*}}void @test_TeBigS(ptr [[BIGS_RET_ATTRS1]] sret(%"TeBigS::Variant") [[BIGS_RET_ATTRS2]], ptr [[BIGS_ARG_ATTRS1]] byval(%"TeBigS::Variant") [[BIGS_ARG_ATTRS2]])
#[no_mangle]
pub extern "C" fn test_TeBigS(_: TeBigS) -> TeBigS { loop {} }
@ -72,18 +72,18 @@ pub enum TeBigU {
Variant(BigU),
}
// CHECK: define{{.*}}void @test_BigU({{%BigU\*|ptr}} [[BIGU_RET_ATTRS1:.*]] sret(%BigU) [[BIGU_RET_ATTRS2:.*]], {{%BigU\*|ptr}} [[BIGU_ARG_ATTRS1:.*]] byval(%BigU) [[BIGU_ARG_ATTRS2:.*]])
// CHECK: define{{.*}}void @test_BigU(ptr [[BIGU_RET_ATTRS1:.*]] sret(%BigU) [[BIGU_RET_ATTRS2:.*]], ptr [[BIGU_ARG_ATTRS1:.*]] byval(%BigU) [[BIGU_ARG_ATTRS2:.*]])
#[no_mangle]
pub extern "C" fn test_BigU(_: BigU) -> BigU { loop {} }
// CHECK: define{{.*}}void @test_TsBigU({{%TsBigU\*|ptr}} [[BIGU_RET_ATTRS1:.*]] sret(%TsBigU) [[BIGU_RET_ATTRS2:.*]], {{%TsBigU\*|ptr}} [[BIGU_ARG_ATTRS1]] byval(%TsBigU) [[BIGU_ARG_ATTRS2]])
// CHECK: define{{.*}}void @test_TsBigU(ptr [[BIGU_RET_ATTRS1:.*]] sret(%TsBigU) [[BIGU_RET_ATTRS2:.*]], ptr [[BIGU_ARG_ATTRS1]] byval(%TsBigU) [[BIGU_ARG_ATTRS2]])
#[no_mangle]
pub extern "C" fn test_TsBigU(_: TsBigU) -> TsBigU { loop {} }
// CHECK: define{{.*}}void @test_TuBigU({{%TuBigU\*|ptr}} [[BIGU_RET_ATTRS1]] sret(%TuBigU) [[BIGU_RET_ATTRS2:.*]], {{%TuBigU\*|ptr}} [[BIGU_ARG_ATTRS1]] byval(%TuBigU) [[BIGU_ARG_ATTRS2]])
// CHECK: define{{.*}}void @test_TuBigU(ptr [[BIGU_RET_ATTRS1]] sret(%TuBigU) [[BIGU_RET_ATTRS2:.*]], ptr [[BIGU_ARG_ATTRS1]] byval(%TuBigU) [[BIGU_ARG_ATTRS2]])
#[no_mangle]
pub extern "C" fn test_TuBigU(_: TuBigU) -> TuBigU { loop {} }
// CHECK: define{{.*}}void @test_TeBigU({{%"TeBigU::Variant"\*|ptr}} [[BIGU_RET_ATTRS1]] sret(%"TeBigU::Variant") [[BIGU_RET_ATTRS2:.*]], {{%"TeBigU::Variant"\*|ptr}} [[BIGU_ARG_ATTRS1]] byval(%"TeBigU::Variant") [[BIGU_ARG_ATTRS2]])
// CHECK: define{{.*}}void @test_TeBigU(ptr [[BIGU_RET_ATTRS1]] sret(%"TeBigU::Variant") [[BIGU_RET_ATTRS2:.*]], ptr [[BIGU_ARG_ATTRS1]] byval(%"TeBigU::Variant") [[BIGU_ARG_ATTRS2]])
#[no_mangle]
pub extern "C" fn test_TeBigU(_: TeBigU) -> TeBigU { loop {} }

View File

@ -37,19 +37,19 @@ pub enum TeBigS {
Variant(BigS),
}
// CHECK: define void @test_BigS({{%BigS\*|ptr}} [[BIGS_RET_ATTRS1:.*]] sret(%BigS) [[BIGS_RET_ATTRS2:.*]], [16 x i32]
// CHECK: define void @test_BigS(ptr [[BIGS_RET_ATTRS1:.*]] sret(%BigS) [[BIGS_RET_ATTRS2:.*]], [16 x i32]
#[no_mangle]
pub extern fn test_BigS(_: BigS) -> BigS { loop {} }
// CHECK: define void @test_TsBigS({{%TsBigS\*|ptr}} [[BIGS_RET_ATTRS1]] sret(%TsBigS) [[BIGS_RET_ATTRS2]], [16 x i32]
// CHECK: define void @test_TsBigS(ptr [[BIGS_RET_ATTRS1]] sret(%TsBigS) [[BIGS_RET_ATTRS2]], [16 x i32]
#[no_mangle]
pub extern fn test_TsBigS(_: TsBigS) -> TsBigS { loop {} }
// CHECK: define void @test_TuBigS({{%TuBigS\*|ptr}} [[BIGS_RET_ATTRS1]] sret(%TuBigS) [[BIGS_RET_ATTRS2]], [16 x i32]
// CHECK: define void @test_TuBigS(ptr [[BIGS_RET_ATTRS1]] sret(%TuBigS) [[BIGS_RET_ATTRS2]], [16 x i32]
#[no_mangle]
pub extern fn test_TuBigS(_: TuBigS) -> TuBigS { loop {} }
// CHECK: define void @test_TeBigS({{%"TeBigS::Variant"\*|ptr}} [[BIGS_RET_ATTRS1]] sret(%"TeBigS::Variant") [[BIGS_RET_ATTRS2]], [16 x i32]
// CHECK: define void @test_TeBigS(ptr [[BIGS_RET_ATTRS1]] sret(%"TeBigS::Variant") [[BIGS_RET_ATTRS2]], [16 x i32]
#[no_mangle]
pub extern fn test_TeBigS(_: TeBigS) -> TeBigS { loop {} }
@ -73,18 +73,18 @@ pub enum TeBigU {
Variant(BigU),
}
// CHECK: define void @test_BigU({{%BigU\*|ptr}} [[BIGU_RET_ATTRS1:.*]] sret(%BigU) [[BIGU_RET_ATTRS2:.*]], [16 x i32]
// CHECK: define void @test_BigU(ptr [[BIGU_RET_ATTRS1:.*]] sret(%BigU) [[BIGU_RET_ATTRS2:.*]], [16 x i32]
#[no_mangle]
pub extern fn test_BigU(_: BigU) -> BigU { loop {} }
// CHECK: define void @test_TsBigU({{%TsBigU\*|ptr}} [[BIGU_RET_ATTRS1]] sret(%TsBigU) [[BIGU_RET_ATTRS2]], [16 x i32]
// CHECK: define void @test_TsBigU(ptr [[BIGU_RET_ATTRS1]] sret(%TsBigU) [[BIGU_RET_ATTRS2]], [16 x i32]
#[no_mangle]
pub extern fn test_TsBigU(_: TsBigU) -> TsBigU { loop {} }
// CHECK: define void @test_TuBigU({{%TuBigU\*|ptr}} [[BIGU_RET_ATTRS1]] sret(%TuBigU) [[BIGU_RET_ATTRS2]], [16 x i32]
// CHECK: define void @test_TuBigU(ptr [[BIGU_RET_ATTRS1]] sret(%TuBigU) [[BIGU_RET_ATTRS2]], [16 x i32]
#[no_mangle]
pub extern fn test_TuBigU(_: TuBigU) -> TuBigU { loop {} }
// CHECK: define void @test_TeBigU({{%"TeBigU::Variant"\*|ptr}} [[BIGU_RET_ATTRS1]] sret(%"TeBigU::Variant") [[BIGU_RET_ATTRS2]], [16 x i32]
// CHECK: define void @test_TeBigU(ptr [[BIGU_RET_ATTRS1]] sret(%"TeBigU::Variant") [[BIGU_RET_ATTRS2]], [16 x i32]
#[no_mangle]
pub extern fn test_TeBigU(_: TeBigU) -> TeBigU { loop {} }

View File

@ -26,7 +26,7 @@ pub extern "C" fn test_F32(_: F32) -> F32 { loop {} }
#[repr(transparent)]
pub struct Ptr(*mut u8);
// CHECK: define{{.*}}{{i8\*|ptr}} @test_Ptr({{i8\*|ptr}} noundef %_1)
// CHECK: define{{.*}}ptr @test_Ptr(ptr noundef %_1)
#[no_mangle]
pub extern "C" fn test_Ptr(_: Ptr) -> Ptr { loop {} }
@ -41,7 +41,7 @@ pub extern "C" fn test_WithZst(_: WithZst) -> WithZst { loop {} }
pub struct WithZeroSizedArray(*const f32, [i8; 0]);
// Apparently we use i32* when newtype-unwrapping f32 pointers. Whatever.
// CHECK: define{{.*}}{{i32\*|ptr}} @test_WithZeroSizedArray({{i32\*|ptr}} noundef %_1)
// CHECK: define{{.*}}ptr @test_WithZeroSizedArray(ptr noundef %_1)
#[no_mangle]
pub extern "C" fn test_WithZeroSizedArray(_: WithZeroSizedArray) -> WithZeroSizedArray { loop {} }
@ -65,7 +65,7 @@ pub extern "C" fn test_Gpz(_: GenericPlusZst<Bool>) -> GenericPlusZst<Bool> { lo
#[repr(transparent)]
pub struct LifetimePhantom<'a, T: 'a>(*const T, PhantomData<&'a T>);
// CHECK: define{{.*}}{{i16\*|ptr}} @test_LifetimePhantom({{i16\*|ptr}} noundef %_1)
// CHECK: define{{.*}}ptr @test_LifetimePhantom(ptr noundef %_1)
#[no_mangle]
pub extern "C" fn test_LifetimePhantom(_: LifetimePhantom<i16>) -> LifetimePhantom<i16> { loop {} }

View File

@ -127,18 +127,18 @@ pub struct Large {
d: i64,
}
// CHECK: define void @f_agg_large({{%Large\*|ptr}} {{.*}}%x)
// CHECK: define void @f_agg_large(ptr {{.*}}%x)
#[no_mangle]
pub extern "C" fn f_agg_large(mut x: Large) {
}
// CHECK: define void @f_agg_large_ret({{%Large\*|ptr}} {{.*}}sret{{.*}}, i32 noundef signext %i, i8 noundef signext %j)
// CHECK: define void @f_agg_large_ret(ptr {{.*}}sret{{.*}}, i32 noundef signext %i, i8 noundef signext %j)
#[no_mangle]
pub extern "C" fn f_agg_large_ret(i: i32, j: i8) -> Large {
Large { a: 1, b: 2, c: 3, d: 4 }
}
// CHECK: define void @f_scalar_stack_1(i64 %0, [2 x i64] %1, i128 %2, {{%Large\*|ptr}} {{.*}}%d, i8 noundef zeroext %e, i8 noundef signext %f, i8 noundef %g, i8 noundef %h)
// CHECK: define void @f_scalar_stack_1(i64 %0, [2 x i64] %1, i128 %2, ptr {{.*}}%d, i8 noundef zeroext %e, i8 noundef signext %f, i8 noundef %g, i8 noundef %h)
#[no_mangle]
pub extern "C" fn f_scalar_stack_1(
a: Tiny,
@ -152,7 +152,7 @@ pub extern "C" fn f_scalar_stack_1(
) {
}
// CHECK: define void @f_scalar_stack_2({{%Large\*|ptr}} {{.*}}sret{{.*}} %_0, i64 noundef %a, i128 %0, i128 %1, i64 noundef %d, i8 noundef zeroext %e, i8 noundef %f, i8 noundef %g)
// CHECK: define void @f_scalar_stack_2(ptr {{.*}}sret{{.*}} %_0, i64 noundef %a, i128 %0, i128 %1, i64 noundef %d, i8 noundef zeroext %e, i8 noundef %f, i8 noundef %g)
#[no_mangle]
pub extern "C" fn f_scalar_stack_2(
a: u64,
@ -172,7 +172,7 @@ pub extern "C" fn f_scalar_stack_2(
#[no_mangle]
pub unsafe extern "C" fn f_va_caller() {
// CHECK: call noundef signext i32 (i32, ...) @f_va_callee(i32 noundef signext 1, i32 noundef signext 2, i64 noundef 3, double {{.*}}, double {{.*}}, i64 {{.*}}, [2 x i64] {{.*}}, i128 {{.*}}, {{%Large\*|ptr}} {{.*}})
// CHECK: call noundef signext i32 (i32, ...) @f_va_callee(i32 noundef signext 1, i32 noundef signext 2, i64 noundef 3, double {{.*}}, double {{.*}}, i64 {{.*}}, [2 x i64] {{.*}}, i128 {{.*}}, ptr {{.*}})
f_va_callee(
1,
2i32,

View File

@ -8,7 +8,7 @@
pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 {
// CHECK-LABEL: define{{.*}}foo{{.*}}!type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: start:
// CHECK: [[TT:%.+]] = call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0}}, metadata !"{{[[:print:]]+}}")
// CHECK: [[TT:%.+]] = call i1 @llvm.type.test(ptr {{%f|%0}}, metadata !"{{[[:print:]]+}}")
// CHECK-NEXT: br i1 [[TT]], label %type_test.pass, label %type_test.fail
// CHECK: type_test.pass:
// CHECK-NEXT: {{%.+}} = call i32 %f(i32 %arg)

View File

@ -8,21 +8,21 @@
pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 {
// CHECK-LABEL: define{{.*}}foo
// CHECK-SAME: {{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0}}, metadata !"_ZTSFu3i32S_E.generalized")
// CHECK: call i1 @llvm.type.test(ptr {{%f|%0}}, metadata !"_ZTSFu3i32S_E.generalized")
f(arg)
}
pub fn bar(f: fn(i32, i32) -> i32, arg1: i32, arg2: i32) -> i32 {
// CHECK-LABEL: define{{.*}}bar
// CHECK-SAME: {{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0}}, metadata !"_ZTSFu3i32S_S_E.generalized")
// CHECK: call i1 @llvm.type.test(ptr {{%f|%0}}, metadata !"_ZTSFu3i32S_S_E.generalized")
f(arg1, arg2)
}
pub fn baz(f: fn(i32, i32, i32) -> i32, arg1: i32, arg2: i32, arg3: i32) -> i32 {
// CHECK-LABEL: define{{.*}}baz
// CHECK-SAME: {{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0}}, metadata !"_ZTSFu3i32S_S_S_E.generalized")
// CHECK: call i1 @llvm.type.test(ptr {{%f|%0}}, metadata !"_ZTSFu3i32S_S_S_E.generalized")
f(arg1, arg2, arg3)
}

View File

@ -8,21 +8,21 @@
pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 {
// CHECK-LABEL: define{{.*}}foo
// CHECK-SAME: {{.*}}![[TYPE1:[0-9]+]]
// CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0}}, metadata !"_ZTSFu3i32S_E.normalized.generalized")
// CHECK: call i1 @llvm.type.test(ptr {{%f|%0}}, metadata !"_ZTSFu3i32S_E.normalized.generalized")
f(arg)
}
pub fn bar(f: fn(i32, i32) -> i32, arg1: i32, arg2: i32) -> i32 {
// CHECK-LABEL: define{{.*}}bar
// CHECK-SAME: {{.*}}![[TYPE2:[0-9]+]]
// CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0}}, metadata !"_ZTSFu3i32S_S_E.normalized.generalized")
// CHECK: call i1 @llvm.type.test(ptr {{%f|%0}}, metadata !"_ZTSFu3i32S_S_E.normalized.generalized")
f(arg1, arg2)
}
pub fn baz(f: fn(i32, i32, i32) -> i32, arg1: i32, arg2: i32, arg3: i32) -> i32 {
// CHECK-LABEL: define{{.*}}baz
// CHECK-SAME: {{.*}}![[TYPE3:[0-9]+]]
// CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0}}, metadata !"_ZTSFu3i32S_S_S_E.normalized.generalized")
// CHECK: call i1 @llvm.type.test(ptr {{%f|%0}}, metadata !"_ZTSFu3i32S_S_S_E.normalized.generalized")
f(arg1, arg2, arg3)
}

View File

@ -8,21 +8,21 @@
pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 {
// CHECK-LABEL: define{{.*}}foo
// CHECK-SAME: {{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}}
// CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0}}, metadata !"_ZTSFu3i32S_E.normalized")
// CHECK: call i1 @llvm.type.test(ptr {{%f|%0}}, metadata !"_ZTSFu3i32S_E.normalized")
f(arg)
}
pub fn bar(f: fn(i32, i32) -> i32, arg1: i32, arg2: i32) -> i32 {
// CHECK-LABEL: define{{.*}}bar
// CHECK-SAME: {{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}}
// CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0}}, metadata !"_ZTSFu3i32S_S_E.normalized")
// CHECK: call i1 @llvm.type.test(ptr {{%f|%0}}, metadata !"_ZTSFu3i32S_S_E.normalized")
f(arg1, arg2)
}
pub fn baz(f: fn(i32, i32, i32) -> i32, arg1: i32, arg2: i32, arg3: i32) -> i32 {
// CHECK-LABEL: define{{.*}}baz
// CHECK-SAME: {{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}}
// CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0}}, metadata !"_ZTSFu3i32S_S_S_E.normalized")
// CHECK: call i1 @llvm.type.test(ptr {{%f|%0}}, metadata !"_ZTSFu3i32S_S_S_E.normalized")
f(arg1, arg2, arg3)
}

View File

@ -8,21 +8,21 @@
pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 {
// CHECK-LABEL: define{{.*}}foo
// CHECK-SAME: {{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0}}, metadata !"_ZTSFu3i32S_E")
// CHECK: call i1 @llvm.type.test(ptr {{%f|%0}}, metadata !"_ZTSFu3i32S_E")
f(arg)
}
pub fn bar(f: fn(i32, i32) -> i32, arg1: i32, arg2: i32) -> i32 {
// CHECK-LABEL: define{{.*}}bar
// CHECK-SAME: {{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0}}, metadata !"_ZTSFu3i32S_S_E")
// CHECK: call i1 @llvm.type.test(ptr {{%f|%0}}, metadata !"_ZTSFu3i32S_S_E")
f(arg1, arg2)
}
pub fn baz(f: fn(i32, i32, i32) -> i32, arg1: i32, arg2: i32, arg3: i32) -> i32 {
// CHECK-LABEL: define{{.*}}baz
// CHECK-SAME: {{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0}}, metadata !"_ZTSFu3i32S_S_S_E")
// CHECK: call i1 @llvm.type.test(ptr {{%f|%0}}, metadata !"_ZTSFu3i32S_S_S_E")
f(arg1, arg2, arg3)
}

View File

@ -68,7 +68,7 @@ impl<T, U, const N: usize> Trait5<U, N> for T {
pub fn foo1(a: &dyn Trait1) {
a.foo();
// CHECK-LABEL: define{{.*}}4foo1{{.*}}!type !{{[0-9]+}}
// CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE1:[[:print:]]+]]")
// CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE1:[[:print:]]+]]")
}
pub fn bar1() {
@ -76,13 +76,13 @@ pub fn bar1() {
let b = &a as &dyn Trait1;
b.foo();
// CHECK-LABEL: define{{.*}}4bar1{{.*}}!type !{{[0-9]+}}
// CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE2:[[:print:]]+]]")
// CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE2:[[:print:]]+]]")
}
pub fn foo2<T>(a: &dyn Trait2<T>) {
a.bar();
// CHECK-LABEL: define{{.*}}4foo2{{.*}}!type !{{[0-9]+}}
// CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE2:[[:print:]]+]]")
// CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE2:[[:print:]]+]]")
}
pub fn bar2() {
@ -91,14 +91,14 @@ pub fn bar2() {
let b = &a as &dyn Trait2<i32>;
b.bar();
// CHECK-LABEL: define{{.*}}4bar2{{.*}}!type !{{[0-9]+}}
// CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE2:[[:print:]]+]]")
// CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE2:[[:print:]]+]]")
}
pub fn foo3(a: &dyn Trait3<Type3>) {
let b = Type3;
a.baz(&b);
// CHECK-LABEL: define{{.*}}4foo3{{.*}}!type !{{[0-9]+}}
// CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE3:[[:print:]]+]]")
// CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE3:[[:print:]]+]]")
}
pub fn bar3() {
@ -107,14 +107,14 @@ pub fn bar3() {
let b = &a as &dyn Trait3<Type3>;
b.baz(&a);
// CHECK-LABEL: define{{.*}}4bar3{{.*}}!type !{{[0-9]+}}
// CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE3:[[:print:]]+]]")
// CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE3:[[:print:]]+]]")
}
pub fn foo4<'a>(a: &dyn Trait4<'a, Type4, Output = &'a i32>) {
let b = Type4;
a.qux(&b);
// CHECK-LABEL: define{{.*}}4foo4{{.*}}!type !{{[0-9]+}}
// CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE4:[[:print:]]+]]")
// CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE4:[[:print:]]+]]")
}
pub fn bar4<'a>() {
@ -123,14 +123,14 @@ pub fn bar4<'a>() {
let b = &a as &dyn Trait4<'a, Type4, Output = &'a i32>;
b.qux(&a);
// CHECK-LABEL: define{{.*}}4bar4{{.*}}!type !{{[0-9]+}}
// CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE4:[[:print:]]+]]")
// CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE4:[[:print:]]+]]")
}
pub fn foo5(a: &dyn Trait5<Type5, 32>) {
let b = &[Type5; 32];
a.quux(&b);
// CHECK-LABEL: define{{.*}}4foo5{{.*}}!type !{{[0-9]+}}
// CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE5:[[:print:]]+]]")
// CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE5:[[:print:]]+]]")
}
pub fn bar5() {
@ -139,7 +139,7 @@ pub fn bar5() {
let b = &a as &dyn Trait5<Type5, 32>;
b.quux(&a);
// CHECK-LABEL: define{{.*}}4bar5{{.*}}!type !{{[0-9]+}}
// CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE5:[[:print:]]+]]")
// CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE5:[[:print:]]+]]")
}
// CHECK: !{{[0-9]+}} = !{i64 0, !"[[TYPE1]]"}

View File

@ -93,7 +93,7 @@ impl<T, U, const N: usize> Trait5<U, N> for T {
pub fn foo1(a: &dyn Trait1) {
a.foo();
// CHECK-LABEL: define{{.*}}4foo1{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
// CHECK: call void %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE1:[[:print:]]+]]) ]
// CHECK: call void %{{[0-9]}}(ptr align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE1:[[:print:]]+]]) ]
}
pub fn bar1() {
@ -101,13 +101,13 @@ pub fn bar1() {
let b = &a as &dyn Trait1;
b.foo();
// CHECK-LABEL: define{{.*}}4bar1{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
// CHECK: call void %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE1:[[:print:]]+]]) ]
// CHECK: call void %{{[0-9]}}(ptr align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE1:[[:print:]]+]]) ]
}
pub fn foo2<T>(a: &dyn Trait2<T>) {
a.bar();
// CHECK-LABEL: define{{.*}}4foo2{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
// CHECK: call void %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE2:[[:print:]]+]]) ]
// CHECK: call void %{{[0-9]}}(ptr align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE2:[[:print:]]+]]) ]
}
pub fn bar2() {
@ -116,14 +116,14 @@ pub fn bar2() {
let b = &a as &dyn Trait2<i32>;
b.bar();
// CHECK-LABEL: define{{.*}}4bar2{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
// CHECK: call void %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE2:[[:print:]]+]]) ]
// CHECK: call void %{{[0-9]}}(ptr align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE2:[[:print:]]+]]) ]
}
pub fn foo3(a: &dyn Trait3<Type3>) {
let b = Type3;
a.baz(&b);
// CHECK-LABEL: define{{.*}}4foo3{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
// CHECK: call void %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}, {{\{\}\*|ptr|%Type3\*}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE3:[[:print:]]+]]) ]
// CHECK: call void %{{[0-9]}}(ptr align 1 {{%[a-z]\.0|%_[0-9]}}, ptr align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE3:[[:print:]]+]]) ]
}
pub fn bar3() {
@ -132,14 +132,14 @@ pub fn bar3() {
let b = &a as &dyn Trait3<Type3>;
b.baz(&a);
// CHECK-LABEL: define{{.*}}4bar3{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
// CHECK: call void %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}, {{\{\}\*|ptr|%Type3\*}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE3:[[:print:]]+]]) ]
// CHECK: call void %{{[0-9]}}(ptr align 1 {{%[a-z]\.0|%_[0-9]}}, ptr align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE3:[[:print:]]+]]) ]
}
pub fn foo4<'a>(a: &dyn Trait4<'a, Type4, Output = &'a i32>) {
let b = Type4;
a.qux(&b);
// CHECK-LABEL: define{{.*}}4foo4{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
// CHECK: call align 4 {{ptr|i32\*}} %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}, {{\{\}\*|ptr|%Type4\*}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE4:[[:print:]]+]]) ]
// CHECK: call align 4 ptr %{{[0-9]}}(ptr align 1 {{%[a-z]\.0|%_[0-9]}}, ptr align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE4:[[:print:]]+]]) ]
}
pub fn bar4<'a>() {
@ -148,14 +148,14 @@ pub fn bar4<'a>() {
let b = &a as &dyn Trait4<'a, Type4, Output = &'a i32>;
b.qux(&a);
// CHECK-LABEL: define{{.*}}4bar4{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
// CHECK: call align 4 {{ptr|i32\*}} %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}, {{\{\}\*|ptr|%Type4\*}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE4:[[:print:]]+]]) ]
// CHECK: call align 4 ptr %{{[0-9]}}(ptr align 1 {{%[a-z]\.0|%_[0-9]}}, ptr align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE4:[[:print:]]+]]) ]
}
pub fn foo5(a: &dyn Trait5<Type5, 32>) {
let b = &[Type5; 32];
a.quux(&b);
// CHECK-LABEL: define{{.*}}4foo5{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
// CHECK: call void %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z](\.0)*|%_[0-9]+]}}, {{\{\}\*|ptr|\[32 x %Type5\]\*}} align 1 {{%[a-z](\.0)*|%_[0-9]+}}){{.*}}[ "kcfi"(i32 [[TYPE5:[[:print:]]+]]) ]
// CHECK: call void %{{[0-9]}}(ptr align 1 {{%[a-z](\.0)*|%_[0-9]+]}}, ptr align 1 {{%[a-z](\.0)*|%_[0-9]+}}){{.*}}[ "kcfi"(i32 [[TYPE5:[[:print:]]+]]) ]
}
pub fn bar5() {
@ -164,7 +164,7 @@ pub fn bar5() {
let b = &a as &dyn Trait5<Type5, 32>;
b.quux(&a);
// CHECK-LABEL: define{{.*}}4bar5{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
// CHECK: call void %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z](\.0)*|%_[0-9]+]}}, {{\{\}\*|ptr|\[32 x %Type5\]\*}} align 1 {{%[a-z](\.0)*|%_[0-9]+}}){{.*}}[ "kcfi"(i32 [[TYPE5:[[:print:]]+]]) ]
// CHECK: call void %{{[0-9]}}(ptr align 1 {{%[a-z](\.0)*|%_[0-9]+]}}, ptr align 1 {{%[a-z](\.0)*|%_[0-9]+}}){{.*}}[ "kcfi"(i32 [[TYPE5:[[:print:]]+]]) ]
}
// CHECK: !{{[0-9]+}} = !{i32 [[TYPE1]]}

View File

@ -23,7 +23,7 @@
#[no_mangle]
pub unsafe fn gather_f32x2(pointers: Vec2<*const f32>, mask: Vec2<i32>,
values: Vec2<f32>) -> Vec2<f32> {
// CHECK: call <2 x float> @llvm.masked.gather.v2f32.{{.+}}(<2 x {{float\*|ptr}}> {{.*}}, i32 {{.*}}, <2 x i1> {{.*}}, <2 x float> {{.*}})
// CHECK: call <2 x float> @llvm.masked.gather.v2f32.{{.+}}(<2 x ptr> {{.*}}, i32 {{.*}}, <2 x i1> {{.*}}, <2 x float> {{.*}})
simd_gather(values, pointers, mask)
}
@ -31,6 +31,6 @@ pub unsafe fn gather_f32x2(pointers: Vec2<*const f32>, mask: Vec2<i32>,
#[no_mangle]
pub unsafe fn gather_pf32x2(pointers: Vec2<*const *const f32>, mask: Vec2<i32>,
values: Vec2<*const f32>) -> Vec2<*const f32> {
// CHECK: call <2 x {{float\*|ptr}}> @llvm.masked.gather.{{.+}}(<2 x {{float\*\*|ptr}}> {{.*}}, i32 {{.*}}, <2 x i1> {{.*}}, <2 x {{float\*|ptr}}> {{.*}})
// CHECK: call <2 x ptr> @llvm.masked.gather.{{.+}}(<2 x ptr> {{.*}}, i32 {{.*}}, <2 x i1> {{.*}}, <2 x ptr> {{.*}})
simd_gather(values, pointers, mask)
}

View File

@ -23,7 +23,7 @@
#[no_mangle]
pub unsafe fn scatter_f32x2(pointers: Vec2<*mut f32>, mask: Vec2<i32>,
values: Vec2<f32>) {
// CHECK: call void @llvm.masked.scatter.v2f32.v2p0{{.*}}(<2 x float> {{.*}}, <2 x {{float\*|ptr}}> {{.*}}, i32 {{.*}}, <2 x i1> {{.*}})
// CHECK: call void @llvm.masked.scatter.v2f32.v2p0{{.*}}(<2 x float> {{.*}}, <2 x ptr> {{.*}}, i32 {{.*}}, <2 x i1> {{.*}})
simd_scatter(values, pointers, mask)
}
@ -32,6 +32,6 @@ pub unsafe fn scatter_f32x2(pointers: Vec2<*mut f32>, mask: Vec2<i32>,
#[no_mangle]
pub unsafe fn scatter_pf32x2(pointers: Vec2<*mut *const f32>, mask: Vec2<i32>,
values: Vec2<*const f32>) {
// CHECK: call void @llvm.masked.scatter.v2p0{{.*}}.v2p0{{.*}}(<2 x {{float\*|ptr}}> {{.*}}, <2 x {{float\*\*|ptr}}> {{.*}}, i32 {{.*}}, <2 x i1> {{.*}})
// CHECK: call void @llvm.masked.scatter.v2p0{{.*}}.v2p0{{.*}}(<2 x ptr> {{.*}}, <2 x ptr> {{.*}}, i32 {{.*}}, <2 x i1> {{.*}})
simd_scatter(values, pointers, mask)
}

View File

@ -42,8 +42,8 @@ pub fn vector_align() -> usize {
// CHECK-LABEL: @build_array_transmute_s
#[no_mangle]
pub fn build_array_transmute_s(x: [f32; 4]) -> S<4> {
// CHECK: %[[VAL:.+]] = load <4 x float>, {{ptr %x|.+>\* %.+}}, align [[ARRAY_ALIGN]]
// CHECK: store <4 x float> %[[VAL:.+]], {{ptr %_0|.+>\* %.+}}, align [[VECTOR_ALIGN]]
// CHECK: %[[VAL:.+]] = load <4 x float>, ptr %x, align [[ARRAY_ALIGN]]
// CHECK: store <4 x float> %[[VAL:.+]], ptr %_0, align [[VECTOR_ALIGN]]
unsafe { std::mem::transmute(x) }
}
@ -57,8 +57,8 @@ pub fn vector_align() -> usize {
// CHECK-LABEL: @build_array_transmute_t
#[no_mangle]
pub fn build_array_transmute_t(x: [f32; 4]) -> T {
// CHECK: %[[VAL:.+]] = load <4 x float>, {{ptr %x|.+>\* %.+}}, align [[ARRAY_ALIGN]]
// CHECK: store <4 x float> %[[VAL:.+]], {{ptr %_0|.+>\* %.+}}, align [[VECTOR_ALIGN]]
// CHECK: %[[VAL:.+]] = load <4 x float>, ptr %x, align [[ARRAY_ALIGN]]
// CHECK: store <4 x float> %[[VAL:.+]], ptr %_0, align [[VECTOR_ALIGN]]
unsafe { std::mem::transmute(x) }
}
@ -76,7 +76,7 @@ pub fn vector_align() -> usize {
// CHECK-LABEL: @build_array_transmute_u
#[no_mangle]
pub fn build_array_transmute_u(x: [f32; 4]) -> U {
// CHECK: %[[VAL:.+]] = load <4 x float>, {{ptr %x|.+>\* %.+}}, align [[ARRAY_ALIGN]]
// CHECK: store <4 x float> %[[VAL:.+]], {{ptr %_0|.+>\* %.+}}, align [[VECTOR_ALIGN]]
// CHECK: %[[VAL:.+]] = load <4 x float>, ptr %x, align [[ARRAY_ALIGN]]
// CHECK: store <4 x float> %[[VAL:.+]], ptr %_0, align [[VECTOR_ALIGN]]
unsafe { std::mem::transmute(x) }
}

View File

@ -21,6 +21,6 @@
// CHECK-LABEL: smoke
#[no_mangle]
pub fn smoke(ptrs: SimdConstPtr<u8, 8>, offsets: Simd<usize, 8>) -> SimdConstPtr<u8, 8> {
// CHECK: getelementptr i8, <8 x {{i8\*|ptr}}> %0, <8 x i64> %1
// CHECK: getelementptr i8, <8 x ptr> %0, <8 x i64> %1
unsafe { simd_arith_offset(ptrs, offsets) }
}

View File

@ -23,7 +23,7 @@ pub fn zero_len_array() {
// CHECK-LABEL: @byte_array
#[no_mangle]
pub fn byte_array() {
// CHECK: call void @llvm.memset.{{.+}}({{i8\*|ptr}} {{.*}}, i8 7, i{{[0-9]+}} 4
// CHECK: call void @llvm.memset.{{.+}}(ptr {{.*}}, i8 7, i{{[0-9]+}} 4
// CHECK-NOT: br label %repeat_loop_header{{.*}}
let x = [7u8; 4];
opaque(&x);
@ -39,7 +39,7 @@ enum Init {
// CHECK-LABEL: @byte_enum_array
#[no_mangle]
pub fn byte_enum_array() {
// CHECK: call void @llvm.memset.{{.+}}({{i8\*|ptr}} {{.*}}, i8 {{.*}}, i{{[0-9]+}} 4
// CHECK: call void @llvm.memset.{{.+}}(ptr {{.*}}, i8 {{.*}}, i{{[0-9]+}} 4
// CHECK-NOT: br label %repeat_loop_header{{.*}}
let x = [Init::Memset; 4];
opaque(&x);
@ -48,7 +48,7 @@ pub fn byte_enum_array() {
// CHECK-LABEL: @zeroed_integer_array
#[no_mangle]
pub fn zeroed_integer_array() {
// CHECK: call void @llvm.memset.{{.+}}({{i8\*|ptr}} {{.*}}, i8 0, i{{[0-9]+}} 16
// CHECK: call void @llvm.memset.{{.+}}(ptr {{.*}}, i8 0, i{{[0-9]+}} 16
// CHECK-NOT: br label %repeat_loop_header{{.*}}
let x = [0u32; 4];
opaque(&x);

View File

@ -9,7 +9,7 @@
#[no_mangle]
pub fn slice_iter_len_eq_zero(y: std::slice::Iter<'_, Demo>) -> bool {
// CHECK-NOT: sub
// CHECK: %[[RET:.+]] = icmp eq {{i8\*|ptr}} {{%1|%0}}, {{%1|%0}}
// CHECK: %[[RET:.+]] = icmp eq ptr {{%1|%0}}, {{%1|%0}}
// CHECK: ret i1 %[[RET]]
y.len() == 0
}

View File

@ -25,7 +25,7 @@
// CHECK-LABEL: @is_zero_slice_short
#[no_mangle]
pub fn is_zero_slice_short(data: &[u8; 4]) -> bool {
// CHECK: %[[LOAD:.+]] = load i32, {{i32\*|ptr}} %{{.+}}, align 1
// CHECK: %[[LOAD:.+]] = load i32, ptr %{{.+}}, align 1
// CHECK-NEXT: %[[EQ:.+]] = icmp eq i32 %[[LOAD]], 0
// CHECK-NEXT: ret i1 %[[EQ]]
&data[..] == [0; 4]
@ -34,7 +34,7 @@
// CHECK-LABEL: @is_zero_array
#[no_mangle]
pub fn is_zero_array(data: &[u8; 4]) -> bool {
// CHECK: %[[LOAD:.+]] = load i32, {{i32\*|ptr}} %{{.+}}, align 1
// CHECK: %[[LOAD:.+]] = load i32, ptr %{{.+}}, align 1
// CHECK-NEXT: %[[EQ:.+]] = icmp eq i32 %[[LOAD]], 0
// CHECK-NEXT: ret i1 %[[EQ]]
*data == [0; 4]
@ -50,7 +50,7 @@
fn eq_slice_of_nested_u8(x: &[[u8; 3]], y: &[[u8; 3]]) -> bool {
// CHECK: icmp eq [[USIZE]] %x.1, %y.1
// CHECK: %[[BYTES:.+]] = mul nsw [[USIZE]] %x.1, 3
// CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}({{i8\*|ptr}}
// CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}(ptr
// CHECK-SAME: , [[USIZE]]{{( noundef)?}} %[[BYTES]])
x == y
}
@ -62,7 +62,7 @@
fn eq_slice_of_i32(x: &[i32], y: &[i32]) -> bool {
// CHECK: icmp eq [[USIZE]] %x.1, %y.1
// CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %x.1, 2
// CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}({{i32\*|ptr}}
// CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}(ptr
// CHECK-SAME: , [[USIZE]]{{( noundef)?}} %[[BYTES]])
x == y
}
@ -74,7 +74,7 @@ fn eq_slice_of_i32(x: &[i32], y: &[i32]) -> bool {
fn eq_slice_of_nonzero(x: &[NonZeroU32], y: &[NonZeroU32]) -> bool {
// CHECK: icmp eq [[USIZE]] %x.1, %y.1
// CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %x.1, 2
// CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}({{i32\*|ptr}}
// CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}(ptr
// CHECK-SAME: , [[USIZE]]{{( noundef)?}} %[[BYTES]])
x == y
}
@ -86,7 +86,7 @@ fn eq_slice_of_nonzero(x: &[NonZeroU32], y: &[NonZeroU32]) -> bool {
fn eq_slice_of_option_of_nonzero(x: &[Option<NonZeroI16>], y: &[Option<NonZeroI16>]) -> bool {
// CHECK: icmp eq [[USIZE]] %x.1, %y.1
// CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %x.1, 1
// CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}({{i16\*|ptr}}
// CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}(ptr
// CHECK-SAME: , [[USIZE]]{{( noundef)?}} %[[BYTES]])
x == y
}

View File

@ -1,7 +1,6 @@
// compile-flags: -O
// only-64bit (because we're using [ui]size)
// ignore-debug (because the assertions get in the way)
// min-llvm-version: 15.0 (because this is a relatively new instcombine)
#![crate_type = "lib"]
#![feature(slice_from_ptr_range)]

View File

@ -17,8 +17,8 @@ pub struct Bytes {
pub fn small_array_alignment(x: &mut [i8; 4], y: [i8; 4]) {
// CHECK: [[TMP:%.+]] = alloca i32
// CHECK: %y = alloca [4 x i8]
// CHECK: store i32 %0, {{i32\*|ptr}} [[TMP]]
// CHECK: call void @llvm.memcpy.{{.*}}({{i8\*|ptr}} align 1 {{.+}}, {{i8\*|ptr}} align 4 {{.+}}, i{{[0-9]+}} 4, i1 false)
// CHECK: store i32 %0, ptr [[TMP]]
// CHECK: call void @llvm.memcpy.{{.*}}(ptr align 1 {{.+}}, ptr align 4 {{.+}}, i{{[0-9]+}} 4, i1 false)
*x = y;
}
@ -29,7 +29,7 @@ pub struct Bytes {
pub fn small_struct_alignment(x: &mut Bytes, y: Bytes) {
// CHECK: [[TMP:%.+]] = alloca i32
// CHECK: %y = alloca %Bytes
// CHECK: store i32 %0, {{i32\*|ptr}} [[TMP]]
// CHECK: call void @llvm.memcpy.{{.*}}({{i8\*|ptr}} align 1 {{.+}}, {{i8\*|ptr}} align 4 {{.+}}, i{{[0-9]+}} 4, i1 false)
// CHECK: store i32 %0, ptr [[TMP]]
// CHECK: call void @llvm.memcpy.{{.*}}(ptr align 1 {{.+}}, ptr align 4 {{.+}}, i{{[0-9]+}} 4, i1 false)
*x = y;
}

View File

@ -83,9 +83,9 @@ pub fn swap_1kb_slices(x: &mut [OneKilobyteBuffer], y: &mut [OneKilobyteBuffer])
#[no_mangle]
pub fn swap_big_aligned(x: &mut BigButHighlyAligned, y: &mut BigButHighlyAligned) {
// CHECK-NOT: call void @llvm.memcpy
// CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} noundef nonnull align 64 dereferenceable(192)
// CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} noundef nonnull align 64 dereferenceable(192)
// CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} noundef nonnull align 64 dereferenceable(192)
// CHECK: call void @llvm.memcpy.{{.+}}(ptr noundef nonnull align 64 dereferenceable(192)
// CHECK: call void @llvm.memcpy.{{.+}}(ptr noundef nonnull align 64 dereferenceable(192)
// CHECK: call void @llvm.memcpy.{{.+}}(ptr noundef nonnull align 64 dereferenceable(192)
// CHECK-NOT: call void @llvm.memcpy
swap(x, y)
}

View File

@ -1,5 +1,4 @@
// compile-flags: -O -Z merge-functions=disabled
// min-llvm-version: 15.0 # this test uses `ptr`s
// ignore-debug
#![crate_type = "lib"]

View File

@ -1,5 +1,4 @@
// compile-flags: -C opt-level=0 -C no-prepopulate-passes
// min-llvm-version: 15.0 # this test assumes `ptr`s and thus no `pointercast`s
#![crate_type = "lib"]

View File

@ -1,4 +1,3 @@
// min-llvm-version: 15.0
// compile-flags: -O -Z merge-functions=disabled --edition=2021
// only-x86_64

View File

@ -1,5 +1,4 @@
// compile-flags: -O
// min-llvm-version: 15.0 (LLVM 13 in CI does this differently from submodule LLVM)
// ignore-debug (because unchecked is checked in debug)
#![crate_type = "lib"]

View File

@ -1,5 +1,4 @@
// compile-flags: -C no-prepopulate-passes
// min-llvm-version: 15.0 (for opaque pointers)
// Check that we use undef (and not zero) for uninitialized bytes in constants.

View File

@ -17,25 +17,25 @@ pub enum Unhab {}
#[derive(Copy, Clone)]
pub union UnionI64x4{ a:(), b: i64x4 }
// CHECK: define {{(dso_local )?}}void @test_UnionI64x4({{<4 x i64>\*|ptr}} {{.*}} %_1)
// CHECK: define {{(dso_local )?}}void @test_UnionI64x4(ptr {{.*}} %_1)
#[no_mangle]
pub fn test_UnionI64x4(_: UnionI64x4) { loop {} }
pub union UnionI64x4_{ a: i64x4, b: (), c:i64x4, d: Unhab, e: ((),()), f: UnionI64x4 }
// CHECK: define {{(dso_local )?}}void @test_UnionI64x4_({{<4 x i64>\*|ptr}} {{.*}} %_1)
// CHECK: define {{(dso_local )?}}void @test_UnionI64x4_(ptr {{.*}} %_1)
#[no_mangle]
pub fn test_UnionI64x4_(_: UnionI64x4_) { loop {} }
pub union UnionI64x4I64{ a: i64x4, b: i64 }
// CHECK: define {{(dso_local )?}}void @test_UnionI64x4I64({{%UnionI64x4I64\*|ptr}} {{.*}} %_1)
// CHECK: define {{(dso_local )?}}void @test_UnionI64x4I64(ptr {{.*}} %_1)
#[no_mangle]
pub fn test_UnionI64x4I64(_: UnionI64x4I64) { loop {} }
pub union UnionI64x4Tuple{ a: i64x4, b: (i64, i64, i64, i64) }
// CHECK: define {{(dso_local )?}}void @test_UnionI64x4Tuple({{%UnionI64x4Tuple\*|ptr}} {{.*}} %_1)
// CHECK: define {{(dso_local )?}}void @test_UnionI64x4Tuple(ptr {{.*}} %_1)
#[no_mangle]
pub fn test_UnionI64x4Tuple(_: UnionI64x4Tuple) { loop {} }
@ -65,7 +65,7 @@ pub fn test_UnionU128(_: UnionU128) -> UnionU128 { loop {} }
#[repr(C)]
pub union CUnionU128{a:u128}
// CHECK: define {{(dso_local )?}}void @test_CUnionU128({{%CUnionU128\*|ptr}} {{.*}} %_1)
// CHECK: define {{(dso_local )?}}void @test_CUnionU128(ptr {{.*}} %_1)
#[no_mangle]
pub fn test_CUnionU128(_: CUnionU128) { loop {} }

View File

@ -4,7 +4,7 @@
// Test that even though we return a *const u8 not a &[u8] or a NonNull<u8>, LLVM knows that this
// pointer is nonnull.
// CHECK: nonnull {{i8\*|ptr}} @vec_as_ptr
// CHECK: nonnull ptr @vec_as_ptr
#[no_mangle]
pub fn vec_as_ptr(v: &Vec<u8>) -> *const u8 {
v.as_ptr()
@ -12,7 +12,7 @@ pub fn vec_as_ptr(v: &Vec<u8>) -> *const u8 {
// Test that even though we return a *const u8 not a &[u8] or a NonNull<u8>, LLVM knows that this
// pointer is nonnull.
// CHECK: nonnull {{i8\*|ptr}} @vec_as_mut_ptr
// CHECK: nonnull ptr @vec_as_mut_ptr
#[no_mangle]
pub fn vec_as_mut_ptr(v: &mut Vec<u8>) -> *mut u8 {
v.as_mut_ptr()

View File

@ -1,7 +1,6 @@
// compile-flags: -O -Z merge-functions=disabled
// only-x86_64
// ignore-debug
// min-llvm-version: 15.0
#![crate_type = "lib"]

View File

@ -39,10 +39,10 @@ CHECK-NOT: [[DEFINE_INTERNAL]]
CHECK: atomicrmw add ptr
CHECK-SAME: @__profc__R{{[a-zA-Z0-9_]+}}testprog14will_be_called,
CHECK: declare void @llvm.instrprof.increment({{i8\*|ptr}}, i64, i32, i32) #[[LLVM_INSTRPROF_INCREMENT_ATTR:[0-9]+]]
CHECK: declare void @llvm.instrprof.increment(ptr, i64, i32, i32) #[[LLVM_INSTRPROF_INCREMENT_ATTR:[0-9]+]]
WINDOWS: define linkonce_odr hidden i32 @__llvm_profile_runtime_user() #[[LLVM_PROFILE_RUNTIME_USER_ATTR:[0-9]+]] comdat {
WINDOWS-NEXT: %1 = load i32, {{i32\*|ptr}} @__llvm_profile_runtime
WINDOWS-NEXT: %1 = load i32, ptr @__llvm_profile_runtime
WINDOWS-NEXT: ret i32 %1
WINDOWS-NEXT: }

View File

@ -2,7 +2,7 @@ CHECK: define void @call_a_bunch_of_functions({{.*}} {
# Make sure that indirect call promotion inserted a check against the most
# frequently called function.
CHECK: %{{.*}} = icmp eq {{void \(\)\*|ptr}} %{{.*}}, @function_called_always
CHECK: %{{.*}} = icmp eq ptr %{{.*}}, @function_called_always
# Check that the call to `function_called_always` was inlined, so that we
# directly call `opaque_f1` from the upstream crate.
@ -12,5 +12,5 @@ CHECK: call void @opaque_f1()
# Same checks as above, repeated for the trait object case
CHECK: define void @call_a_bunch_of_trait_methods({{.*}}
CHECK: %{{.*}} = icmp eq {{void \(\{\}\*\)\*|ptr}} %{{.*}}, {{.*}}@foo
CHECK: %{{.*}} = icmp eq ptr %{{.*}}, {{.*}}@foo
CHECK: tail call void @opaque_f2()

View File

@ -1,6 +1,5 @@
// build-pass
// compile-flags: -O
// min-llvm-version: 14.0.5
// needs-asm-support
// only-x86_64
// only-linux

View File

@ -1,7 +1,5 @@
// run-pass
// ^-- The above is needed as this issue is related to LLVM/codegen.
// min-llvm-version:15.0.0
// ^-- The above is needed as this issue is fixed by the opaque pointers.
fn main() {
type_error(|x| &x);

View File

@ -1,8 +1,6 @@
// run-pass
// compile-flags: -Copt-level=0 -Cllvm-args=-opaque-pointers=0
// (opaque-pointers flag is called force-opaque-pointers in LLVM 13...)
// min-llvm-version: 14.0
// (the ability to disable opaque pointers has been removed in LLVM 17)
// ignore-llvm-version: 17 - 99

View File

@ -1,6 +1,5 @@
// run-pass
// regression test for issue #94923
// min-llvm-version: 15.0.0
// compile-flags: -C opt-level=3
fn f0<T>(mut x: usize) -> usize {