Compare commits

..

No commits in common. "cb88edea1f1d91e7db72f7bd03aa9a4ba0aa0ff3" and "9c43dafcf5cb44e30d88bff257bb2fb1327dc9c2" have entirely different histories.

6 changed files with 70 additions and 84 deletions

View file

@ -544,23 +544,10 @@ main := fn(): int {
```hb
Color := struct {r: u8, g: u8, b: u8, a: u8}
white := Color.(255, 255, 255, 255)
u32_to_color := fn(v: u32): Color return @as(Color, @bitcast(u32_to_u32(@bitcast(v))))
u32_to_color := fn(v: u32): Color return @bitcast(v)
u32_to_u32 := fn(v: u32): u32 return v
main := fn(): int {
return u32_to_color(@bitcast(white)).r
}
```
#### small_struct_assignment
```hb
Color := struct {r: u8, g: u8, b: u8, a: u8}
white := Color.(255, 255, 255, 255)
black := Color.(0, 0, 0, 0)
main := fn(): int {
f := black
f = white
return f.a
return u32_to_color(@bitcast(white)).r + @as(Color, @bitcast(u32_to_u32(@bitcast(white)))).g
}
```

View file

@ -39,6 +39,16 @@ type Nid = u16;
type Lookup = crate::ctx_map::CtxMap<Nid>;
trait StoreId: Sized {
fn to_store(self) -> Option<Self>;
}
impl StoreId for Nid {
fn to_store(self) -> Option<Self> {
(self != MEM).then_some(self)
}
}
impl crate::ctx_map::CtxEntry for Nid {
type Ctx = [Result<Node, (Nid, debug::Trace)>];
type Key<'a> = (Kind, &'a [Nid], ty::Id);
@ -447,7 +457,6 @@ impl Nodes {
K::Stre => {
if self[target].inputs[2] != VOID
&& self[target].inputs.len() == 4
&& self[self[target].inputs[1]].kind != Kind::Load
&& self[self[target].inputs[3]].kind == Kind::Stre
&& self[self[target].inputs[3]].lock_rc == 0
&& self[self[target].inputs[3]].inputs[2] == self[target].inputs[2]
@ -863,7 +872,7 @@ impl Nodes {
#[allow(dead_code)]
fn eliminate_stack_temporaries(&mut self) {
'o: for stack in self[MEM].outputs.clone() {
if self.values[stack as usize].is_err() || self[stack].kind != Kind::Stck {
if self[stack].kind != Kind::Stck {
continue;
}
let mut full_read_into = None;
@ -1023,7 +1032,7 @@ pub enum Kind {
impl Kind {
fn is_pinned(&self) -> bool {
self.is_cfg() || matches!(self, Self::Phi | Self::Arg | Self::Mem)
self.is_cfg() || matches!(self, Self::Phi | Self::Mem | Self::Arg)
}
fn is_cfg(&self) -> bool {
@ -1620,7 +1629,7 @@ impl ItemCtx {
if !matches!(self.nodes[stck].kind, Kind::Stck | Kind::Arg) {
debug_assert_matches!(
self.nodes[stck].kind,
Kind::Phi | Kind::Return | Kind::Load | Kind::Call { .. } | Kind::Stre
Kind::Phi | Kind::Return | Kind::Load
);
continue;
}
@ -2036,8 +2045,11 @@ impl<'a> Codegen<'a> {
);
debug_assert!(self.ci.nodes[region].kind != Kind::Stre);
let mut vc = Vc::from([VOID, value, region]);
self.ci.nodes.load_loop_store(&mut self.ci.scope.store, &mut self.ci.loops);
let mut vc = Vc::from([VOID, value, region, self.ci.scope.store.value()]);
if let Some(str) = self.ci.scope.store.value().to_store() {
vc.push(str);
}
for load in self.ci.scope.loads.drain(..) {
if load == value {
self.ci.nodes.unlock(load);
@ -2068,8 +2080,11 @@ impl<'a> Codegen<'a> {
self.ty_display(self.ci.nodes[region].ty)
);
debug_assert!(self.ci.nodes[region].kind != Kind::Stre);
let mut vc = Vc::from([VOID, region]);
self.ci.nodes.load_loop_store(&mut self.ci.scope.store, &mut self.ci.loops);
let vc = [VOID, region, self.ci.scope.store.value()];
if let Some(str) = self.ci.scope.store.value().to_store() {
vc.push(str);
}
let load = self.ci.nodes.new_node(ty, Kind::Load, vc);
self.ci.nodes.lock(load);
self.ci.scope.loads.push(load);
@ -2191,7 +2206,9 @@ impl<'a> Codegen<'a> {
debug_assert_ne!(self.ci.ctrl, VOID);
let mut inps = Vc::from([self.ci.ctrl, value.id]);
self.ci.nodes.load_loop_store(&mut self.ci.scope.store, &mut self.ci.loops);
inps.push(self.ci.scope.store.value());
if let Some(str) = self.ci.scope.store.value().to_store() {
inps.push(str);
}
self.ci.ctrl = self.ci.nodes.new_node(ty::Id::VOID, Kind::Return, inps);
@ -2553,7 +2570,9 @@ impl<'a> Codegen<'a> {
self.ci.nodes.unlock(n);
}
inps.push(self.ci.scope.store.value());
if let Some(str) = self.ci.scope.store.value().to_store() {
inps.push(str);
}
self.ci.scope.loads.retain(|&load| {
if inps.contains(&load) {
return true;
@ -2639,7 +2658,9 @@ impl<'a> Codegen<'a> {
}
if has_ptr_arg {
inps.push(self.ci.scope.store.value());
if let Some(str) = self.ci.scope.store.value().to_store() {
inps.push(str);
}
self.ci.scope.loads.retain(|&load| {
if inps.contains(&load) {
return true;
@ -4222,7 +4243,7 @@ fn push_up(nodes: &mut Nodes) {
return;
}
for i in 1..nodes[node].inputs.len() {
for i in 0..nodes[node].inputs.len() {
let inp = nodes[node].inputs[i];
if !nodes[inp].kind.is_pinned() {
push_up_impl(inp, nodes);
@ -4277,20 +4298,6 @@ fn push_up(nodes: &mut Nodes) {
}
}
}
debug_assert_eq!(
nodes
.iter()
.map(|(n, _)| n)
.filter(|&n| !nodes.visited.get(n) && !matches!(nodes[n].kind, Kind::Arg | Kind::Mem))
.collect::<Vec<_>>(),
vec![],
"{:?}",
nodes
.iter()
.filter(|&(n, nod)| !nodes.visited.get(n) && !matches!(nod.kind, Kind::Arg | Kind::Mem))
.collect::<Vec<_>>()
);
}
fn push_down(nodes: &mut Nodes, node: Nid) {
@ -4305,7 +4312,6 @@ fn push_down(nodes: &mut Nodes, node: Nid) {
}
fn better(nodes: &mut Nodes, is: Nid, then: Nid) -> bool {
debug_assert_ne!(idepth(nodes, is), idepth(nodes, then), "{is} {then}");
loop_depth(is, nodes) < loop_depth(then, nodes)
|| idepth(nodes, is) > idepth(nodes, then)
|| nodes[then].kind == Kind::If
@ -4315,12 +4321,6 @@ fn push_down(nodes: &mut Nodes, node: Nid) {
return;
}
for usage in nodes[node].outputs.clone() {
if is_forward_edge(usage, node, nodes) && nodes[node].kind == Kind::Stre {
push_down(nodes, usage);
}
}
for usage in nodes[node].outputs.clone() {
if is_forward_edge(usage, node, nodes) {
push_down(nodes, usage);
@ -4342,11 +4342,14 @@ fn push_down(nodes: &mut Nodes, node: Nid) {
debug_assert!(nodes.dominates(nodes[node].inputs[0], min));
let mut cursor = min;
while cursor != nodes[node].inputs[0] {
cursor = idom(nodes, cursor);
loop {
if better(nodes, cursor, min) {
min = cursor;
}
if cursor == nodes[node].inputs[0] {
break;
}
cursor = idom(nodes, cursor);
}
if nodes[min].kind.ends_basic_block() {
@ -4465,7 +4468,6 @@ mod tests {
// Purely Testing Examples;
returning_global_struct;
small_struct_bitcast;
small_struct_assignment;
wide_ret;
comptime_min_reg_leak;
different_types;

View file

@ -287,6 +287,7 @@ impl BitSet {
self.data.resize(new_len, 0);
}
#[track_caller]
pub fn set(&mut self, idx: Nid) -> bool {
let idx = idx as usize;
let data_idx = idx / Self::ELEM_SIZE;
@ -295,12 +296,4 @@ impl BitSet {
self.data[data_idx] |= 1 << sub_idx;
prev == 0
}
pub fn get(&self, idx: Nid) -> bool {
let idx = idx as usize;
let data_idx = idx / Self::ELEM_SIZE;
let sub_idx = idx % Self::ELEM_SIZE;
let prev = self.data[data_idx] & (1 << sub_idx);
prev != 0
}
}

View file

@ -1,17 +1,17 @@
main:
LI64 r5, 0d
LRA r4, r0, :gb
LI64 r10, 6d
LD r7, r4, 0a, 8h
CMPS r11, r7, r5
CMPUI r11, r11, 0d
ORI r12, r11, 0d
ANDI r12, r12, 255d
JNE r12, r0, :0
CP r5, r10
LD r6, r4, 0a, 8h
CMPS r9, r6, r5
CMPUI r9, r9, 0d
ORI r11, r9, 0d
LI64 r1, 6d
ANDI r11, r11, 255d
JNE r11, r0, :0
CP r5, r1
JMP :1
0: LI64 r5, 1d
1: SUB64 r1, r5, r10
1: SUB64 r1, r5, r1
JALA r0, r31, 0a
code size: 131
ret: 0

View file

@ -1,29 +1,33 @@
main:
ADDI64 r254, r254, -12d
ST r31, r254, 4a, 8h
ADDI64 r254, r254, -24d
ST r31, r254, 8a, 16h
LRA r1, r0, :white
ADDI64 r4, r254, 0d
LD r2, r1, 0a, 4h
LD r32, r1, 0a, 4h
ADDI64 r5, r254, 4d
CP r2, r32
JAL r31, r0, :u32_to_color
ST r1, r254, 4a, 4h
CP r2, r32
JAL r31, r0, :u32_to_u32
ADDI64 r12, r254, 0d
LD r11, r254, 4a, 1h
ST r1, r254, 0a, 4h
LD r9, r254, 0a, 1h
ANDI r1, r9, 255d
LD r31, r254, 4a, 8h
ADDI64 r254, r254, 12d
LD r4, r254, 1a, 1h
ADD8 r7, r4, r11
ANDI r1, r7, 255d
LD r31, r254, 8a, 16h
ADDI64 r254, r254, 24d
JALA r0, r31, 0a
u32_to_color:
ADDI64 r254, r254, -12d
ST r31, r254, 4a, 8h
JAL r31, r0, :u32_to_u32
ADDI64 r5, r254, 0d
ST r1, r254, 0a, 4h
LD r1, r5, 0a, 4h
LD r31, r254, 4a, 8h
ADDI64 r254, r254, 12d
ADDI64 r254, r254, -4d
ADDI64 r3, r254, 0d
ST r2, r254, 0a, 4h
LD r1, r3, 0a, 4h
ADDI64 r254, r254, 4d
JALA r0, r31, 0a
u32_to_u32:
CP r1, r2
JALA r0, r31, 0a
code size: 263
ret: 255
code size: 284
ret: 254
status: Ok(())