From fbbc910ddc00a9b88071aae0aa0d9bce64a3a1cc Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Fri, 20 Dec 2019 19:11:06 +0100 Subject: [PATCH] [OPT] Emit stack_{load,store} where possible --- src/pointer.rs | 91 +++++++++++++++++++++++++++++++++--------- src/value_and_place.rs | 17 ++++---- 2 files changed, 81 insertions(+), 27 deletions(-) diff --git a/src/pointer.rs b/src/pointer.rs index cadf57255cc9..3899dd15fa43 100644 --- a/src/pointer.rs +++ b/src/pointer.rs @@ -4,14 +4,27 @@ use cranelift::codegen::ir::immediates::Offset32; #[derive(Copy, Clone, Debug)] pub struct Pointer { - base_addr: Value, + base: PointerBase, offset: Offset32, } +#[derive(Copy, Clone, Debug)] +enum PointerBase { + Addr(Value), + Stack(StackSlot), +} + impl Pointer { pub fn new(addr: Value) -> Self { 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), } } @@ -19,22 +32,30 @@ impl Pointer { 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); Pointer { - base_addr: addr, + base: PointerBase::Addr(addr), offset: Offset32::new(0), } } pub fn get_addr<'a, 'tcx>(self, fx: &mut FunctionCx<'a, 'tcx, impl Backend>) -> Value { - let offset: i64 = self.offset.into(); - if offset == 0 { - self.base_addr - } else { - fx.bcx.ins().iadd_imm(self.base_addr, offset) + match self.base { + PointerBase::Addr(base_addr) => { + let offset: i64 = self.offset.into(); + if offset == 0 { + 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) { - (self.base_addr, self.offset) + pub fn try_get_addr_and_offset(self) -> Option<(Value, Offset32)> { + match self.base { + PointerBase::Addr(addr) => Some((addr, self.offset)), + PointerBase::Stack(_) => None, + } } pub fn offset<'a, 'tcx>( @@ -52,15 +73,19 @@ impl Pointer { ) -> Self { if let Some(new_offset) = self.offset.try_add_i64(extra_offset) { Pointer { - base_addr: self.base_addr, + base: self.base, offset: new_offset, } } else { let base_offset: i64 = self.offset.into(); 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 { - base_addr: addr, + base: PointerBase::Addr(addr), offset: Offset32::new(0), } } else { @@ -74,10 +99,18 @@ impl Pointer { fx: &mut FunctionCx<'a, 'tcx, impl Backend>, extra_offset: Value, ) -> Self { - let base_addr = fx.bcx.ins().iadd(self.base_addr, extra_offset); - Pointer { - base_addr, - offset: self.offset, + match self.base { + PointerBase::Addr(addr) => Pointer { + base: PointerBase::Addr(fx.bcx.ins().iadd(addr, extra_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, flags: MemFlags, ) -> 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>( @@ -96,6 +138,17 @@ impl Pointer { value: Value, 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); + } + } } } diff --git a/src/value_and_place.rs b/src/value_and_place.rs index df690468ccbb..8a497df1e7e9 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -103,9 +103,12 @@ impl<'tcx> CValue<'tcx> { pub fn try_to_addr(self) -> Option { match self.0 { CValueInner::ByRef(ptr) => { - let (base_addr, offset) = ptr.get_addr_and_offset(); - if offset == Offset32::new(0) { - Some(base_addr) + if let Some((base_addr, offset)) = ptr.try_get_addr_and_offset() { + if offset == Offset32::new(0) { + Some(base_addr) + } else { + None + } } else { None } @@ -314,7 +317,7 @@ impl<'tcx> CPlace<'tcx> { CValue::by_ref(ptr, layout) } 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, ), CPlaceInner::NoPlace => CValue::by_ref( @@ -338,7 +341,7 @@ impl<'tcx> CPlace<'tcx> { match self.inner { CPlaceInner::Addr(ptr, extra) => (ptr, extra), CPlaceInner::Stack(stack_slot) => ( - Pointer::new(fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 0)), + Pointer::stack_slot(stack_slot), None, ), CPlaceInner::NoPlace => { @@ -428,9 +431,7 @@ impl<'tcx> CPlace<'tcx> { return; } CPlaceInner::Addr(ptr, None) => ptr, - CPlaceInner::Stack(stack_slot) => { - Pointer::new(fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 0)) - } + CPlaceInner::Stack(stack_slot) => Pointer::stack_slot(stack_slot), CPlaceInner::NoPlace => { if dst_layout.abi != Abi::Uninhabited { assert_eq!(dst_layout.size.bytes(), 0, "{:?}", dst_layout);