codegen: use new {re,de,}allocator annotations in llvm
This obviates the patch that teaches LLVM internals about _rust_{re,de}alloc functions by putting annotations directly in the IR for the optimizer. The sole test change is required to anchor FileCheck to the body of the `box_uninitialized` method, so it doesn't see the `allocalign` on `__rust_alloc` and get mad about the string `alloca` showing up. Since I was there anyway, I added some checks on the attributes to prove the right attributes got set. While we're here, we also emit allocator attributes on __rust_alloc_zeroed. This should allow LLVM to perform more optimizations for zeroed blocks, and probably fixes #90032. [This comment](https://github.com/rust-lang/rust/issues/24194#issuecomment-308791157) mentions "weird UB-like behaviour with bitvec iterators in rustc_data_structures" so we may need to back this change out if things go wrong. The new test cases require LLVM 15, so we copy them into LLVM 14-supporting versions, which we can delete when we drop LLVM 14.
This commit is contained in:
parent
2fdbf075cf
commit
130a1df71e
14 changed files with 356 additions and 4 deletions
|
@ -234,6 +234,14 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
|
|||
return Attribute::SanitizeMemTag;
|
||||
case ShadowCallStack:
|
||||
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
|
||||
}
|
||||
report_fatal_error("bad AttributeKind");
|
||||
}
|
||||
|
@ -305,6 +313,67 @@ extern "C" LLVMAttributeRef LLVMRustCreateUWTableAttr(LLVMContextRef C, bool Asy
|
|||
#endif
|
||||
}
|
||||
|
||||
extern "C" LLVMAttributeRef LLVMRustCreateAllocSizeAttr(LLVMContextRef C, uint32_t ElementSizeArg) {
|
||||
return wrap(Attribute::getWithAllocSizeArgs(*unwrap(C), ElementSizeArg, None));
|
||||
}
|
||||
|
||||
#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
|
||||
// passing them to LLVM.
|
||||
enum class LLVMRustAllocKindFlags : uint64_t {
|
||||
Unknown = 0,
|
||||
Alloc = 1,
|
||||
Realloc = 1 << 1,
|
||||
Free = 1 << 2,
|
||||
Uninitialized = 1 << 3,
|
||||
Zeroed = 1 << 4,
|
||||
Aligned = 1 << 5,
|
||||
};
|
||||
|
||||
static LLVMRustAllocKindFlags operator&(LLVMRustAllocKindFlags A, LLVMRustAllocKindFlags B) {
|
||||
return static_cast<LLVMRustAllocKindFlags>(static_cast<uint64_t>(A) &
|
||||
static_cast<uint64_t>(B));
|
||||
}
|
||||
|
||||
static bool isSet(LLVMRustAllocKindFlags F) { return F != LLVMRustAllocKindFlags::Unknown; }
|
||||
|
||||
static llvm::AllocFnKind allocKindFromRust(LLVMRustAllocKindFlags F) {
|
||||
llvm::AllocFnKind AFK = llvm::AllocFnKind::Unknown;
|
||||
if (isSet(F & LLVMRustAllocKindFlags::Alloc)) {
|
||||
AFK |= llvm::AllocFnKind::Alloc;
|
||||
}
|
||||
if (isSet(F & LLVMRustAllocKindFlags::Realloc)) {
|
||||
AFK |= llvm::AllocFnKind::Realloc;
|
||||
}
|
||||
if (isSet(F & LLVMRustAllocKindFlags::Free)) {
|
||||
AFK |= llvm::AllocFnKind::Free;
|
||||
}
|
||||
if (isSet(F & LLVMRustAllocKindFlags::Uninitialized)) {
|
||||
AFK |= llvm::AllocFnKind::Uninitialized;
|
||||
}
|
||||
if (isSet(F & LLVMRustAllocKindFlags::Zeroed)) {
|
||||
AFK |= llvm::AllocFnKind::Zeroed;
|
||||
}
|
||||
if (isSet(F & LLVMRustAllocKindFlags::Aligned)) {
|
||||
AFK |= llvm::AllocFnKind::Aligned;
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
// Enable a fast-math flag
|
||||
//
|
||||
// https://llvm.org/docs/LangRef.html#fast-math-flags
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue