Skip to content

Commit 7d177e6

Browse files
committed
Made the logical shift / artihmetic shift not relly on signs of intigers
1 parent f0ab82f commit 7d177e6

File tree

3 files changed

+62
-32
lines changed

3 files changed

+62
-32
lines changed

src/builder.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,11 @@ use crate::type_of::LayoutGccExt;
4040

4141
// TODO(antoyo)
4242
type Funclet = ();
43-
43+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
44+
pub enum ShiftKind {
45+
Logical,
46+
Arithmetic,
47+
}
4448
enum ExtremumOperation {
4549
Max,
4650
Min,
@@ -827,13 +831,13 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
827831
}
828832

829833
fn lshr(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
830-
self.gcc_lshr(a, b)
834+
self.gcc_shr(a, b, ShiftKind::Logical)
831835
}
832836

833837
fn ashr(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
834838
// TODO(antoyo): check whether behavior is an arithmetic shift for >> .
835839
// It seems to be if the value is signed.
836-
self.gcc_lshr(a, b)
840+
self.gcc_shr(a, b, ShiftKind::Arithmetic)
837841
}
838842

839843
fn and(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {

src/int.rs

Lines changed: 48 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use rustc_middle::ty::{self, Ty};
1414
use rustc_target::callconv::{ArgAbi, ArgAttributes, FnAbi, PassMode};
1515
use rustc_type_ir::{Interner, TyKind};
1616

17-
use crate::builder::{Builder, ToGccComp};
17+
use crate::builder::{Builder, ShiftKind, ToGccComp};
1818
use crate::common::{SignType, TypeReflection};
1919
use crate::context::CodegenCx;
2020

@@ -68,36 +68,59 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
6868
self.cx.bitwise_operation(BinaryOp::BitwiseAnd, a, b, self.location)
6969
}
7070

71-
pub fn gcc_lshr(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
71+
pub fn gcc_shr(
72+
&mut self,
73+
a: RValue<'gcc>,
74+
b: RValue<'gcc>,
75+
shift_kind: ShiftKind,
76+
) -> RValue<'gcc> {
7277
let a_type = a.get_type();
7378
let b_type = b.get_type();
7479
let a_native = self.is_native_int_type(a_type);
7580
let b_native = self.is_native_int_type(b_type);
7681
if a_native && b_native {
77-
// FIXME(antoyo): remove the casts when libgccjit can shift an unsigned number by a signed number.
78-
// TODO(antoyo): cast to unsigned to do a logical shift if that does not work.
79-
if a_type.is_signed(self) != b_type.is_signed(self) {
80-
let b = self.context.new_cast(self.location, b, a_type);
81-
a >> b
82-
} else {
83-
let a_size = a_type.get_size();
84-
let b_size = b_type.get_size();
85-
match a_size.cmp(&b_size) {
86-
std::cmp::Ordering::Less => {
87-
let a = self.context.new_cast(self.location, a, b_type);
88-
a >> b
89-
}
90-
std::cmp::Ordering::Equal => a >> b,
91-
std::cmp::Ordering::Greater => {
92-
let b = self.context.new_cast(self.location, b, a_type);
93-
a >> b
94-
}
82+
let (a, a_type) = match (shift_kind, a_type.is_signed(self.cx)) {
83+
(ShiftKind::Logical, true) => {
84+
let a_type = a_type.to_unsigned(self.cx);
85+
(self.gcc_int_cast(a, a_type), a_type)
86+
}
87+
(ShiftKind::Logical, false) => (a, a_type),
88+
(ShiftKind::Arithmetic, true) => (a, a_type),
89+
(ShiftKind::Arithmetic, false) => {
90+
let a_type = a_type.to_signed(self.cx);
91+
(self.gcc_int_cast(a, a_type), a_type)
92+
}
93+
};
94+
let (b, b_type) = match (shift_kind, b_type.is_signed(self.cx)) {
95+
(ShiftKind::Logical, true) => {
96+
let b_type = b_type.to_unsigned(self.cx);
97+
(self.gcc_int_cast(b, b_type), b_type)
98+
}
99+
(ShiftKind::Logical, false) => (b, b_type),
100+
(ShiftKind::Arithmetic, true) => (b, b_type),
101+
(ShiftKind::Arithmetic, false) => {
102+
let b_type = b_type.to_signed(self.cx);
103+
(self.gcc_int_cast(b, b_type), b_type)
104+
}
105+
};
106+
107+
let a_size = a_type.get_size();
108+
let b_size = b_type.get_size();
109+
match a_size.cmp(&b_size) {
110+
std::cmp::Ordering::Less => {
111+
let a = self.context.new_cast(self.location, a, b_type);
112+
a >> b
113+
}
114+
std::cmp::Ordering::Equal => a >> b,
115+
std::cmp::Ordering::Greater => {
116+
let b = self.context.new_cast(self.location, b, a_type);
117+
a >> b
95118
}
96119
}
97120
} else if a_type.is_vector() && b_type.is_vector() {
98121
a >> b
99122
} else if a_native && !b_native {
100-
self.gcc_lshr(a, self.gcc_int_cast(b, a_type))
123+
self.gcc_shr(a, self.gcc_int_cast(b, a_type), shift_kind)
101124
} else {
102125
// NOTE: we cannot use the lshr builtin because it's calling hi() (to get the most
103126
// significant half of the number) which uses lshr.
@@ -122,7 +145,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
122145

123146
let shift_value = self.gcc_sub(b, sixty_four);
124147
let high = self.high(a);
125-
let sign = if a_type.is_signed(self) { high >> sixty_three } else { zero };
148+
let sign = match shift_kind{
149+
ShiftKind::Logical => zero,
150+
ShiftKind::Arithmetic => high >> sixty_three,
151+
};
126152
let array_value = self.concat_low_high_rvalues(a_type, high >> shift_value, sign);
127153
then_block.add_assignment(self.location, result, array_value);
128154
then_block.end_with_jump(self.location, after_block);

src/intrinsic/mod.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -865,7 +865,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
865865
128 => {
866866
// TODO(antoyo): find a more efficient implementation?
867867
let sixty_four = self.gcc_int(typ, 64);
868-
let right_shift = self.gcc_lshr(value, sixty_four);
868+
let right_shift = self.lshr(value, sixty_four);
869869
let high = self.gcc_int_cast(right_shift, self.u64_type);
870870
let low = self.gcc_int_cast(value, self.u64_type);
871871

@@ -998,7 +998,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
998998
.new_local(None, array_type, "count_loading_zeroes_results");
999999

10001000
let sixty_four = self.gcc_int(arg_type, 64);
1001-
let shift = self.gcc_lshr(arg, sixty_four);
1001+
let shift = self.lshr(arg, sixty_four);
10021002
let high = self.gcc_int_cast(shift, self.u64_type);
10031003
let low = self.gcc_int_cast(arg, self.u64_type);
10041004

@@ -1073,7 +1073,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
10731073
// TODO(antoyo): remove this if/when native 128-bit integers land in libgccjit
10741074
if value_type.is_u128(self.cx) && !self.cx.supports_128bit_integers {
10751075
let sixty_four = self.gcc_int(value_type, 64);
1076-
let right_shift = self.gcc_lshr(value, sixty_four);
1076+
let right_shift = self.lshr(value, sixty_four);
10771077
let high = self.gcc_int_cast(right_shift, self.cx.ulonglong_type);
10781078
let high = self.pop_count(high);
10791079
let low = self.gcc_int_cast(value, self.cx.ulonglong_type);
@@ -1196,12 +1196,12 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
11961196
// Return `result_type`'s maximum or minimum value on overflow
11971197
// NOTE: convert the type to unsigned to have an unsigned shift.
11981198
let unsigned_type = result_type.to_unsigned(self.cx);
1199-
let shifted = self.gcc_lshr(
1199+
let shifted = self.lshr(
12001200
self.gcc_int_cast(lhs, unsigned_type),
12011201
self.gcc_int(unsigned_type, width as i64 - 1),
12021202
);
12031203
let uint_max = self.gcc_not(self.gcc_int(unsigned_type, 0));
1204-
let int_max = self.gcc_lshr(uint_max, self.gcc_int(unsigned_type, 1));
1204+
let int_max = self.lshr(uint_max, self.gcc_int(unsigned_type, 1));
12051205
then_block.add_assignment(
12061206
self.location,
12071207
res,
@@ -1267,12 +1267,12 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
12671267
// Return `result_type`'s maximum or minimum value on overflow
12681268
// NOTE: convert the type to unsigned to have an unsigned shift.
12691269
let unsigned_type = result_type.to_unsigned(self.cx);
1270-
let shifted = self.gcc_lshr(
1270+
let shifted = self.lshr(
12711271
self.gcc_int_cast(lhs, unsigned_type),
12721272
self.gcc_int(unsigned_type, width as i64 - 1),
12731273
);
12741274
let uint_max = self.gcc_not(self.gcc_int(unsigned_type, 0));
1275-
let int_max = self.gcc_lshr(uint_max, self.gcc_int(unsigned_type, 1));
1275+
let int_max = self.lshr(uint_max, self.gcc_int(unsigned_type, 1));
12761276
then_block.add_assignment(
12771277
self.location,
12781278
res,

0 commit comments

Comments
 (0)