]> git.lizzy.rs Git - rust.git/commitdiff
[OPT] Emit stack_{load,store} where possible
authorbjorn3 <bjorn3@users.noreply.github.com>
Fri, 20 Dec 2019 18:11:06 +0000 (19:11 +0100)
committerbjorn3 <bjorn3@users.noreply.github.com>
Fri, 20 Dec 2019 18:30:56 +0000 (19:30 +0100)
src/pointer.rs
src/value_and_place.rs

index cadf57255cc9ea719eb5be4af2b81e8cfc21bb83..3899dd15fa43d0f2711e1a6c1dbb906f65614a53 100644 (file)
@@ -4,14 +4,27 @@
 
 #[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 @@ pub fn new(addr: Value) -> 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);
         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 @@ pub fn offset_i64<'a, 'tcx>(
     ) -> 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 @@ pub fn offset_value<'a, 'tcx>(
         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 @@ pub fn load<'a, 'tcx>(
         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 @@ pub fn store<'a, 'tcx>(
         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);
+            }
+        }
     }
 }
index df690468ccbbc8cfc3fb3c1a940291ec695b2a10..8a497df1e7e9327bf7d20756717b8de192677709 100644 (file)
@@ -103,9 +103,12 @@ pub fn force_stack<'a>(self, fx: &mut FunctionCx<'_, 'tcx, impl Backend>) -> Poi
     pub fn try_to_addr(self) -> Option<Value> {
         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 @@ pub fn to_cvalue(self, fx: &mut FunctionCx<'_, 'tcx, impl Backend>) -> CValue<'t
                 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 @@ pub fn to_ptr_maybe_unsized(
         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 @@ fn assert_assignable<'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);