[OPT] Emit stack_{load,store} where possible
This commit is contained in:
parent
8f5ef6172c
commit
fbbc910ddc
2 changed files with 81 additions and 27 deletions
|
@ -4,14 +4,27 @@ use cranelift::codegen::ir::immediates::Offset32;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub struct Pointer {
|
pub struct Pointer {
|
||||||
base_addr: Value,
|
base: PointerBase,
|
||||||
offset: Offset32,
|
offset: Offset32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
enum PointerBase {
|
||||||
|
Addr(Value),
|
||||||
|
Stack(StackSlot),
|
||||||
|
}
|
||||||
|
|
||||||
impl Pointer {
|
impl Pointer {
|
||||||
pub fn new(addr: Value) -> Self {
|
pub fn new(addr: Value) -> Self {
|
||||||
Pointer {
|
Pointer {
|
||||||
base_addr: addr,
|
base: PointerBase::Addr(addr),
|
||||||
|
offset: Offset32::new(0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn stack_slot(stack_slot: StackSlot) -> Self {
|
||||||
|
Pointer {
|
||||||
|
base: PointerBase::Stack(stack_slot),
|
||||||
offset: Offset32::new(0),
|
offset: Offset32::new(0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,22 +32,30 @@ impl Pointer {
|
||||||
pub fn const_addr<'a, 'tcx>(fx: &mut FunctionCx<'a, 'tcx, impl Backend>, addr: i64) -> Self {
|
pub fn const_addr<'a, 'tcx>(fx: &mut FunctionCx<'a, 'tcx, impl Backend>, addr: i64) -> Self {
|
||||||
let addr = fx.bcx.ins().iconst(fx.pointer_type, addr);
|
let addr = fx.bcx.ins().iconst(fx.pointer_type, addr);
|
||||||
Pointer {
|
Pointer {
|
||||||
base_addr: addr,
|
base: PointerBase::Addr(addr),
|
||||||
offset: Offset32::new(0),
|
offset: Offset32::new(0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_addr<'a, 'tcx>(self, fx: &mut FunctionCx<'a, 'tcx, impl Backend>) -> Value {
|
pub fn get_addr<'a, 'tcx>(self, fx: &mut FunctionCx<'a, 'tcx, impl Backend>) -> Value {
|
||||||
let offset: i64 = self.offset.into();
|
match self.base {
|
||||||
if offset == 0 {
|
PointerBase::Addr(base_addr) => {
|
||||||
self.base_addr
|
let offset: i64 = self.offset.into();
|
||||||
} else {
|
if offset == 0 {
|
||||||
fx.bcx.ins().iadd_imm(self.base_addr, offset)
|
base_addr
|
||||||
|
} else {
|
||||||
|
fx.bcx.ins().iadd_imm(base_addr, offset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PointerBase::Stack(stack_slot) => fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, self.offset),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_addr_and_offset(self) -> (Value, Offset32) {
|
pub fn try_get_addr_and_offset(self) -> Option<(Value, Offset32)> {
|
||||||
(self.base_addr, self.offset)
|
match self.base {
|
||||||
|
PointerBase::Addr(addr) => Some((addr, self.offset)),
|
||||||
|
PointerBase::Stack(_) => None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn offset<'a, 'tcx>(
|
pub fn offset<'a, 'tcx>(
|
||||||
|
@ -52,15 +73,19 @@ impl Pointer {
|
||||||
) -> Self {
|
) -> Self {
|
||||||
if let Some(new_offset) = self.offset.try_add_i64(extra_offset) {
|
if let Some(new_offset) = self.offset.try_add_i64(extra_offset) {
|
||||||
Pointer {
|
Pointer {
|
||||||
base_addr: self.base_addr,
|
base: self.base,
|
||||||
offset: new_offset,
|
offset: new_offset,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let base_offset: i64 = self.offset.into();
|
let base_offset: i64 = self.offset.into();
|
||||||
if let Some(new_offset) = base_offset.checked_add(extra_offset){
|
if let Some(new_offset) = base_offset.checked_add(extra_offset){
|
||||||
let addr = fx.bcx.ins().iadd_imm(self.base_addr, new_offset);
|
let base_addr = match self.base {
|
||||||
|
PointerBase::Addr(addr) => addr,
|
||||||
|
PointerBase::Stack(stack_slot) => fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 0),
|
||||||
|
};
|
||||||
|
let addr = fx.bcx.ins().iadd_imm(base_addr, new_offset);
|
||||||
Pointer {
|
Pointer {
|
||||||
base_addr: addr,
|
base: PointerBase::Addr(addr),
|
||||||
offset: Offset32::new(0),
|
offset: Offset32::new(0),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -74,10 +99,18 @@ impl Pointer {
|
||||||
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
|
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
|
||||||
extra_offset: Value,
|
extra_offset: Value,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let base_addr = fx.bcx.ins().iadd(self.base_addr, extra_offset);
|
match self.base {
|
||||||
Pointer {
|
PointerBase::Addr(addr) => Pointer {
|
||||||
base_addr,
|
base: PointerBase::Addr(fx.bcx.ins().iadd(addr, extra_offset)),
|
||||||
offset: self.offset,
|
offset: self.offset,
|
||||||
|
},
|
||||||
|
PointerBase::Stack(stack_slot) => {
|
||||||
|
let base_addr = fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, self.offset);
|
||||||
|
Pointer {
|
||||||
|
base: PointerBase::Addr(fx.bcx.ins().iadd(base_addr, extra_offset)),
|
||||||
|
offset: Offset32::new(0),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +120,16 @@ impl Pointer {
|
||||||
ty: Type,
|
ty: Type,
|
||||||
flags: MemFlags,
|
flags: MemFlags,
|
||||||
) -> Value {
|
) -> Value {
|
||||||
fx.bcx.ins().load(ty, flags, self.base_addr, self.offset)
|
match self.base {
|
||||||
|
PointerBase::Addr(base_addr) => fx.bcx.ins().load(ty, flags, base_addr, self.offset),
|
||||||
|
PointerBase::Stack(stack_slot) => if ty == types::I128 {
|
||||||
|
// WORKAROUND for stack_load.i128 not being implemented
|
||||||
|
let base_addr = fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 0);
|
||||||
|
fx.bcx.ins().load(ty, flags, base_addr, self.offset)
|
||||||
|
} else {
|
||||||
|
fx.bcx.ins().stack_load(ty, stack_slot, self.offset)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn store<'a, 'tcx>(
|
pub fn store<'a, 'tcx>(
|
||||||
|
@ -96,6 +138,17 @@ impl Pointer {
|
||||||
value: Value,
|
value: Value,
|
||||||
flags: MemFlags,
|
flags: MemFlags,
|
||||||
) {
|
) {
|
||||||
fx.bcx.ins().store(flags, value, self.base_addr, self.offset);
|
match self.base {
|
||||||
|
PointerBase::Addr(base_addr) => {
|
||||||
|
fx.bcx.ins().store(flags, value, base_addr, self.offset);
|
||||||
|
}
|
||||||
|
PointerBase::Stack(stack_slot) => if fx.bcx.func.dfg.value_type(value) == types::I128 {
|
||||||
|
// WORKAROUND for stack_load.i128 not being implemented
|
||||||
|
let base_addr = fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 0);
|
||||||
|
fx.bcx.ins().store(flags, value, base_addr, self.offset);
|
||||||
|
} else {
|
||||||
|
fx.bcx.ins().stack_store(value, stack_slot, self.offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,9 +103,12 @@ impl<'tcx> CValue<'tcx> {
|
||||||
pub fn try_to_addr(self) -> Option<Value> {
|
pub fn try_to_addr(self) -> Option<Value> {
|
||||||
match self.0 {
|
match self.0 {
|
||||||
CValueInner::ByRef(ptr) => {
|
CValueInner::ByRef(ptr) => {
|
||||||
let (base_addr, offset) = ptr.get_addr_and_offset();
|
if let Some((base_addr, offset)) = ptr.try_get_addr_and_offset() {
|
||||||
if offset == Offset32::new(0) {
|
if offset == Offset32::new(0) {
|
||||||
Some(base_addr)
|
Some(base_addr)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -314,7 +317,7 @@ impl<'tcx> CPlace<'tcx> {
|
||||||
CValue::by_ref(ptr, layout)
|
CValue::by_ref(ptr, layout)
|
||||||
}
|
}
|
||||||
CPlaceInner::Stack(stack_slot) => CValue::by_ref(
|
CPlaceInner::Stack(stack_slot) => CValue::by_ref(
|
||||||
Pointer::new(fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 0)),
|
Pointer::stack_slot(stack_slot),
|
||||||
layout,
|
layout,
|
||||||
),
|
),
|
||||||
CPlaceInner::NoPlace => CValue::by_ref(
|
CPlaceInner::NoPlace => CValue::by_ref(
|
||||||
|
@ -338,7 +341,7 @@ impl<'tcx> CPlace<'tcx> {
|
||||||
match self.inner {
|
match self.inner {
|
||||||
CPlaceInner::Addr(ptr, extra) => (ptr, extra),
|
CPlaceInner::Addr(ptr, extra) => (ptr, extra),
|
||||||
CPlaceInner::Stack(stack_slot) => (
|
CPlaceInner::Stack(stack_slot) => (
|
||||||
Pointer::new(fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 0)),
|
Pointer::stack_slot(stack_slot),
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
CPlaceInner::NoPlace => {
|
CPlaceInner::NoPlace => {
|
||||||
|
@ -428,9 +431,7 @@ impl<'tcx> CPlace<'tcx> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
CPlaceInner::Addr(ptr, None) => ptr,
|
CPlaceInner::Addr(ptr, None) => ptr,
|
||||||
CPlaceInner::Stack(stack_slot) => {
|
CPlaceInner::Stack(stack_slot) => Pointer::stack_slot(stack_slot),
|
||||||
Pointer::new(fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 0))
|
|
||||||
}
|
|
||||||
CPlaceInner::NoPlace => {
|
CPlaceInner::NoPlace => {
|
||||||
if dst_layout.abi != Abi::Uninhabited {
|
if dst_layout.abi != Abi::Uninhabited {
|
||||||
assert_eq!(dst_layout.size.bytes(), 0, "{:?}", dst_layout);
|
assert_eq!(dst_layout.size.bytes(), 0, "{:?}", dst_layout);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue