Skip to content

Commit

Permalink
refactor(hugr-llvm)!: Optimise the llvm types used to represent hugr …
Browse files Browse the repository at this point in the history
…sums. (#1855)

We rework `LLVMSumType` and `LLVMValueType` to have llvm representations
that
* elide the tag field when the sum type has only one variant
* elide any "uninformational" fields, i.e. `Type::UNIT`.
* elide the struct wrapper when there is only a single field
* reuse fields from other variants where possible.

In particular, the hugr `bool_t()` is now represented by `i1`.

BREAKING CHANGE: `LLVMSumValue::get_tag_type` renamed to `tag_type`.
`LLVMSumType::try_new2` renamed to `LLVMSumType::try_new`.
`LLVMSumType::get_variant` removed.

---------

Co-authored-by: Mark Koch <48097969+mark-koch@users.noreply.github.com>
  • Loading branch information
doug-q and mark-koch authored Jan 20, 2025
1 parent b38a2e8 commit 8cbbc35
Show file tree
Hide file tree
Showing 107 changed files with 2,409 additions and 1,716 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ proptest = "1.4.0"
proptest-derive = "0.5.0"
regex = "1.9.5"
regex-syntax = "0.8.3"
rstest = "0.23.0"
rstest = "0.24.0"
serde = "1.0"
serde_json = "1.0.97"
serde_yaml = "0.9.19"
Expand Down
1 change: 1 addition & 0 deletions hugr-llvm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ pathsearch = { workspace = true, optional = true }
serde_json = { workspace = true, optional = true }
serde = { workspace = true, optional = true }
typetag = { workspace = true, optional = true }
derive_more = { workspace = true, features = ["debug"] }

[dev-dependencies]
hugr-llvm = { "path" = ".", features = ["test-utils"] }
8 changes: 2 additions & 6 deletions hugr-llvm/src/custom/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,11 @@ impl<'a> TypeMapping for LLVMTypeMapping<'a> {

fn map_sum_type<'c>(
&self,
sum_type: &HugrSumType,
_sum_type: &HugrSumType,
context: TypingSession<'c, 'a>,
variants: impl IntoIterator<Item = Vec<Self::OutV<'c>>>,
) -> Result<Self::SumOutV<'c>> {
LLVMSumType::try_new2(
context.iw_context(),
variants.into_iter().collect(),
sum_type.clone(),
)
LLVMSumType::try_new(context.iw_context(), variants.into_iter().collect_vec())
}

fn map_function_type<'c>(
Expand Down
7 changes: 3 additions & 4 deletions hugr-llvm/src/emit/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ use inkwell::values::{BasicValueEnum, CallableValue};
use itertools::{zip_eq, Itertools};
use petgraph::visit::Walker;

use crate::types::LLVMSumType;
use crate::{
sum::LLVMSumValue,
utils::fat::{FatExt as _, FatNode},
Expand Down Expand Up @@ -130,12 +129,12 @@ pub fn emit_value<'c, H: HugrView>(
values,
sum_type,
}) => {
let llvm_st = LLVMSumType::try_new(&context.typing_session(), sum_type.clone())?;
let llvm_st = context.llvm_sum_type(sum_type.clone())?;
let vs = values
.iter()
.map(|x| emit_value(context, x))
.collect::<Result<Vec<_>>>()?;
llvm_st.build_tag(context.builder(), *tag, vs)
Ok(llvm_st.build_tag(context.builder(), *tag, vs)?.into())
}
}
}
Expand All @@ -160,7 +159,7 @@ fn emit_tag<'c, H: HugrView>(
let builder = context.builder();
args.outputs.finish(
builder,
[st.build_tag(builder, args.node.tag, args.inputs)?],
[st.build_tag(builder, args.node.tag, args.inputs)?.into()],
)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
source: src/emit/ops/cfg.rs
expression: module.to_string()
source: hugr-llvm/src/emit/ops/cfg.rs
expression: mod_str
---
; ModuleID = 'test_context'
source_filename = "test_context"
Expand All @@ -12,38 +12,33 @@ alloca_block:
entry_block: ; preds = %alloca_block
br label %2

2: ; preds = %14, %entry_block
%"7_0.0" = phi i8 [ %0, %entry_block ], [ %16, %14 ]
%"7_1.0" = phi i8 [ %1, %entry_block ], [ %9, %14 ]
%3 = insertvalue { i8, i8 } undef, i8 %"7_0.0", 0
2: ; preds = %11, %entry_block
%"7_0.0" = phi i8 [ %0, %entry_block ], [ %12, %11 ]
%"7_1.0" = phi i8 [ %1, %entry_block ], [ %7, %11 ]
%3 = insertvalue { i8, i8 } poison, i8 %"7_0.0", 0
%4 = insertvalue { i8, i8 } %3, i8 %"7_1.0", 1
%5 = insertvalue { { i8, i8 } } poison, { i8, i8 } %4, 0
switch i32 0, label %6 [
switch i1 false, label %5 [
]

6: ; preds = %2
%7 = extractvalue { { i8, i8 } } %5, 0
%8 = extractvalue { i8, i8 } %7, 0
%9 = extractvalue { i8, i8 } %7, 1
br label %10

10: ; preds = %6
%11 = insertvalue { i8 } undef, i8 %8, 0
%12 = insertvalue { i32, { i8 }, {} } { i32 0, { i8 } poison, {} poison }, { i8 } %11, 1
%13 = extractvalue { i32, { i8 }, {} } %12, 0
switch i32 %13, label %14 [
i32 1, label %17
5: ; preds = %2
%6 = extractvalue { i8, i8 } %4, 0
%7 = extractvalue { i8, i8 } %4, 1
br label %8

8: ; preds = %5
%9 = insertvalue { i1, i8 } { i1 false, i8 poison }, i8 %6, 1
%10 = extractvalue { i1, i8 } %9, 0
switch i1 %10, label %11 [
i1 true, label %13
]

14: ; preds = %10
%15 = extractvalue { i32, { i8 }, {} } %12, 1
%16 = extractvalue { i8 } %15, 0
11: ; preds = %8
%12 = extractvalue { i1, i8 } %9, 1
br label %2

17: ; preds = %10
%18 = extractvalue { i32, { i8 }, {} } %12, 2
br label %19
13: ; preds = %8
br label %14

19: ; preds = %17
ret i8 %9
14: ; preds = %13
ret i8 %7
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
source: src/emit/ops/cfg.rs
expression: module.to_string()
source: hugr-llvm/src/emit/ops/cfg.rs
expression: mod_str
---
; ModuleID = 'test_context'
source_filename = "test_context"
Expand All @@ -16,8 +16,8 @@ alloca_block:
%"03" = alloca i8, align 1
%"11_0" = alloca i8, align 1
%"11_1" = alloca i8, align 1
%"9_0" = alloca { { i8, i8 } }, align 8
%"13_0" = alloca { i32, { i8 }, {} }, align 8
%"9_0" = alloca { i8, i8 }, align 8
%"13_0" = alloca { i1, i8 }, align 8
br label %entry_block

entry_block: ; preds = %alloca_block
Expand All @@ -29,64 +29,59 @@ entry_block: ; preds = %alloca_block
store i8 %"2_12", i8* %"7_1", align 1
br label %2

2: ; preds = %14, %entry_block
2: ; preds = %11, %entry_block
%"7_04" = load i8, i8* %"7_0", align 1
%"7_15" = load i8, i8* %"7_1", align 1
store i8 %"7_04", i8* %"7_0", align 1
store i8 %"7_15", i8* %"7_1", align 1
%"7_06" = load i8, i8* %"7_0", align 1
%"7_17" = load i8, i8* %"7_1", align 1
%3 = insertvalue { i8, i8 } undef, i8 %"7_06", 0
%3 = insertvalue { i8, i8 } poison, i8 %"7_06", 0
%4 = insertvalue { i8, i8 } %3, i8 %"7_17", 1
%5 = insertvalue { { i8, i8 } } poison, { i8, i8 } %4, 0
store { { i8, i8 } } %5, { { i8, i8 } }* %"9_0", align 1
%"9_08" = load { { i8, i8 } }, { { i8, i8 } }* %"9_0", align 1
store { { i8, i8 } } %"9_08", { { i8, i8 } }* %"9_0", align 1
%"9_09" = load { { i8, i8 } }, { { i8, i8 } }* %"9_0", align 1
switch i32 0, label %6 [
store { i8, i8 } %4, { i8, i8 }* %"9_0", align 1
%"9_08" = load { i8, i8 }, { i8, i8 }* %"9_0", align 1
store { i8, i8 } %"9_08", { i8, i8 }* %"9_0", align 1
%"9_09" = load { i8, i8 }, { i8, i8 }* %"9_0", align 1
switch i1 false, label %5 [
]

6: ; preds = %2
%7 = extractvalue { { i8, i8 } } %"9_09", 0
%8 = extractvalue { i8, i8 } %7, 0
%9 = extractvalue { i8, i8 } %7, 1
store i8 %8, i8* %"11_0", align 1
store i8 %9, i8* %"11_1", align 1
br label %10
5: ; preds = %2
%6 = extractvalue { i8, i8 } %"9_09", 0
%7 = extractvalue { i8, i8 } %"9_09", 1
store i8 %6, i8* %"11_0", align 1
store i8 %7, i8* %"11_1", align 1
br label %8

10: ; preds = %6
8: ; preds = %5
%"11_011" = load i8, i8* %"11_0", align 1
%"11_112" = load i8, i8* %"11_1", align 1
store i8 %"11_011", i8* %"11_0", align 1
store i8 %"11_112", i8* %"11_1", align 1
%"11_013" = load i8, i8* %"11_0", align 1
%11 = insertvalue { i8 } undef, i8 %"11_013", 0
%12 = insertvalue { i32, { i8 }, {} } { i32 0, { i8 } poison, {} poison }, { i8 } %11, 1
store { i32, { i8 }, {} } %12, { i32, { i8 }, {} }* %"13_0", align 4
%"13_014" = load { i32, { i8 }, {} }, { i32, { i8 }, {} }* %"13_0", align 4
%9 = insertvalue { i1, i8 } { i1 false, i8 poison }, i8 %"11_013", 1
store { i1, i8 } %9, { i1, i8 }* %"13_0", align 1
%"13_014" = load { i1, i8 }, { i1, i8 }* %"13_0", align 1
%"11_115" = load i8, i8* %"11_1", align 1
store { i32, { i8 }, {} } %"13_014", { i32, { i8 }, {} }* %"13_0", align 4
store { i1, i8 } %"13_014", { i1, i8 }* %"13_0", align 1
store i8 %"11_115", i8* %"11_1", align 1
%"13_016" = load { i32, { i8 }, {} }, { i32, { i8 }, {} }* %"13_0", align 4
%"13_016" = load { i1, i8 }, { i1, i8 }* %"13_0", align 1
%"11_117" = load i8, i8* %"11_1", align 1
%13 = extractvalue { i32, { i8 }, {} } %"13_016", 0
switch i32 %13, label %14 [
i32 1, label %17
%10 = extractvalue { i1, i8 } %"13_016", 0
switch i1 %10, label %11 [
i1 true, label %13
]

14: ; preds = %10
%15 = extractvalue { i32, { i8 }, {} } %"13_016", 1
%16 = extractvalue { i8 } %15, 0
store i8 %16, i8* %"7_0", align 1
11: ; preds = %8
%12 = extractvalue { i1, i8 } %"13_016", 1
store i8 %12, i8* %"7_0", align 1
store i8 %"11_117", i8* %"7_1", align 1
br label %2

17: ; preds = %10
%18 = extractvalue { i32, { i8 }, {} } %"13_016", 2
13: ; preds = %8
store i8 %"11_117", i8* %"03", align 1
br label %19
br label %14

19: ; preds = %17
14: ; preds = %13
%"010" = load i8, i8* %"03", align 1
store i8 %"010", i8* %"4_0", align 1
%"4_018" = load i8, i8* %"4_0", align 1
Expand Down
Original file line number Diff line number Diff line change
@@ -1,95 +1,83 @@
---
source: src/emit/ops/cfg.rs
expression: module.to_string()
source: hugr-llvm/src/emit/ops/cfg.rs
expression: mod_str
---
; ModuleID = 'test_context'
source_filename = "test_context"

define { i32, {}, {} } @_hl.main.1({ i32, {}, {}, {} } %0, { i32, {}, {} } %1) {
define i1 @_hl.main.1(i2 %0, i1 %1) {
alloca_block:
br label %entry_block

entry_block: ; preds = %alloca_block
br label %2

2: ; preds = %entry_block
br label %10
br label %8

3: ; preds = %29
switch i32 0, label %4 [
3: ; preds = %19
switch i1 false, label %4 [
]

4: ; preds = %3
%5 = extractvalue { {} } undef, 0
br label %9
br label %7

6: ; preds = %31
switch i32 0, label %7 [
5: ; preds = %20
switch i1 false, label %6 [
]

7: ; preds = %6
%8 = extractvalue { {} } undef, 0
br label %9
6: ; preds = %5
br label %7

9: ; preds = %7, %4
%"03.0" = phi { i32, {}, {} } [ { i32 1, {} poison, {} undef }, %4 ], [ { i32 0, {} undef, {} poison }, %7 ]
ret { i32, {}, {} } %"03.0"
7: ; preds = %6, %4
%"03.0" = phi i1 [ true, %4 ], [ false, %6 ]
ret i1 %"03.0"

10: ; preds = %2
%11 = extractvalue { i32, {}, {}, {} } %0, 0
switch i32 %11, label %12 [
i32 1, label %14
i32 2, label %16
8: ; preds = %2
switch i2 %0, label %9 [
i2 1, label %10
i2 -2, label %11
]

12: ; preds = %10
%13 = extractvalue { i32, {}, {}, {} } %0, 1
br label %18
9: ; preds = %8
br label %12

14: ; preds = %10
%15 = extractvalue { i32, {}, {}, {} } %0, 2
br label %21
10: ; preds = %8
br label %14

16: ; preds = %10
%17 = extractvalue { i32, {}, {}, {} } %0, 3
br label %24
11: ; preds = %8
br label %16

18: ; preds = %12
switch i32 0, label %19 [
12: ; preds = %9
switch i1 false, label %13 [
]

19: ; preds = %18
%20 = extractvalue { {} } undef, 0
br label %27
13: ; preds = %12
br label %18

21: ; preds = %14
switch i32 0, label %22 [
14: ; preds = %10
switch i1 false, label %15 [
]

22: ; preds = %21
%23 = extractvalue { {} } undef, 0
br label %27
15: ; preds = %14
br label %18

24: ; preds = %16
switch i32 0, label %25 [
16: ; preds = %11
switch i1 false, label %17 [
]

25: ; preds = %24
%26 = extractvalue { {} } undef, 0
br label %27
17: ; preds = %16
br label %18

27: ; preds = %25, %22, %19
%"06.0" = phi { i32, {}, {} } [ { i32 1, {} poison, {} undef }, %19 ], [ %1, %25 ], [ { i32 0, {} undef, {} poison }, %22 ]
%28 = extractvalue { i32, {}, {} } %"06.0", 0
switch i32 %28, label %29 [
i32 1, label %31
18: ; preds = %17, %15, %13
%"06.0" = phi i1 [ true, %13 ], [ %1, %17 ], [ false, %15 ]
switch i1 %"06.0", label %19 [
i1 true, label %20
]

29: ; preds = %27
%30 = extractvalue { i32, {}, {} } %"06.0", 1
19: ; preds = %18
br label %3

31: ; preds = %27
%32 = extractvalue { i32, {}, {} } %"06.0", 2
br label %6
20: ; preds = %18
br label %5
}
Loading

0 comments on commit 8cbbc35

Please sign in to comment.