Deadlock - Due to update causing Index page movement within an index
So did some testing and the deadlock is in fact caused by page movement within the non clustered index caused by an update which changes the position of the row in the index.



So initially Session 2 (update) takes out IX lock on Page2 where the index row is originally located.  Since the update would change the value and in turn change the position of the index row within the index, session 2 will also want to take out another IX lock on the target page where the index row will end up after the update.

For understanding the reason why a select would want to hold on to S lock please refer to this question.

REPO

set nocount on 
create table deadlck ( a int , b int, c char (3), constraint PKA primary key (a))
create index idx on deadlck(b)
--creating a big enough table so that selects use page lock instead of row lock
declare @a int =1
declare @b int =57800000 
while 1=1
begin
insert into deadlck select @a,@b,'111'
if (@a%521) =520 -- to make idx index pages fit one value in each page perfectly,  not necessary, just easier to simulate the issue while testing
set @b=@b-1
Set @a=@a+1
if @a=52100
break
end

ALTER INDEX idx ON deadlck
REBUILD WITH (FILLFACTOR = 90); -- same reason as above, i did the math with a fill factor of 90 to have the pages of idx index have one value per page and and also the pages needed to have some space so when we do the update the index entry can move to another page without have to do a page split

ALTER INDEX PKA ON deadlck
REBUILD WITH (FILLFACTOR = 90); 

--session 1
while 1=1
begin
begin tran
update deadlck set b=57799999 where a=2
rollback
end

--session 2
while 1=1
begin
begin tran
select b from deadlck with(paglock) where (b =57799999 or b=57800000)
rollback
end