Merge commit '59a81c2ca1edc88ad3ac4b27a8e03977ffb8e73a' into subtree-update_cg_gcc_2025_01_12
This commit is contained in:
@@ -1102,18 +1102,24 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||
val: RValue<'gcc>,
|
||||
ptr: RValue<'gcc>,
|
||||
align: Align,
|
||||
_flags: MemFlags,
|
||||
flags: MemFlags,
|
||||
) -> RValue<'gcc> {
|
||||
let ptr = self.check_store(val, ptr);
|
||||
let destination = ptr.dereference(self.location);
|
||||
// NOTE: libgccjit does not support specifying the alignment on the assignment, so we cast
|
||||
// to type so it gets the proper alignment.
|
||||
let destination_type = destination.to_rvalue().get_type().unqualified();
|
||||
let aligned_type = destination_type.get_aligned(align.bytes()).make_pointer();
|
||||
let aligned_destination = self.cx.context.new_bitcast(self.location, ptr, aligned_type);
|
||||
let aligned_destination = aligned_destination.dereference(self.location);
|
||||
self.llbb().add_assignment(self.location, aligned_destination, val);
|
||||
// TODO(antoyo): handle align and flags.
|
||||
let align = if flags.contains(MemFlags::UNALIGNED) { 1 } else { align.bytes() };
|
||||
let mut modified_destination_type = destination_type.get_aligned(align);
|
||||
if flags.contains(MemFlags::VOLATILE) {
|
||||
modified_destination_type = modified_destination_type.make_volatile();
|
||||
}
|
||||
|
||||
let modified_ptr =
|
||||
self.cx.context.new_cast(self.location, ptr, modified_destination_type.make_pointer());
|
||||
let modified_destination = modified_ptr.dereference(self.location);
|
||||
self.llbb().add_assignment(self.location, modified_destination, val);
|
||||
// TODO(antoyo): handle `MemFlags::NONTEMPORAL`.
|
||||
// NOTE: dummy value here since it's never used. FIXME(antoyo): API should not return a value here?
|
||||
// When adding support for NONTEMPORAL, make sure to not just emit MOVNT on x86; see the
|
||||
// LLVM backend for details.
|
||||
@@ -1236,13 +1242,13 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||
}
|
||||
|
||||
fn ptrtoint(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
|
||||
let usize_value = self.cx.const_bitcast(value, self.cx.type_isize());
|
||||
let usize_value = self.cx.context.new_cast(None, value, self.cx.type_isize());
|
||||
self.intcast(usize_value, dest_ty, false)
|
||||
}
|
||||
|
||||
fn inttoptr(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
|
||||
let usize_value = self.intcast(value, self.cx.type_isize(), false);
|
||||
self.cx.const_bitcast(usize_value, dest_ty)
|
||||
self.cx.context.new_cast(None, usize_value, dest_ty)
|
||||
}
|
||||
|
||||
fn bitcast(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
|
||||
@@ -1901,6 +1907,15 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
||||
v2: RValue<'gcc>,
|
||||
mask: RValue<'gcc>,
|
||||
) -> RValue<'gcc> {
|
||||
// NOTE: if the `mask` is a constant value, the following code will copy it in many places,
|
||||
// which will make GCC create a lot (+4000) local variables in some cases.
|
||||
// So we assign it to an explicit local variable once to avoid this.
|
||||
let func = self.current_func();
|
||||
let mask_var = func.new_local(self.location, mask.get_type(), "mask");
|
||||
let block = self.block;
|
||||
block.add_assignment(self.location, mask_var, mask);
|
||||
let mask = mask_var.to_rvalue();
|
||||
|
||||
// TODO(antoyo): use a recursive unqualified() here.
|
||||
let vector_type = v1.get_type().unqualified().dyncast_vector().expect("vector type");
|
||||
let element_type = vector_type.get_element_type();
|
||||
@@ -1917,18 +1932,35 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
||||
self.int_type
|
||||
};
|
||||
|
||||
let vector_type =
|
||||
mask.get_type().dyncast_vector().expect("simd_shuffle mask should be of vector type");
|
||||
let mask_num_units = vector_type.get_num_units();
|
||||
let mut mask_elements = vec![];
|
||||
for i in 0..mask_num_units {
|
||||
let index = self.context.new_rvalue_from_long(self.cx.type_u32(), i as _);
|
||||
mask_elements.push(self.context.new_cast(
|
||||
self.location,
|
||||
self.extract_element(mask, index).to_rvalue(),
|
||||
mask_element_type,
|
||||
));
|
||||
}
|
||||
// NOTE: this condition is needed because we call shuffle_vector in the implementation of
|
||||
// simd_gather.
|
||||
let mut mask_elements = if let Some(vector_type) = mask.get_type().dyncast_vector() {
|
||||
let mask_num_units = vector_type.get_num_units();
|
||||
let mut mask_elements = vec![];
|
||||
for i in 0..mask_num_units {
|
||||
let index = self.context.new_rvalue_from_long(self.cx.type_u32(), i as _);
|
||||
mask_elements.push(self.context.new_cast(
|
||||
self.location,
|
||||
self.extract_element(mask, index).to_rvalue(),
|
||||
mask_element_type,
|
||||
));
|
||||
}
|
||||
mask_elements
|
||||
} else {
|
||||
let struct_type = mask.get_type().is_struct().expect("mask should be of struct type");
|
||||
let mask_num_units = struct_type.get_field_count();
|
||||
let mut mask_elements = vec![];
|
||||
for i in 0..mask_num_units {
|
||||
let field = struct_type.get_field(i as i32);
|
||||
mask_elements.push(self.context.new_cast(
|
||||
self.location,
|
||||
mask.access_field(self.location, field).to_rvalue(),
|
||||
mask_element_type,
|
||||
));
|
||||
}
|
||||
mask_elements
|
||||
};
|
||||
let mask_num_units = mask_elements.len();
|
||||
|
||||
// NOTE: the mask needs to be the same length as the input vectors, so add the missing
|
||||
// elements in the mask if needed.
|
||||
|
||||
Reference in New Issue
Block a user