Skip to content

Commit c58452e

Browse files
github-actions[bot]vmaksimoDmitry Sidorov
authored
[Backport to llvm_release_220] Enhance handling of umul_with_overflow in reverse translation (#3530)
Backport of PR #3518 into `llvm_release_220`. All commits applied cleanly. Co-authored-by: Viktoria Maximova <viktoria.maksimova@intel.com> Co-authored-by: Dmitry Sidorov <dmitry.sidorov@intel.com>
1 parent 739d568 commit c58452e

File tree

2 files changed

+20
-12
lines changed

2 files changed

+20
-12
lines changed

lib/SPIRV/SPIRVReader.cpp

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3491,6 +3491,20 @@ Function *SPIRVToLLVM::transFunction(SPIRVFunction *BF, unsigned AS) {
34913491
M, Intrinsic::memset, {FT->getParamType(0), FT->getParamType(2)})
34923492
->getName();
34933493
}
3494+
3495+
// Special handling for spirv.llvm_umul_with_overflow_* functions
3496+
// These were created during forward translation by lowering intrinsics.
3497+
// During reverse translation, we replace them with intrinsic calls.
3498+
if (FuncNameRef.starts_with("spirv.llvm_umul_with_overflow_")) {
3499+
Type *OverloadTy = FT->getParamType(0);
3500+
Function *F = Intrinsic::getOrInsertDeclaration(
3501+
M, Intrinsic::umul_with_overflow, {OverloadTy});
3502+
F = cast<Function>(mapValue(BF, F));
3503+
mapFunction(BF, F);
3504+
return F; // Skip body translation - intrinsic will be used instead
3505+
}
3506+
3507+
// Normal function handling.
34943508
if (FuncNameRef.consume_front("spirv.")) {
34953509
FuncNameRef.consume_back(".volatile");
34963510
FuncName = FuncNameRef.str();
@@ -3499,21 +3513,12 @@ Function *SPIRVToLLVM::transFunction(SPIRVFunction *BF, unsigned AS) {
34993513
Function *F = M->getFunction(FuncName);
35003514
if (!F)
35013515
F = Function::Create(FT, Linkage, AS, FuncName, M);
3516+
35023517
F = cast<Function>(mapValue(BF, F));
35033518
mapFunction(BF, F);
35043519

35053520
if (F->isIntrinsic()) {
3506-
if (F->getIntrinsicID() != Intrinsic::umul_with_overflow)
3507-
return F;
3508-
std::string Name = F->getName().str();
3509-
auto *ST = cast<StructType>(F->getReturnType());
3510-
auto *FT = F->getFunctionType();
3511-
auto *NewST = StructType::get(ST->getContext(), ST->elements());
3512-
auto *NewFT = FunctionType::get(NewST, FT->params(), FT->isVarArg());
3513-
F->setName("old_" + Name);
3514-
auto *NewFn = Function::Create(NewFT, F->getLinkage(), F->getAddressSpace(),
3515-
Name, F->getParent());
3516-
return NewFn;
3521+
return F;
35173522
}
35183523

35193524
F->setCallingConv(IsKernel ? CallingConv::SPIR_KERNEL

test/llvm-intrinsics/umul.with.overflow.ll

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
; On LLVM level, we'll check that the intrinsics were generated again in reverse
77
; translation, replacing the SPIR-V level implementations.
88
; RUN: llvm-dis %t.rev.bc -o - | FileCheck %s --check-prefix=CHECK-LLVM \
9-
; RUN: "--implicit-check-not=declare {{.*}} @spirv.llvm_umul_with_overflow_{{.*}}"
9+
; RUN: "--implicit-check-not=declare {{.*}} @spirv.llvm_umul_with_overflow_{{.*}}" \
10+
; RUN: "--implicit-check-not=old_llvm.umul.with.overflow.{{.*}}"
1011

1112
; CHECK-SPIRV: Name [[NAME_UMUL_FUNC_8:[0-9]+]] "spirv.llvm_umul_with_overflow_i8"
1213
; CHECK-SPIRV: Name [[NAME_UMUL_FUNC_32:[0-9]+]] "spirv.llvm_umul_with_overflow_i32"
@@ -25,6 +26,8 @@ entry:
2526
%umul.value = extractvalue { i8, i1 } %umul, 0
2627
%storemerge = select i1 %cmp, i8 0, i8 %umul.value
2728
store i8 %storemerge, ptr %c, align 1, !tbaa !2
29+
; This test case verifies we don't leave any artifact calls behind (e.g. old_llvm.umul.with.overflow.i8).
30+
%umul2 = tail call { i8, i1 } @llvm.umul.with.overflow.i8(i8 %a, i8 %b)
2831
ret void
2932
}
3033

0 commit comments

Comments
 (0)