Skip to content

Commit 9dd9391

Browse files
committed
Extract common logic for converting vector masks to i1 vectors and make it use the sign bit instead of lowest bit consistently
1 parent b8b2b8d commit 9dd9391

File tree

1 file changed

+50
-57
lines changed

1 file changed

+50
-57
lines changed

compiler/rustc_codegen_llvm/src/intrinsic.rs

+50-57
Original file line numberDiff line numberDiff line change
@@ -854,6 +854,20 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
854854
};
855855
}
856856

857+
fn vector_mask_to_bitmask<'a, 'll, 'tcx>(
858+
bx: &mut Builder<'a, 'll, 'tcx>,
859+
i_xn: &'ll Value,
860+
in_elem_bitwidth: u64,
861+
in_len: u64,
862+
) -> &'ll Value {
863+
// Shift the MSB to the right by "in_elem_bitwidth - 1" into the first bit position.
864+
let shift_idx = bx.cx.const_int(bx.type_ix(in_elem_bitwidth), (in_elem_bitwidth - 1) as _);
865+
let shift_indices = vec![shift_idx; in_len as _];
866+
let i_xn_msb = bx.lshr(i_xn, bx.const_vector(shift_indices.as_slice()));
867+
// Truncate vector to an <i1 x N>
868+
bx.trunc(i_xn_msb, bx.type_vector(bx.type_i1(), in_len))
869+
}
870+
857871
let tcx = bx.tcx();
858872
let sig =
859873
tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), callee_ty.fn_sig(tcx));
@@ -1061,14 +1075,11 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
10611075
m_len == v_len,
10621076
InvalidMonomorphization::MismatchedLengths { span, name, m_len, v_len }
10631077
);
1064-
match m_elem_ty.kind() {
1065-
ty::Int(_) => {}
1078+
let in_elem_bitwidth = match m_elem_ty.kind() {
1079+
ty::Int(i) => i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size.bits()),
10661080
_ => return_error!(InvalidMonomorphization::MaskType { span, name, ty: m_elem_ty }),
1067-
}
1068-
// truncate the mask to a vector of i1s
1069-
let i1 = bx.type_i1();
1070-
let i1xn = bx.type_vector(i1, m_len as u64);
1071-
let m_i1s = bx.trunc(args[0].immediate(), i1xn);
1081+
};
1082+
let m_i1s = vector_mask_to_bitmask(bx, args[0].immediate(), in_elem_bitwidth, m_len);
10721083
return Ok(bx.select(m_i1s, args[1].immediate(), args[2].immediate()));
10731084
}
10741085

@@ -1103,15 +1114,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
11031114
}),
11041115
};
11051116

1106-
// Shift the MSB to the right by "in_elem_bitwidth - 1" into the first bit position.
1107-
let shift_indices =
1108-
vec![
1109-
bx.cx.const_int(bx.type_ix(in_elem_bitwidth), (in_elem_bitwidth - 1) as _);
1110-
in_len as _
1111-
];
1112-
let i_xn_msb = bx.lshr(i_xn, bx.const_vector(shift_indices.as_slice()));
1113-
// Truncate vector to an <i1 x N>
1114-
let i1xn = bx.trunc(i_xn_msb, bx.type_vector(bx.type_i1(), in_len));
1117+
let i1xn = vector_mask_to_bitmask(bx, i_xn, in_elem_bitwidth, in_len);
11151118
// Bitcast <i1 x N> to iN:
11161119
let i_ = bx.bitcast(i1xn, bx.type_ix(in_len));
11171120

@@ -1377,31 +1380,25 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
13771380

13781381
// The element type of the third argument must be a signed integer type of any width:
13791382
let (_, element_ty2) = arg_tys[2].simd_size_and_type(bx.tcx());
1380-
match element_ty2.kind() {
1381-
ty::Int(_) => (),
1383+
let mask_elem_bitwidth = match element_ty2.kind() {
1384+
ty::Int(i) => i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size.bits()),
13821385
_ => {
1383-
require!(
1384-
false,
1385-
InvalidMonomorphization::ThirdArgElementType {
1386-
span,
1387-
name,
1388-
expected_element: element_ty2,
1389-
third_arg: arg_tys[2]
1390-
}
1391-
);
1386+
return_error!(InvalidMonomorphization::ThirdArgElementType {
1387+
span,
1388+
name,
1389+
expected_element: element_ty2,
1390+
third_arg: arg_tys[2]
1391+
})
13921392
}
1393-
}
1393+
};
13941394

13951395
// Alignment of T, must be a constant integer value:
13961396
let alignment_ty = bx.type_i32();
13971397
let alignment = bx.const_i32(bx.align_of(in_elem).bytes() as i32);
13981398

13991399
// Truncate the mask vector to a vector of i1s:
1400-
let (mask, mask_ty) = {
1401-
let i1 = bx.type_i1();
1402-
let i1xn = bx.type_vector(i1, in_len);
1403-
(bx.trunc(args[2].immediate(), i1xn), i1xn)
1404-
};
1400+
let mask = vector_mask_to_bitmask(bx, args[2].immediate(), mask_elem_bitwidth, in_len);
1401+
let mask_ty = bx.type_vector(bx.type_i1(), in_len);
14051402

14061403
// Type of the vector of pointers:
14071404
let llvm_pointer_vec_ty = llvm_vector_ty(bx, underlying_ty, in_len, pointer_count);
@@ -1518,31 +1515,25 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
15181515
assert_eq!(underlying_ty, non_ptr(element_ty0));
15191516

15201517
// The element type of the third argument must be a signed integer type of any width:
1521-
match element_ty2.kind() {
1522-
ty::Int(_) => (),
1518+
let mask_elem_bitwidth = match element_ty2.kind() {
1519+
ty::Int(i) => i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size.bits()),
15231520
_ => {
1524-
require!(
1525-
false,
1526-
InvalidMonomorphization::ThirdArgElementType {
1527-
span,
1528-
name,
1529-
expected_element: element_ty2,
1530-
third_arg: arg_tys[2]
1531-
}
1532-
);
1521+
return_error!(InvalidMonomorphization::ThirdArgElementType {
1522+
span,
1523+
name,
1524+
expected_element: element_ty2,
1525+
third_arg: arg_tys[2]
1526+
});
15331527
}
1534-
}
1528+
};
15351529

15361530
// Alignment of T, must be a constant integer value:
15371531
let alignment_ty = bx.type_i32();
15381532
let alignment = bx.const_i32(bx.align_of(in_elem).bytes() as i32);
15391533

15401534
// Truncate the mask vector to a vector of i1s:
1541-
let (mask, mask_ty) = {
1542-
let i1 = bx.type_i1();
1543-
let i1xn = bx.type_vector(i1, in_len);
1544-
(bx.trunc(args[2].immediate(), i1xn), i1xn)
1545-
};
1535+
let mask = vector_mask_to_bitmask(bx, args[2].immediate(), mask_elem_bitwidth, in_len);
1536+
let mask_ty = bx.type_vector(bx.type_i1(), in_len);
15461537

15471538
let ret_t = bx.type_void();
15481539

@@ -1682,8 +1673,13 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
16821673
);
16831674
args[0].immediate()
16841675
} else {
1685-
match in_elem.kind() {
1686-
ty::Int(_) | ty::Uint(_) => {}
1676+
let bitwidth = match in_elem.kind() {
1677+
ty::Int(i) => {
1678+
i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size.bits())
1679+
}
1680+
ty::Uint(i) => {
1681+
i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size.bits())
1682+
}
16871683
_ => return_error!(InvalidMonomorphization::UnsupportedSymbol {
16881684
span,
16891685
name,
@@ -1692,12 +1688,9 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
16921688
in_elem,
16931689
ret_ty
16941690
}),
1695-
}
1691+
};
16961692

1697-
// boolean reductions operate on vectors of i1s:
1698-
let i1 = bx.type_i1();
1699-
let i1xn = bx.type_vector(i1, in_len as u64);
1700-
bx.trunc(args[0].immediate(), i1xn)
1693+
vector_mask_to_bitmask(bx, args[0].immediate(), bitwidth, in_len as _)
17011694
};
17021695
return match in_elem.kind() {
17031696
ty::Int(_) | ty::Uint(_) => {

0 commit comments

Comments
 (0)