@@ -501,30 +501,42 @@ function lower_byval(@nospecialize(job::CompilerJob), mod::LLVM.Module, f::LLVM.
501
501
else
502
502
changes = LLVM. API. LLVMCloneFunctionChangeTypeLocalChangesOnly
503
503
end
504
- clone_into! (new_f, f; value_map, changes)
504
+
505
+ # use a value materializer for replacing uses of the function in constants
506
+ # NOTE: we assume kernel functions can't be called. on-device kernel launches,
507
+ # e.g. CUDA's dynamic parallelism, will pass the function to an API instead,
508
+ # and we update those constant expressions arguments here.
509
+ function materializer (val)
510
+ opcodes = (LLVM. API. LLVMPtrToInt, LLVM. API. LLVMAddrSpaceCast, LLVM. API. LLVMBitCast)
511
+ if val isa LLVM. ConstantExpr && opcode (val) in opcodes
512
+ target = operands (val)[1 ]
513
+ if target == f
514
+ return if opcode (val) == LLVM. API. LLVMPtrToInt
515
+ LLVM. const_ptrtoint (new_f, llvmtype (val))
516
+ elseif opcode (val) == LLVM. API. LLVMAddrSpaceCast
517
+ LLVM. const_addrspacecast (new_f, llvmtype (val))
518
+ elseif opcode (val) == LLVM. API. LLVMBitCast
519
+ LLVM. const_bitcast (new_f, llvmtype (val))
520
+ end
521
+ end
522
+ end
523
+ return val
524
+ end
525
+
526
+ # we don't want module-level changes, because otherwise LLVM will clone metadata,
527
+ # resulting in mismatching references between `!dbg` metadata and `dbg` instructions
528
+ clone_into! (new_f, f; value_map, changes, materializer)
505
529
506
530
# fall through
507
531
br! (builder, blocks (new_f)[2 ])
508
532
end
509
533
510
- # update uses of the kernel
511
- # NOTE: we assume kernel functions can't be called. on-device kernel launches,
512
- # e.g. CUDA's dynamic parallelism, will pass the function to an API instead,
513
- # and we update those constant expressions arguments here.
534
+ # drop unused constants that may be referring to the old functions
535
+ # XXX : can we do this differently?
514
536
for use in uses (f)
515
537
val = user (use)
516
- if val isa LLVM. ConstantExpr && opcode (val) == LLVM. API. LLVMPtrToInt
517
- target = operands (val)[1 ]
518
- if target == f
519
- new_val = LLVM. const_ptrtoint (new_f, llvmtype (val))
520
- replace_uses! (val, new_val)
521
-
522
- # drop the old constant if it is unused
523
- # XXX : can we do this differently?
524
- if isempty (uses (val))
525
- LLVM. unsafe_destroy! (val)
526
- end
527
- end
538
+ if val isa LLVM. ConstantExpr && isempty (uses (val))
539
+ LLVM. unsafe_destroy! (val)
528
540
end
529
541
end
530
542
@@ -608,10 +620,17 @@ function add_kernel_state!(@nospecialize(job::CompilerJob), mod::LLVM.Module,
608
620
609
621
# use a value materializer for replacing uses of the function in constants
610
622
function materializer (val)
611
- if val isa LLVM. ConstantExpr && opcode (val) == LLVM. API. LLVMPtrToInt
623
+ opcodes = (LLVM. API. LLVMPtrToInt, LLVM. API. LLVMAddrSpaceCast, LLVM. API. LLVMBitCast)
624
+ if val isa LLVM. ConstantExpr && opcode (val) in opcodes
612
625
src = operands (val)[1 ]
613
626
if haskey (workmap, src)
614
- return LLVM. const_ptrtoint (workmap[src], llvmtype (val))
627
+ return if opcode (val) == LLVM. API. LLVMPtrToInt
628
+ LLVM. const_ptrtoint (workmap[src], llvmtype (val))
629
+ elseif opcode (val) == LLVM. API. LLVMAddrSpaceCast
630
+ LLVM. const_addrspacecast (workmap[src], llvmtype (val))
631
+ elseif opcode (val) == LLVM. API. LLVMBitCast
632
+ LLVM. const_bitcast (workmap[src], llvmtype (val))
633
+ end
615
634
end
616
635
end
617
636
return val
@@ -677,20 +696,6 @@ function add_kernel_state!(@nospecialize(job::CompilerJob), mod::LLVM.Module,
677
696
replace_uses! (val, new_val)
678
697
@assert isempty (uses (val))
679
698
unsafe_delete! (LLVM. parent (val), val)
680
- elseif val isa LLVM. ConstantExpr && opcode (val) == LLVM. API. LLVMBitCast
681
- # XXX : why isn't this caught by the value materializer above?
682
- target = operands (val)[1 ]
683
- @assert target == f
684
- new_val = LLVM. const_bitcast (new_f, llvmtype (val))
685
- rewrite_uses! (val, new_val)
686
- # we can't simply replace this constant expression, as it may be used
687
- # as a call, taking arguments (so we need to rewrite it to pass the state)
688
-
689
- # drop the old constant if it is unused
690
- # XXX : can we do this differently?
691
- if isempty (uses (val))
692
- LLVM. unsafe_destroy! (val)
693
- end
694
699
else
695
700
error (" Cannot rewrite unknown use of function: $val " )
696
701
end
0 commit comments