145 lines
4.9 KiB
LLVM
145 lines
4.9 KiB
LLVM
; Finds the maximum value in a binary tree
|
|
|
|
%struct.Node = type { %struct.Node*, %struct.Node*, i64 }
|
|
|
|
@node1 = global %struct.Node { %struct.Node* null, %struct.Node* null, i64 100 }
|
|
@node2 = global %struct.Node { %struct.Node* @node1, %struct.Node* null, i64 10 }
|
|
@node3 = global %struct.Node { %struct.Node* null, %struct.Node* null, i64 1 }
|
|
@test1 = global %struct.Node { %struct.Node* @node2, %struct.Node* @node3, i64 5 }
|
|
@test2 = global %struct.Node { %struct.Node* @test1, %struct.Node* null, i64 1000 }
|
|
@test3 = global %struct.Node { %struct.Node* @test2, %struct.Node* null, i64 100 }
|
|
|
|
define i64 @find_max(%struct.Node* %node) {
|
|
entry:
|
|
; Check if node is null
|
|
%is_null = icmp eq %struct.Node* %node, null
|
|
br i1 %is_null, label %return_default, label %not_null
|
|
|
|
return_default:
|
|
; If node is null, return default value
|
|
ret i64 0
|
|
|
|
not_null:
|
|
; If node is not null, continue with the rest of the function
|
|
; Initialize max to the value of the root node
|
|
%value_ptr_root = getelementptr %struct.Node, %struct.Node* %node, i32 0, i32 2
|
|
%root_value = load i64, i64* %value_ptr_root
|
|
%max = alloca i64
|
|
store i64 %root_value, i64* %max
|
|
|
|
; Initialize left and right maximum values to 0
|
|
%left_max = alloca i64
|
|
store i64 0, i64* %left_max
|
|
%right_max = alloca i64
|
|
store i64 0, i64* %right_max
|
|
|
|
; Start loop iteration
|
|
br label %loop
|
|
|
|
loop:
|
|
; Load current node's value
|
|
%value_ptr = getelementptr %struct.Node, %struct.Node* %node, i32 0, i32 2
|
|
%value = load i64, i64* %value_ptr
|
|
|
|
; Load the current maximum value
|
|
%old_max = load i64, i64* %max
|
|
|
|
; Compare current value with the maximum value
|
|
%is_greater = icmp sgt i64 %value, %old_max
|
|
|
|
; If current value is greater, update maximum value
|
|
br i1 %is_greater, label %update_max, label %check_left
|
|
|
|
update_max:
|
|
; Store the current value as the new maximum
|
|
store i64 %value, i64* %max
|
|
br label %check_left
|
|
|
|
check_left:
|
|
; Check if left child exists
|
|
%left_child_ptr = getelementptr %struct.Node, %struct.Node* %node, i32 0, i32 0
|
|
%left_child = load %struct.Node*, %struct.Node** %left_child_ptr
|
|
%is_left_null = icmp eq %struct.Node* %left_child, null
|
|
br i1 %is_left_null, label %check_right, label %visit_left
|
|
|
|
visit_left:
|
|
; Recurse on left child
|
|
%left_max_value = call i64 @find_max(%struct.Node* %left_child)
|
|
store i64 %left_max_value, i64* %left_max
|
|
br label %check_right
|
|
|
|
check_right:
|
|
; Check if right child exists
|
|
%right_child_ptr = getelementptr %struct.Node, %struct.Node* %node, i32 0, i32 1
|
|
%right_child = load %struct.Node*, %struct.Node** %right_child_ptr
|
|
%is_right_null = icmp eq %struct.Node* %right_child, null
|
|
br i1 %is_right_null, label %end_loop, label %visit_right
|
|
|
|
visit_right:
|
|
; Recurse on right child
|
|
%right_max_value = call i64 @find_max(%struct.Node* %right_child)
|
|
store i64 %right_max_value, i64* %right_max
|
|
br label %end_loop
|
|
|
|
end_loop:
|
|
; Get current maximum value from root
|
|
%final_max = load i64, i64* %max
|
|
; Get the maximum value from left and right subtrees
|
|
%final_left_max = load i64, i64* %left_max
|
|
%final_right_max = load i64, i64* %right_max
|
|
; Compare maximum values from left and right subtrees
|
|
%is_left_greater = icmp sgt i64 %final_left_max, %final_right_max
|
|
br i1 %is_left_greater, label %left_greater, label %right_greater
|
|
|
|
left_greater:
|
|
; Check with middle
|
|
%is_middle_greater_left = icmp sgt i64 %final_max, %final_left_max
|
|
br i1 %is_middle_greater_left, label %return_middle_max, label %return_left_max
|
|
|
|
return_left_max:
|
|
; If left maximum is greater, return it
|
|
ret i64 %final_left_max
|
|
|
|
right_greater:
|
|
; Check with middle
|
|
%is_middle_greater_right = icmp sgt i64 %final_max, %final_right_max
|
|
br i1 %is_middle_greater_right, label %return_middle_max, label %return_right_max
|
|
|
|
return_right_max:
|
|
; If right maximum is greater, return it
|
|
ret i64 %final_right_max
|
|
|
|
return_middle_max:
|
|
; If middle maximum is greater, return it
|
|
ret i64 %final_max
|
|
}
|
|
|
|
define i64 @main(i64 %argc, i8** %argv) {
|
|
%res1 = call i64 @find_max(%struct.Node* @test1)
|
|
%cmp1 = icmp eq i64 %res1, 100
|
|
br i1 %cmp1, label %test2, label %FAIL
|
|
test2:
|
|
%res2 = call i64 @find_max(%struct.Node* @test2)
|
|
%cmp2 = icmp eq i64 %res2, 1000
|
|
br i1 %cmp2, label %test3, label %FAIL
|
|
test3:
|
|
%res3 = call i64 @find_max(%struct.Node* @test3)
|
|
%cmp3 = icmp eq i64 %res3, 1000
|
|
br i1 %cmp3, label %node1, label %FAIL
|
|
node1:
|
|
%res4 = call i64 @find_max(%struct.Node* @node1)
|
|
%cmp4 = icmp eq i64 %res4, 100
|
|
br i1 %cmp4, label %node2, label %FAIL
|
|
node2:
|
|
%res5 = call i64 @find_max(%struct.Node* @node2)
|
|
%cmp5 = icmp eq i64 %res5, 100
|
|
br i1 %cmp5, label %node3, label %FAIL
|
|
node3:
|
|
%res6 = call i64 @find_max(%struct.Node* @node3)
|
|
%cmp6 = icmp eq i64 %res6, 1
|
|
br i1 %cmp6, label %PASS, label %FAIL
|
|
PASS:
|
|
ret i64 1
|
|
FAIL:
|
|
ret i64 0
|
|
}
|