Auto merge of #109220 - nikic:poison, r=cuviper

Use poison instead of undef

In cases where it is legal, we should prefer poison values over undef values.

This replaces undef with poison for aggregate construction and for uninhabited types. There are more places where we can likely use poison, but I wanted to stay conservative to start with.

In particular the aggregate case is important for newer LLVM versions, which are not able to handle an undef base value during early optimization due to poison-propagation concerns.

r? `@cuviper`
This commit is contained in:
bors 2023-03-24 15:39:40 +00:00
commit 31d74fb24b
9 changed files with 17 additions and 6 deletions

View File

@ -73,6 +73,11 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
}
}
fn const_poison(&self, typ: Type<'gcc>) -> RValue<'gcc> {
// No distinction between undef and poison.
self.const_undef(typ)
}
fn const_int(&self, typ: Type<'gcc>, int: i64) -> RValue<'gcc> {
self.gcc_int(typ, int)
}

View File

@ -990,7 +990,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
fn resume(&mut self, exn0: &'ll Value, exn1: &'ll Value) {
let ty = self.type_struct(&[self.type_i8p(), self.type_i32()], false);
let mut exn = self.const_undef(ty);
let mut exn = self.const_poison(ty);
exn = self.insert_value(exn, exn0, 0);
exn = self.insert_value(exn, exn1, 1);
unsafe {

View File

@ -130,6 +130,10 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
unsafe { llvm::LLVMGetUndef(t) }
}
fn const_poison(&self, t: &'ll Type) -> &'ll Value {
unsafe { llvm::LLVMGetPoison(t) }
}
fn const_int(&self, t: &'ll Type, i: i64) -> &'ll Value {
unsafe { llvm::LLVMConstInt(t, i as u64, True) }
}

View File

@ -1069,6 +1069,7 @@ extern "C" {
// Operations on constants of any type
pub fn LLVMConstNull(Ty: &Type) -> &Value;
pub fn LLVMGetUndef(Ty: &Type) -> &Value;
pub fn LLVMGetPoison(Ty: &Type) -> &Value;
// Operations on metadata
pub fn LLVMMDStringInContext(C: &Context, Str: *const c_char, SLen: c_uint) -> &Value;

View File

@ -60,7 +60,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
) -> OperandRef<'tcx, V> {
assert!(layout.is_zst());
OperandRef {
val: OperandValue::Immediate(bx.const_undef(bx.immediate_backend_type(layout))),
val: OperandValue::Immediate(bx.const_poison(bx.immediate_backend_type(layout))),
layout,
}
}
@ -145,7 +145,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
let llty = bx.cx().backend_type(self.layout);
debug!("Operand::immediate_or_packed_pair: packing {:?} into {:?}", self, llty);
// Reconstruct the immediate aggregate.
let mut llpair = bx.cx().const_undef(llty);
let mut llpair = bx.cx().const_poison(llty);
let imm_a = bx.from_immediate(a);
let imm_b = bx.from_immediate(b);
llpair = bx.insert_value(llpair, imm_a, 0);

View File

@ -214,7 +214,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
let cast_to_size = cast_to_layout.layout.size();
let cast_to = bx.cx().immediate_backend_type(cast_to_layout);
if self.layout.abi.is_uninhabited() {
return bx.cx().const_undef(cast_to);
return bx.cx().const_poison(cast_to);
}
let (tag_scalar, tag_encoding, tag_field) = match self.layout.variants {
Variants::Single { index } => {

View File

@ -346,7 +346,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
assert!(bx.cx().is_backend_immediate(cast));
let ll_t_out = bx.cx().immediate_backend_type(cast);
if operand.layout.abi.is_uninhabited() {
let val = OperandValue::Immediate(bx.cx().const_undef(ll_t_out));
let val = OperandValue::Immediate(bx.cx().const_poison(ll_t_out));
return OperandRef { val, layout: cast };
}
let r_t_in =

View File

@ -8,6 +8,7 @@ pub trait ConstMethods<'tcx>: BackendTypes {
// Constant constructors
fn const_null(&self, t: Self::Type) -> Self::Value;
fn const_undef(&self, t: Self::Type) -> Self::Value;
fn const_poison(&self, t: Self::Type) -> Self::Value;
fn const_int(&self, t: Self::Type, i: i64) -> Self::Value;
fn const_uint(&self, t: Self::Type, i: u64) -> Self::Value;
fn const_uint_big(&self, t: Self::Type, u: u128) -> Self::Value;

View File

@ -13,7 +13,7 @@ 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]] } undef, {{\[0 x i8\]\*|ptr}} %x.0, 0
// 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
{ x }