Skip to content

Commit c08b3e4

Browse files
vmaksimojsji
authored andcommitted
Translate OpIAddCarry and OpISubBorrow back to llvm intrinsics (#2877)
Semantically we can translate `OpIAddCarry` and `OpISubBorrow` back into `@llvm.uadd.with.overflow` and `@llvm.usub.with.overflow` respectively. It require small transformation as there is a difference between return types in SPIR-V and LLVM IR - e.g., SPIR-V instructions return {i32, i32} struct, but LLVM intrinsics return {i32, i1}. Original commit: KhronosGroup/SPIRV-LLVM-Translator@44bd69ee70b79ed
1 parent 4fbe742 commit c08b3e4

File tree

6 files changed

+243
-99
lines changed

6 files changed

+243
-99
lines changed

llvm-spirv/lib/SPIRV/SPIRVReader.cpp

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2717,13 +2717,37 @@ Value *SPIRVToLLVM::transValueWithoutDecoration(SPIRVValue *BV, Function *F,
27172717
case OpSignBitSet:
27182718
return mapValue(BV,
27192719
transRelational(static_cast<SPIRVInstruction *>(BV), BB));
2720-
case OpIAddCarry: {
2721-
auto *BC = static_cast<SPIRVBinary *>(BV);
2722-
return mapValue(BV, transBuiltinFromInst("__spirv_IAddCarry", BC, BB));
2723-
}
2720+
case OpIAddCarry:
27242721
case OpISubBorrow: {
2722+
IRBuilder Builder(BB);
27252723
auto *BC = static_cast<SPIRVBinary *>(BV);
2726-
return mapValue(BV, transBuiltinFromInst("__spirv_ISubBorrow", BC, BB));
2724+
Intrinsic::ID ID = OC == OpIAddCarry ? Intrinsic::uadd_with_overflow
2725+
: Intrinsic::usub_with_overflow;
2726+
auto *Inst =
2727+
Builder.CreateBinaryIntrinsic(ID, transValue(BC->getOperand(0), F, BB),
2728+
transValue(BC->getOperand(1), F, BB));
2729+
2730+
// Extract components of the result.
2731+
auto *Result = Builder.CreateExtractValue(Inst, 0); // iN result
2732+
auto *Carry = Builder.CreateExtractValue(Inst, 1); // i1 overflow
2733+
2734+
// Convert {iN, i1} into {iN, iN} for SPIR-V compatibility.
2735+
Value *CarryInt;
2736+
if (Carry->getType()->isVectorTy()) {
2737+
CarryInt = Builder.CreateZExt(
2738+
Carry, VectorType::get(
2739+
cast<VectorType>(Result->getType())->getElementType(),
2740+
cast<VectorType>(Carry->getType())->getElementCount()));
2741+
} else {
2742+
CarryInt = Builder.CreateZExt(Carry, Result->getType());
2743+
}
2744+
auto *ResultStruct =
2745+
Builder.CreateInsertValue(UndefValue::get(StructType::get(
2746+
Result->getType(), CarryInt->getType())),
2747+
Result, 0);
2748+
ResultStruct = Builder.CreateInsertValue(ResultStruct, CarryInt, 1);
2749+
2750+
return mapValue(BV, ResultStruct);
27272751
}
27282752
case OpSMulExtended: {
27292753
auto *BC = static_cast<SPIRVBinary *>(BV);

llvm-spirv/test/builtin_returns_struct.spvasm

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
OpBranch %20
3535
%20 = OpLabel
3636
%e = OpPhi %uint %a %19 %math %21
37-
%16 = OpIAddCarry %_struct_7 %e %uint_1
37+
%16 = OpUMulExtended %_struct_7 %e %uint_1
3838
%math = OpCompositeExtract %uint %16 0
3939
%17 = OpCompositeExtract %uint %16 1
4040
%ov = OpINotEqual %bool %17 %10
@@ -47,6 +47,6 @@
4747
OpFunctionEnd
4848

4949
; CHECK: %[[#Var:]] = alloca %structtype, align 8
50-
; CHECK: call spir_func void @_Z17__spirv_IAddCarryii(ptr sret(%structtype) %[[#Var:]]
50+
; CHECK: call spir_func void @_Z20__spirv_UMulExtendedii(ptr sret(%structtype) %[[#Var:]]
5151
; CHECK: %[[#Load:]] = load %structtype, ptr %[[#Var]], align 4
5252
; CHECK-2: extractvalue %structtype %[[#Load:]]

llvm-spirv/test/iaddcarry_builtin.ll

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,13 @@ define spir_func void @test_builtin_iaddcarrycc(i8 %a, i8 %b) {
5757
; CHECK-SPIRV: OpFunctionEnd
5858

5959
; CHECK-LLVM: %0 = alloca [[i8struct]], align 8
60-
; CHECK-LLVM: call spir_func void @_Z17__spirv_IAddCarrycc(ptr sret([[i8struct]]) %0, i8 %a, i8 %b)
60+
; CHECK-LLVM: %1 = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 %a, i8 %b)
61+
; CHECK-LLVM: %2 = extractvalue { i8, i1 } %1, 0
62+
; CHECK-LLVM: %3 = extractvalue { i8, i1 } %1, 1
63+
; CHECK-LLVM: %4 = zext i1 %3 to i8
64+
; CHECK-LLVM: %5 = insertvalue { i8, i8 } undef, i8 %2, 0
65+
; CHECK-LLVM: %6 = insertvalue { i8, i8 } %5, i8 %4, 1
66+
; CHECK-LLVM: store { i8, i8 } %6, ptr %0, align 1
6167
; CHECK-LLVM: ret void
6268
define spir_func void @test_builtin_iaddcarryss(i16 %a, i16 %b) {
6369
entry:
@@ -75,7 +81,13 @@ define spir_func void @test_builtin_iaddcarryss(i16 %a, i16 %b) {
7581
; CHECK-SPIRV: OpFunctionEnd
7682

7783
; CHECK-LLVM: %0 = alloca [[i16struct]], align 8
78-
; CHECK-LLVM: call spir_func void @_Z17__spirv_IAddCarryss(ptr sret([[i16struct]]) %0, i16 %a, i16 %b)
84+
; CHECK-LLVM: %1 = call { i16, i1 } @llvm.uadd.with.overflow.i16(i16 %a, i16 %b)
85+
; CHECK-LLVM: %2 = extractvalue { i16, i1 } %1, 0
86+
; CHECK-LLVM: %3 = extractvalue { i16, i1 } %1, 1
87+
; CHECK-LLVM: %4 = zext i1 %3 to i16
88+
; CHECK-LLVM: %5 = insertvalue { i16, i16 } undef, i16 %2, 0
89+
; CHECK-LLVM: %6 = insertvalue { i16, i16 } %5, i16 %4, 1
90+
; CHECK-LLVM: store { i16, i16 } %6, ptr %0, align 2
7991
; CHECK-LLVM: ret void
8092
define spir_func void @test_builtin_iaddcarryii(i32 %a, i32 %b) {
8193
entry:
@@ -93,7 +105,13 @@ define spir_func void @test_builtin_iaddcarryii(i32 %a, i32 %b) {
93105
; CHECK-SPIRV: OpFunctionEnd
94106

95107
; CHECK-LLVM: %0 = alloca [[i32struct]], align 8
96-
; CHECK-LLVM: call spir_func void @_Z17__spirv_IAddCarryii(ptr sret([[i32struct]]) %0, i32 %a, i32 %b)
108+
; CHECK-LLVM: %1 = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %a, i32 %b)
109+
; CHECK-LLVM: %2 = extractvalue { i32, i1 } %1, 0
110+
; CHECK-LLVM: %3 = extractvalue { i32, i1 } %1, 1
111+
; CHECK-LLVM: %4 = zext i1 %3 to i32
112+
; CHECK-LLVM: %5 = insertvalue { i32, i32 } undef, i32 %2, 0
113+
; CHECK-LLVM: %6 = insertvalue { i32, i32 } %5, i32 %4, 1
114+
; CHECK-LLVM: store { i32, i32 } %6, ptr %0, align 4
97115
; CHECK-LLVM: ret void
98116
define spir_func void @test_builtin_iaddcarryll(i64 %a, i64 %b) {
99117
entry:
@@ -111,7 +129,13 @@ define spir_func void @test_builtin_iaddcarryll(i64 %a, i64 %b) {
111129
; CHECK-SPIRV: OpFunctionEnd
112130

113131
; CHECK-LLVM: %0 = alloca [[i64struct]]
114-
; CHECK-LLVM: call spir_func void @_Z17__spirv_IAddCarryll(ptr sret([[i64struct]]) %0, i64 %a, i64 %b)
132+
; CHECK-LLVM: %1 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %a, i64 %b)
133+
; CHECK-LLVM: %2 = extractvalue { i64, i1 } %1, 0
134+
; CHECK-LLVM: %3 = extractvalue { i64, i1 } %1, 1
135+
; CHECK-LLVM: %4 = zext i1 %3 to i64
136+
; CHECK-LLVM: %5 = insertvalue { i64, i64 } undef, i64 %2, 0
137+
; CHECK-LLVM: %6 = insertvalue { i64, i64 } %5, i64 %4, 1
138+
; CHECK-LLVM: store { i64, i64 } %6, ptr %0, align 8
115139
; CHECK-LLVM: ret void
116140
define spir_func void @test_builtin_iaddcarryDv4_xS_(<4 x i32> %a, <4 x i32> %b) {
117141
entry:
@@ -129,7 +153,13 @@ define spir_func void @test_builtin_iaddcarryDv4_xS_(<4 x i32> %a, <4 x i32> %b)
129153
; CHECK-SPIRV: OpFunctionEnd
130154

131155
; CHECK-LLVM: %0 = alloca [[vecstruct]]
132-
; CHECK-LLVM: call spir_func void @_Z17__spirv_IAddCarryDv4_iS_(ptr sret([[vecstruct]]) %0, <4 x i32> %a, <4 x i32> %b)
156+
; CHECK-LLVM: %1 = call { <4 x i32>, <4 x i1> } @llvm.uadd.with.overflow.v4i32(<4 x i32> %a, <4 x i32> %b)
157+
; CHECK-LLVM: %2 = extractvalue { <4 x i32>, <4 x i1> } %1, 0
158+
; CHECK-LLVM: %3 = extractvalue { <4 x i32>, <4 x i1> } %1, 1
159+
; CHECK-LLVM: %4 = zext <4 x i1> %3 to <4 x i32>
160+
; CHECK-LLVM: %5 = insertvalue { <4 x i32>, <4 x i32> } undef, <4 x i32> %2, 0
161+
; CHECK-LLVM: %6 = insertvalue { <4 x i32>, <4 x i32> } %5, <4 x i32> %4, 1
162+
; CHECK-LLVM: store { <4 x i32>, <4 x i32> } %6, ptr %0, align 16
133163
; CHECK-LLVM: ret void
134164

135165
%struct.anon = type { i32, i32 }
@@ -151,7 +181,13 @@ define spir_func void @test_builtin_iaddcarry_anon(i32 %a, i32 %b) {
151181

152182
; CHECK-LLVM: %0 = alloca [[struct_anon]], align 8
153183
; CHECK-LLVM: %1 = addrspacecast ptr %0 to ptr addrspace(4)
154-
; CHECK-LLVM: call spir_func void @_Z17__spirv_IAddCarryii.1(ptr addrspace(4) sret([[struct_anon]]) %1, i32 %a, i32 %b)
184+
; CHECK-LLVM: %2 = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %a, i32 %b)
185+
; CHECK-LLVM: %3 = extractvalue { i32, i1 } %2, 0
186+
; CHECK-LLVM: %4 = extractvalue { i32, i1 } %2, 1
187+
; CHECK-LLVM: %5 = zext i1 %4 to i32
188+
; CHECK-LLVM: %6 = insertvalue { i32, i32 } undef, i32 %3, 0
189+
; CHECK-LLVM: %7 = insertvalue { i32, i32 } %6, i32 %5, 1
190+
; CHECK-LLVM: store { i32, i32 } %7, ptr addrspace(4) %1, align 4
155191
; CHECK-LLVM: ret void
156192

157193
declare void @_Z17__spirv_IAddCarryIiiE4anonIT_T0_ES1_S2_(ptr addrspace(4) sret(%struct.anon) align 4, i32, i32)

llvm-spirv/test/isubborrow_builtin.ll

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,13 @@ define spir_func void @test_builtin_isubborrowcc(i8 %a, i8 %b) {
5858
; CHECK-SPIRV: OpFunctionEnd
5959

6060
; CHECK-LLVM: %0 = alloca [[i8struct]], align 8
61-
; CHECK-LLVM: call spir_func void @_Z18__spirv_ISubBorrowcc(ptr sret([[i8struct]]) %0, i8 %a, i8 %b)
61+
; CHECK-LLVM: %1 = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %a, i8 %b)
62+
; CHECK-LLVM: %2 = extractvalue { i8, i1 } %1, 0
63+
; CHECK-LLVM: %3 = extractvalue { i8, i1 } %1, 1
64+
; CHECK-LLVM: %4 = zext i1 %3 to i8
65+
; CHECK-LLVM: %5 = insertvalue { i8, i8 } undef, i8 %2, 0
66+
; CHECK-LLVM: %6 = insertvalue { i8, i8 } %5, i8 %4, 1
67+
; CHECK-LLVM: store { i8, i8 } %6, ptr %0, align 1
6268
; CHECK-LLVM: ret void
6369
define spir_func void @test_builtin_isubborrowss(i16 %a, i16 %b) {
6470
entry:
@@ -76,7 +82,13 @@ define spir_func void @test_builtin_isubborrowss(i16 %a, i16 %b) {
7682
; CHECK-SPIRV: OpFunctionEnd
7783

7884
; CHECK-LLVM: %0 = alloca [[i16struct]], align 8
79-
; CHECK-LLVM: call spir_func void @_Z18__spirv_ISubBorrowss(ptr sret([[i16struct]]) %0, i16 %a, i16 %b)
85+
; CHECK-LLVM: %1 = call { i16, i1 } @llvm.usub.with.overflow.i16(i16 %a, i16 %b)
86+
; CHECK-LLVM: %2 = extractvalue { i16, i1 } %1, 0
87+
; CHECK-LLVM: %3 = extractvalue { i16, i1 } %1, 1
88+
; CHECK-LLVM: %4 = zext i1 %3 to i16
89+
; CHECK-LLVM: %5 = insertvalue { i16, i16 } undef, i16 %2, 0
90+
; CHECK-LLVM: %6 = insertvalue { i16, i16 } %5, i16 %4, 1
91+
; CHECK-LLVM: store { i16, i16 } %6, ptr %0, align 2
8092
; CHECK-LLVM: ret void
8193
define spir_func void @test_builtin_isubborrowii(i32 %a, i32 %b) {
8294
entry:
@@ -94,7 +106,13 @@ define spir_func void @test_builtin_isubborrowii(i32 %a, i32 %b) {
94106
; CHECK-SPIRV: OpFunctionEnd
95107

96108
; CHECK-LLVM: %0 = alloca [[i32struct]], align 8
97-
; CHECK-LLVM: call spir_func void @_Z18__spirv_ISubBorrowii(ptr sret([[i32struct]]) %0, i32 %a, i32 %b)
109+
; CHECK-LLVM: %1 = call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %a, i32 %b)
110+
; CHECK-LLVM: %2 = extractvalue { i32, i1 } %1, 0
111+
; CHECK-LLVM: %3 = extractvalue { i32, i1 } %1, 1
112+
; CHECK-LLVM: %4 = zext i1 %3 to i32
113+
; CHECK-LLVM: %5 = insertvalue { i32, i32 } undef, i32 %2, 0
114+
; CHECK-LLVM: %6 = insertvalue { i32, i32 } %5, i32 %4, 1
115+
; CHECK-LLVM: store { i32, i32 } %6, ptr %0, align 4
98116
; CHECK-LLVM: ret void
99117
define spir_func void @test_builtin_isubborrowll(i64 %a, i64 %b) {
100118
entry:
@@ -112,7 +130,13 @@ define spir_func void @test_builtin_isubborrowll(i64 %a, i64 %b) {
112130
; CHECK-SPIRV: OpFunctionEnd
113131

114132
; CHECK-LLVM: %0 = alloca [[i64struct]]
115-
; CHECK-LLVM: call spir_func void @_Z18__spirv_ISubBorrowll(ptr sret([[i64struct]]) %0, i64 %a, i64 %b)
133+
; CHECK-LLVM: %1 = call { i64, i1 } @llvm.usub.with.overflow.i64(i64 %a, i64 %b)
134+
; CHECK-LLVM: %2 = extractvalue { i64, i1 } %1, 0
135+
; CHECK-LLVM: %3 = extractvalue { i64, i1 } %1, 1
136+
; CHECK-LLVM: %4 = zext i1 %3 to i64
137+
; CHECK-LLVM: %5 = insertvalue { i64, i64 } undef, i64 %2, 0
138+
; CHECK-LLVM: %6 = insertvalue { i64, i64 } %5, i64 %4, 1
139+
; CHECK-LLVM: store { i64, i64 } %6, ptr %0, align 8
116140
; CHECK-LLVM: ret void
117141
define spir_func void @test_builtin_isubborrowDv4_xS_(<4 x i32> %a, <4 x i32> %b) {
118142
entry:
@@ -130,7 +154,13 @@ define spir_func void @test_builtin_isubborrowDv4_xS_(<4 x i32> %a, <4 x i32> %b
130154
; CHECK-SPIRV: OpFunctionEnd
131155

132156
; CHECK-LLVM: %0 = alloca [[vecstruct]]
133-
; CHECK-LLVM: call spir_func void @_Z18__spirv_ISubBorrowDv4_iS_(ptr sret([[vecstruct]]) %0, <4 x i32> %a, <4 x i32> %b)
157+
; CHECK-LLVM: %1 = call { <4 x i32>, <4 x i1> } @llvm.usub.with.overflow.v4i32(<4 x i32> %a, <4 x i32> %b)
158+
; CHECK-LLVM: %2 = extractvalue { <4 x i32>, <4 x i1> } %1, 0
159+
; CHECK-LLVM: %3 = extractvalue { <4 x i32>, <4 x i1> } %1, 1
160+
; CHECK-LLVM: %4 = zext <4 x i1> %3 to <4 x i32>
161+
; CHECK-LLVM: %5 = insertvalue { <4 x i32>, <4 x i32> } undef, <4 x i32> %2, 0
162+
; CHECK-LLVM: %6 = insertvalue { <4 x i32>, <4 x i32> } %5, <4 x i32> %4, 1
163+
; CHECK-LLVM: store { <4 x i32>, <4 x i32> } %6, ptr %0, align 16
134164
; CHECK-LLVM: ret void
135165

136166

@@ -151,7 +181,13 @@ define spir_func void @test_builtin_isubborrow_anon(i32 %a, i32 %b) {
151181

152182
; CHECK-LLVM: %0 = alloca [[struct_anon]], align 8
153183
; CHECK-LLVM: %1 = addrspacecast ptr %0 to ptr addrspace(4)
154-
; CHECK-LLVM: call spir_func void @_Z18__spirv_ISubBorrowii.1(ptr addrspace(4) sret([[struct_anon]]) %1, i32 %a, i32 %b)
184+
; CHECK-LLVM: %2 = call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %a, i32 %b)
185+
; CHECK-LLVM: %3 = extractvalue { i32, i1 } %2, 0
186+
; CHECK-LLVM: %4 = extractvalue { i32, i1 } %2, 1
187+
; CHECK-LLVM: %5 = zext i1 %4 to i32
188+
; CHECK-LLVM: %6 = insertvalue { i32, i32 } undef, i32 %3, 0
189+
; CHECK-LLVM: %7 = insertvalue { i32, i32 } %6, i32 %5, 1
190+
; CHECK-LLVM: store { i32, i32 } %7, ptr addrspace(4) %1, align 4
155191
; CHECK-LLVM: ret void
156192

157193
declare void @_Z18__spirv_ISubBorrowIiiE4anonIT_T0_ES1_S2_(ptr addrspace(4) sret(%struct.anon) align 4, i32, i32)

llvm-spirv/test/llvm-intrinsics/uadd.with.overflow.ll

Lines changed: 64 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -73,16 +73,22 @@ entry:
7373
; CHECK-SPIRV: OpReturnValue [[var_23]]
7474

7575
; CHECK-LLVM: %0 = alloca [[structtype]], align 8
76-
; CHECK-LLVM: call spir_func void @_Z17__spirv_IAddCarryss(ptr sret([[structtype]]) %0, i16 %a, i16 %b)
77-
; CHECK-LLVM: %1 = load [[structtype]], ptr %0, align 2
78-
; CHECK-LLVM: %2 = extractvalue [[structtype]] %1, 0
79-
; CHECK-LLVM: %3 = extractvalue [[structtype]] %1, 1
80-
; CHECK-LLVM: %4 = icmp ne i16 %3, 0
81-
; CHECK-LLVM: %5 = insertvalue [[structtype_0]] undef, i16 %2, 0
82-
; CHECK-LLVM: %6 = insertvalue [[structtype_0]] %5, i1 %4, 1
83-
; CHECK-LLVM: %7 = extractvalue [[structtype_0]] %6, 0
84-
; CHECK-LLVM: %8 = extractvalue [[structtype_0]] %6, 1
85-
; CHECK-LLVM: ret i1 %8
76+
; CHECK-LLVM: %1 = call { i16, i1 } @llvm.uadd.with.overflow.i16(i16 %a, i16 %b)
77+
; CHECK-LLVM: %2 = extractvalue { i16, i1 } %1, 0
78+
; CHECK-LLVM: %3 = extractvalue { i16, i1 } %1, 1
79+
; CHECK-LLVM: %4 = zext i1 %3 to i16
80+
; CHECK-LLVM: %5 = insertvalue { i16, i16 } undef, i16 %2, 0
81+
; CHECK-LLVM: %6 = insertvalue { i16, i16 } %5, i16 %4, 1
82+
; CHECK-LLVM: store { i16, i16 } %6, ptr %0, align 2
83+
; CHECK-LLVM: %7 = load %structtype, ptr %0, align 2
84+
; CHECK-LLVM: %8 = extractvalue [[structtype]] %7, 0
85+
; CHECK-LLVM: %9 = extractvalue [[structtype]] %7, 1
86+
; CHECK-LLVM: %10 = icmp ne i16 %9, 0
87+
; CHECK-LLVM: %11 = insertvalue [[structtype_0]] undef, i16 %8, 0
88+
; CHECK-LLVM: %12 = insertvalue [[structtype_0]] %11, i1 %10, 1
89+
; CHECK-LLVM: %13 = extractvalue [[structtype_0]] %12, 0
90+
; CHECK-LLVM: %14 = extractvalue [[structtype_0]] %12, 1
91+
; CHECK-LLVM: ret i1 %14
8692
define spir_func i1 @test_uadd_with_overflow_i32(i32 %a, i32 %b) {
8793
entry:
8894
%res = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %a, i32 %b)
@@ -109,16 +115,22 @@ entry:
109115

110116

111117
; CHECK-LLVM: %0 = alloca [[structtype_1]], align 8
112-
; CHECK-LLVM: call spir_func void @_Z17__spirv_IAddCarryii(ptr sret([[structtype_1]]) %0, i32 %a, i32 %b)
113-
; CHECK-LLVM: %1 = load [[structtype_1]], ptr %0, align 4
114-
; CHECK-LLVM: %2 = extractvalue [[structtype_1]] %1, 0
115-
; CHECK-LLVM: %3 = extractvalue [[structtype_1]] %1, 1
116-
; CHECK-LLVM: %4 = icmp ne i32 %3, 0
117-
; CHECK-LLVM: %5 = insertvalue [[structtype_2]] undef, i32 %2, 0
118-
; CHECK-LLVM: %6 = insertvalue [[structtype_2]] %5, i1 %4, 1
119-
; CHECK-LLVM: %7 = extractvalue [[structtype_2]] %6, 0
120-
; CHECK-LLVM: %8 = extractvalue [[structtype_2]] %6, 1
121-
; CHECK-LLVM: ret i1 %8
118+
; CHECK-LLVM: %1 = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %a, i32 %b)
119+
; CHECK-LLVM: %2 = extractvalue { i32, i1 } %1, 0
120+
; CHECK-LLVM: %3 = extractvalue { i32, i1 } %1, 1
121+
; CHECK-LLVM: %4 = zext i1 %3 to i32
122+
; CHECK-LLVM: %5 = insertvalue { i32, i32 } undef, i32 %2, 0
123+
; CHECK-LLVM: %6 = insertvalue { i32, i32 } %5, i32 %4, 1
124+
; CHECK-LLVM: store { i32, i32 } %6, ptr %0, align 4
125+
; CHECK-LLVM: %7 = load [[structtype_1]], ptr %0, align 4
126+
; CHECK-LLVM: %8 = extractvalue [[structtype_1]] %7, 0
127+
; CHECK-LLVM: %9 = extractvalue [[structtype_1]] %7, 1
128+
; CHECK-LLVM: %10 = icmp ne i32 %9, 0
129+
; CHECK-LLVM: %11 = insertvalue [[structtype_2]] undef, i32 %8, 0
130+
; CHECK-LLVM: %12 = insertvalue [[structtype_2]] %11, i1 %10, 1
131+
; CHECK-LLVM: %13 = extractvalue [[structtype_2]] %12, 0
132+
; CHECK-LLVM: %14 = extractvalue [[structtype_2]] %12, 1
133+
; CHECK-LLVM: ret i1 %14
122134
define spir_func i1 @test_uadd_with_overflow_i64(i64 %a, i64 %b) {
123135
entry:
124136
%res = call {i64, i1} @llvm.uadd.with.overflow.i64(i64 %a, i64 %b)
@@ -144,16 +156,22 @@ entry:
144156
; CHECK-SPIRV: OpReturnValue [[var_65]]
145157

146158
; CHECK-LLVM: %0 = alloca [[structtype_3]], align 8
147-
; CHECK-LLVM: call spir_func void @_Z17__spirv_IAddCarryll(ptr sret([[structtype_3]]) %0, i64 %a, i64 %b)
148-
; CHECK-LLVM: %1 = load [[structtype_3]], ptr %0, align 4
149-
; CHECK-LLVM: %2 = extractvalue [[structtype_3]] %1, 0
150-
; CHECK-LLVM: %3 = extractvalue [[structtype_3]] %1, 1
151-
; CHECK-LLVM: %4 = icmp ne i64 %3, 0
152-
; CHECK-LLVM: %5 = insertvalue [[structtype_4]] undef, i64 %2, 0
153-
; CHECK-LLVM: %6 = insertvalue [[structtype_4]] %5, i1 %4, 1
154-
; CHECK-LLVM: %7 = extractvalue [[structtype_4]] %6, 0
155-
; CHECK-LLVM: %8 = extractvalue [[structtype_4]] %6, 1
156-
; CHECK-LLVM: ret i1 %8
159+
; CHECK-LLVM: %1 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %a, i64 %b)
160+
; CHECK-LLVM: %2 = extractvalue { i64, i1 } %1, 0
161+
; CHECK-LLVM: %3 = extractvalue { i64, i1 } %1, 1
162+
; CHECK-LLVM: %4 = zext i1 %3 to i64
163+
; CHECK-LLVM: %5 = insertvalue { i64, i64 } undef, i64 %2, 0
164+
; CHECK-LLVM: %6 = insertvalue { i64, i64 } %5, i64 %4, 1
165+
; CHECK-LLVM: store { i64, i64 } %6, ptr %0, align 8
166+
; CHECK-LLVM: %7 = load [[structtype_3]], ptr %0, align 4
167+
; CHECK-LLVM: %8 = extractvalue [[structtype_3]] %7, 0
168+
; CHECK-LLVM: %9 = extractvalue [[structtype_3]] %7, 1
169+
; CHECK-LLVM: %10 = icmp ne i64 %9, 0
170+
; CHECK-LLVM: %11 = insertvalue [[structtype_4]] undef, i64 %8, 0
171+
; CHECK-LLVM: %12 = insertvalue [[structtype_4]] %11, i1 %10, 1
172+
; CHECK-LLVM: %13 = extractvalue [[structtype_4]] %12, 0
173+
; CHECK-LLVM: %14 = extractvalue [[structtype_4]] %12, 1
174+
; CHECK-LLVM: ret i1 %14
157175
define spir_func <4 x i1> @test_uadd_with_overflow_v4i32(<4 x i32> %a, <4 x i32> %b) {
158176
entry:
159177
%res = call {<4 x i32>, <4 x i1>} @llvm.uadd.with.overflow.v4i32(<4 x i32> %a, <4 x i32> %b)
@@ -179,16 +197,22 @@ entry:
179197
; CHECK-SPIRV: OpReturnValue [[var_87]]
180198

181199
; CHECK-LLVM: %0 = alloca [[structtype_5]], align 16
182-
; CHECK-LLVM: call spir_func void @_Z17__spirv_IAddCarryDv4_iS_(ptr sret([[structtype_5]]) %0, <4 x i32> %a, <4 x i32> %b)
183-
; CHECK-LLVM: %1 = load [[structtype_5]], ptr %0, align 16
184-
; CHECK-LLVM: %2 = extractvalue [[structtype_5]] %1, 0
185-
; CHECK-LLVM: %3 = extractvalue [[structtype_5]] %1, 1
186-
; CHECK-LLVM: %4 = icmp ne <4 x i32> %3, zeroinitializer
187-
; CHECK-LLVM: %5 = insertvalue [[structtype_6]] undef, <4 x i32> %2, 0
188-
; CHECK-LLVM: %6 = insertvalue [[structtype_6]] %5, <4 x i1> %4, 1
189-
; CHECK-LLVM: %7 = extractvalue [[structtype_6]] %6, 0
190-
; CHECK-LLVM: %8 = extractvalue [[structtype_6]] %6, 1
191-
; CHECK-LLVM: ret <4 x i1> %8
200+
; CHECK-LLVM: %1 = call { <4 x i32>, <4 x i1> } @llvm.uadd.with.overflow.v4i32(<4 x i32> %a, <4 x i32> %b)
201+
; CHECK-LLVM: %2 = extractvalue { <4 x i32>, <4 x i1> } %1, 0
202+
; CHECK-LLVM: %3 = extractvalue { <4 x i32>, <4 x i1> } %1, 1
203+
; CHECK-LLVM: %4 = zext <4 x i1> %3 to <4 x i32>
204+
; CHECK-LLVM: %5 = insertvalue { <4 x i32>, <4 x i32> } undef, <4 x i32> %2, 0
205+
; CHECK-LLVM: %6 = insertvalue { <4 x i32>, <4 x i32> } %5, <4 x i32> %4, 1
206+
; CHECK-LLVM: store { <4 x i32>, <4 x i32> } %6, ptr %0, align 16
207+
; CHECK-LLVM: %7 = load [[structtype_5]], ptr %0, align 16
208+
; CHECK-LLVM: %8 = extractvalue [[structtype_5]] %7, 0
209+
; CHECK-LLVM: %9 = extractvalue [[structtype_5]] %7, 1
210+
; CHECK-LLVM: %10 = icmp ne <4 x i32> %9, zeroinitializer
211+
; CHECK-LLVM: %11 = insertvalue [[structtype_6]] undef, <4 x i32> %8, 0
212+
; CHECK-LLVM: %12 = insertvalue [[structtype_6]] %11, <4 x i1> %10, 1
213+
; CHECK-LLVM: %13 = extractvalue [[structtype_6]] %12, 0
214+
; CHECK-LLVM: %14 = extractvalue [[structtype_6]] %12, 1
215+
; CHECK-LLVM: ret <4 x i1> %14
192216
declare {i16, i1} @llvm.uadd.with.overflow.i16(i16 %a, i16 %b)
193217
declare {i32, i1} @llvm.uadd.with.overflow.i32(i32 %a, i32 %b)
194218
declare {i64, i1} @llvm.uadd.with.overflow.i64(i64 %a, i64 %b)

0 commit comments

Comments
 (0)