From my tests this function is faster than yours fn_split() and SplitString().
CREATE FUNCTION [dbo].[fn_split](
@input VARCHAR(8000),
@delimiter VARCHAR(10) = ';'
)
RETURNS @result TABLE (rownum int NOT NULL, item VARCHAR(max))
BEGIN
DECLARE @item VARCHAR(max), @rownum int = 0
WHILE CHARINDEX(@delimiter,@input,0) > 0
BEGIN
SELECT
@item = ltrim(RTRIM(LTRIM(SUBSTRING(@input, 1, CHARINDEX(@delimiter, @input, 0) - 1)))),
@input = ltrim(RTRIM(LTRIM(SUBSTRING(@input, CHARINDEX(@delimiter, @input, 0) + LEN(@delimiter), LEN(@input)))))
IF LEN(@item) > 0
BEGIN
SET @rownum += 1;
INSERT INTO @result SELECT @rownum, @item
END
END
IF LEN(@input) > 0
BEGIN
SET @rownum += 1;
INSERT INTO @result SELECT @rownum, @input
END
RETURN
END
GO
END GO