Skip to content

Commit 3033182

Browse files
committed
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.
1 parent cd6c574 commit 3033182

File tree

9 files changed

+17
-6
lines changed

9 files changed

+17
-6
lines changed

compiler/rustc_codegen_gcc/src/common.rs

+5
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,11 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
7373
}
7474
}
7575

76+
fn const_poison(&self, typ: Type<'gcc>) -> RValue<'gcc> {
77+
// No distinction between undef and poison.
78+
self.const_undef(typ)
79+
}
80+
7681
fn const_int(&self, typ: Type<'gcc>, int: i64) -> RValue<'gcc> {
7782
self.gcc_int(typ, int)
7883
}

compiler/rustc_codegen_llvm/src/builder.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -990,7 +990,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
990990

991991
fn resume(&mut self, exn0: &'ll Value, exn1: &'ll Value) {
992992
let ty = self.type_struct(&[self.type_i8p(), self.type_i32()], false);
993-
let mut exn = self.const_undef(ty);
993+
let mut exn = self.const_poison(ty);
994994
exn = self.insert_value(exn, exn0, 0);
995995
exn = self.insert_value(exn, exn1, 1);
996996
unsafe {

compiler/rustc_codegen_llvm/src/common.rs

+4
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,10 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
130130
unsafe { llvm::LLVMGetUndef(t) }
131131
}
132132

133+
fn const_poison(&self, t: &'ll Type) -> &'ll Value {
134+
unsafe { llvm::LLVMGetPoison(t) }
135+
}
136+
133137
fn const_int(&self, t: &'ll Type, i: i64) -> &'ll Value {
134138
unsafe { llvm::LLVMConstInt(t, i as u64, True) }
135139
}

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1069,6 +1069,7 @@ extern "C" {
10691069
// Operations on constants of any type
10701070
pub fn LLVMConstNull(Ty: &Type) -> &Value;
10711071
pub fn LLVMGetUndef(Ty: &Type) -> &Value;
1072+
pub fn LLVMGetPoison(Ty: &Type) -> &Value;
10721073

10731074
// Operations on metadata
10741075
pub fn LLVMMDStringInContext(C: &Context, Str: *const c_char, SLen: c_uint) -> &Value;

compiler/rustc_codegen_ssa/src/mir/operand.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
6060
) -> OperandRef<'tcx, V> {
6161
assert!(layout.is_zst());
6262
OperandRef {
63-
val: OperandValue::Immediate(bx.const_undef(bx.immediate_backend_type(layout))),
63+
val: OperandValue::Immediate(bx.const_poison(bx.immediate_backend_type(layout))),
6464
layout,
6565
}
6666
}
@@ -145,7 +145,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
145145
let llty = bx.cx().backend_type(self.layout);
146146
debug!("Operand::immediate_or_packed_pair: packing {:?} into {:?}", self, llty);
147147
// Reconstruct the immediate aggregate.
148-
let mut llpair = bx.cx().const_undef(llty);
148+
let mut llpair = bx.cx().const_poison(llty);
149149
let imm_a = bx.from_immediate(a);
150150
let imm_b = bx.from_immediate(b);
151151
llpair = bx.insert_value(llpair, imm_a, 0);

compiler/rustc_codegen_ssa/src/mir/place.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
214214
let cast_to_size = cast_to_layout.layout.size();
215215
let cast_to = bx.cx().immediate_backend_type(cast_to_layout);
216216
if self.layout.abi.is_uninhabited() {
217-
return bx.cx().const_undef(cast_to);
217+
return bx.cx().const_poison(cast_to);
218218
}
219219
let (tag_scalar, tag_encoding, tag_field) = match self.layout.variants {
220220
Variants::Single { index } => {

compiler/rustc_codegen_ssa/src/mir/rvalue.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
295295
assert!(bx.cx().is_backend_immediate(cast));
296296
let ll_t_out = bx.cx().immediate_backend_type(cast);
297297
if operand.layout.abi.is_uninhabited() {
298-
let val = OperandValue::Immediate(bx.cx().const_undef(ll_t_out));
298+
let val = OperandValue::Immediate(bx.cx().const_poison(ll_t_out));
299299
return OperandRef { val, layout: cast };
300300
}
301301
let r_t_in =

compiler/rustc_codegen_ssa/src/traits/consts.rs

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ pub trait ConstMethods<'tcx>: BackendTypes {
88
// Constant constructors
99
fn const_null(&self, t: Self::Type) -> Self::Value;
1010
fn const_undef(&self, t: Self::Type) -> Self::Value;
11+
fn const_poison(&self, t: Self::Type) -> Self::Value;
1112
fn const_int(&self, t: Self::Type, i: i64) -> Self::Value;
1213
fn const_uint(&self, t: Self::Type, i: u64) -> Self::Value;
1314
fn const_uint_big(&self, t: Self::Type, u: u128) -> Self::Value;

tests/codegen/adjustments.rs

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

0 commit comments

Comments
 (0)