Skip to content

Commit 45afa2f

Browse files
committed
Make AddUint64 use llvm.uadd.with.overflow.v2i32
When the input args are of type uint4, uses the vec2 variant of llvm.uadd.with.overflow to sum the low words of both args.
1 parent 4fae564 commit 45afa2f

File tree

3 files changed

+115
-77
lines changed

3 files changed

+115
-77
lines changed

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 42 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -19461,31 +19461,50 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
1946119461
4)) &&
1946219462
"input vectors must have 2 or 4 elements each");
1946319463

19464-
llvm::Value *Result = PoisonValue::get(OpA->getType());
1946519464
uint64_t NumElements =
1946619465
E->getArg(0)->getType()->castAs<VectorType>()->getNumElements();
19467-
for (uint64_t i = 0; i < NumElements / 2; ++i) {
19468-
19469-
// Obtain low and high words of inputs A and B
19470-
llvm::Value *LowA = Builder.CreateExtractElement(OpA, 2 * i + 0);
19471-
llvm::Value *HighA = Builder.CreateExtractElement(OpA, 2 * i + 1);
19472-
llvm::Value *LowB = Builder.CreateExtractElement(OpB, 2 * i + 0);
19473-
llvm::Value *HighB = Builder.CreateExtractElement(OpB, 2 * i + 1);
19474-
19475-
// Use an uadd_with_overflow to compute the sum of low words and obtain a
19476-
// carry value
19477-
llvm::Value *Carry;
19478-
llvm::Value *LowSum = EmitOverflowIntrinsic(
19479-
*this, llvm::Intrinsic::uadd_with_overflow, LowA, LowB, Carry);
19480-
llvm::Value *ZExtCarry = Builder.CreateZExt(Carry, HighA->getType());
19481-
19482-
// Sum the high words and the carry
19483-
llvm::Value *HighSum = Builder.CreateAdd(HighA, HighB);
19484-
llvm::Value *HighSumPlusCarry = Builder.CreateAdd(HighSum, ZExtCarry);
19485-
19486-
// Insert the low and high word sums into the result vector
19487-
Result = Builder.CreateInsertElement(Result, LowSum, 2 * i + 0);
19488-
Result = Builder.CreateInsertElement(Result, HighSumPlusCarry, 2 * i + 1,
19466+
19467+
llvm::Value *Result = PoisonValue::get(OpA->getType());
19468+
llvm::Value *LowA;
19469+
llvm::Value *HighA;
19470+
llvm::Value *LowB;
19471+
llvm::Value *HighB;
19472+
19473+
// Obtain low and high words of inputs A and B
19474+
if (NumElements == 2) {
19475+
LowA = Builder.CreateExtractElement(OpA, (uint64_t)0, "LowA");
19476+
HighA = Builder.CreateExtractElement(OpA, (uint64_t)1, "HighA");
19477+
LowB = Builder.CreateExtractElement(OpB, (uint64_t)0, "LowB");
19478+
HighB = Builder.CreateExtractElement(OpB, (uint64_t)1, "HighB");
19479+
} else {
19480+
LowA = Builder.CreateShuffleVector(OpA, ArrayRef<int>{0, 2}, "LowA");
19481+
HighA = Builder.CreateShuffleVector(OpA, ArrayRef<int>{1, 3}, "HighA");
19482+
LowB = Builder.CreateShuffleVector(OpB, ArrayRef<int>{0, 2}, "LowB");
19483+
HighB = Builder.CreateShuffleVector(OpB, ArrayRef<int>{1, 3}, "HighB");
19484+
}
19485+
19486+
// Use an uadd_with_overflow to compute the sum of low words and obtain a
19487+
// carry value
19488+
llvm::Value *Carry;
19489+
llvm::Value *LowSum = EmitOverflowIntrinsic(
19490+
*this, llvm::Intrinsic::uadd_with_overflow, LowA, LowB, Carry);
19491+
llvm::Value *ZExtCarry =
19492+
Builder.CreateZExt(Carry, HighA->getType(), "CarryZExt");
19493+
19494+
// Sum the high words and the carry
19495+
llvm::Value *HighSum = Builder.CreateAdd(HighA, HighB, "HighSum");
19496+
llvm::Value *HighSumPlusCarry =
19497+
Builder.CreateAdd(HighSum, ZExtCarry, "HighSumPlusCarry");
19498+
19499+
// Insert the low and high word sums into the result vector
19500+
if (NumElements == 2) {
19501+
Result = Builder.CreateInsertElement(Result, LowSum, (uint64_t)0,
19502+
"hlsl.AddUint64.upto0");
19503+
Result = Builder.CreateInsertElement(Result, HighSumPlusCarry,
19504+
(uint64_t)1, "hlsl.AddUint64");
19505+
} else { /* NumElements == 4 */
19506+
Result = Builder.CreateShuffleVector(LowSum, HighSumPlusCarry,
19507+
ArrayRef<int>{0, 2, 1, 3},
1948919508
"hlsl.AddUint64");
1949019509
}
1949119510
return Result;

clang/test/CodeGenHLSL/builtins/AddUint64.hlsl

Lines changed: 27 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,20 @@
1111
// CHECK-NEXT: [[B_ADDR:%.*]] = alloca <2 x i32>, align 8
1212
// CHECK-NEXT: store <2 x i32> [[A]], ptr [[A_ADDR]], align 8
1313
// CHECK-NEXT: store <2 x i32> [[B]], ptr [[B_ADDR]], align 8
14-
// CHECK-NEXT: [[A_LOAD:%.*]] = load <2 x i32>, ptr [[A_ADDR]], align 8
15-
// CHECK-NEXT: [[B_LOAD:%.*]] = load <2 x i32>, ptr [[B_ADDR]], align 8
16-
// CHECK-NEXT: [[LowA:%.*]] = extractelement <2 x i32> [[A_LOAD]], i64 0
17-
// CHECK-NEXT: [[HighA:%.*]] = extractelement <2 x i32> [[A_LOAD]], i64 1
18-
// CHECK-NEXT: [[LowB:%.*]] = extractelement <2 x i32> [[B_LOAD]], i64 0
19-
// CHECK-NEXT: [[HighB:%.*]] = extractelement <2 x i32> [[B_LOAD]], i64 1
20-
// CHECK-NEXT: [[UAddc:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[LowA]], i32 [[LowB]])
21-
// CHECK-NEXT: [[Carry:%.*]] = extractvalue { i32, i1 } [[UAddc]], 1
22-
// CHECK-NEXT: [[LowSum:%.*]] = extractvalue { i32, i1 } [[UAddc]], 0
23-
// CHECK-NEXT: [[CarryZExt:%.*]] = zext i1 [[Carry]] to i32
24-
// CHECK-NEXT: [[HighSum:%.*]] = add i32 [[HighA]], [[HighB]]
25-
// CHECK-NEXT: [[HighSumPlusCarry:%.*]] = add i32 [[HighSum]], [[CarryZExt]]
26-
// CHECK-NEXT: [[HLSL_ADDUINT64_UPTO0:%.*]] = insertelement <2 x i32> poison, i32 [[LowSum]], i64 0
27-
// CHECK-NEXT: [[HLSL_ADDUINT64:%.*]] = insertelement <2 x i32> [[HLSL_ADDUINT64_UPTO0]], i32 [[HighSumPlusCarry]], i64 1
14+
// CHECK-NEXT: [[TMP0:%.*]] = load <2 x i32>, ptr [[A_ADDR]], align 8
15+
// CHECK-NEXT: [[TMP1:%.*]] = load <2 x i32>, ptr [[B_ADDR]], align 8
16+
// CHECK-NEXT: [[LOWA:%.*]] = extractelement <2 x i32> [[TMP0]], i64 0
17+
// CHECK-NEXT: [[HIGHA:%.*]] = extractelement <2 x i32> [[TMP0]], i64 1
18+
// CHECK-NEXT: [[LOWB:%.*]] = extractelement <2 x i32> [[TMP1]], i64 0
19+
// CHECK-NEXT: [[HIGHB:%.*]] = extractelement <2 x i32> [[TMP1]], i64 1
20+
// CHECK-NEXT: [[TMP2:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[LOWA]], i32 [[LOWB]])
21+
// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP2]], 1
22+
// CHECK-NEXT: [[TMP4:%.*]] = extractvalue { i32, i1 } [[TMP2]], 0
23+
// CHECK-NEXT: [[CARRYZEXT:%.*]] = zext i1 [[TMP3]] to i32
24+
// CHECK-NEXT: [[HIGHSUM:%.*]] = add i32 [[HIGHA]], [[HIGHB]]
25+
// CHECK-NEXT: [[HIGHSUMPLUSCARRY:%.*]] = add i32 [[HIGHSUM]], [[CARRYZEXT]]
26+
// CHECK-NEXT: [[HLSL_ADDUINT64_UPTO0:%.*]] = insertelement <2 x i32> poison, i32 [[TMP4]], i64 0
27+
// CHECK-NEXT: [[HLSL_ADDUINT64:%.*]] = insertelement <2 x i32> [[HLSL_ADDUINT64_UPTO0]], i32 [[HIGHSUMPLUSCARRY]], i64 1
2828
// CHECK-NEXT: ret <2 x i32> [[HLSL_ADDUINT64]]
2929
//
3030
uint2 test_AddUint64_uint2(uint2 a, uint2 b) {
@@ -38,32 +38,19 @@ uint2 test_AddUint64_uint2(uint2 a, uint2 b) {
3838
// CHECK-NEXT: [[B_ADDR:%.*]] = alloca <4 x i32>, align 16
3939
// CHECK-NEXT: store <4 x i32> [[A]], ptr [[A_ADDR]], align 16
4040
// CHECK-NEXT: store <4 x i32> [[B]], ptr [[B_ADDR]], align 16
41-
// CHECK-NEXT: [[A_LOAD:%.*]] = load <4 x i32>, ptr [[A_ADDR]], align 16
42-
// CHECK-NEXT: [[B_LOAD:%.*]] = load <4 x i32>, ptr [[B_ADDR]], align 16
43-
// CHECK-NEXT: [[LowA:%.*]] = extractelement <4 x i32> [[A_LOAD]], i64 0
44-
// CHECK-NEXT: [[HighA:%.*]] = extractelement <4 x i32> [[A_LOAD]], i64 1
45-
// CHECK-NEXT: [[LowB:%.*]] = extractelement <4 x i32> [[B_LOAD]], i64 0
46-
// CHECK-NEXT: [[HighB:%.*]] = extractelement <4 x i32> [[B_LOAD]], i64 1
47-
// CHECK-NEXT: [[UAddc:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[LowA]], i32 [[LowB]])
48-
// CHECK-NEXT: [[Carry:%.*]] = extractvalue { i32, i1 } [[UAddc]], 1
49-
// CHECK-NEXT: [[LowSum:%.*]] = extractvalue { i32, i1 } [[UAddc]], 0
50-
// CHECK-NEXT: [[CarryZExt:%.*]] = zext i1 [[Carry]] to i32
51-
// CHECK-NEXT: [[HighSum:%.*]] = add i32 [[HighA]], [[HighB]]
52-
// CHECK-NEXT: [[HighSumPlusCarry:%.*]] = add i32 [[HighSum]], [[CarryZExt]]
53-
// CHECK-NEXT: [[HLSL_ADDUINT64_UPTO0:%.*]] = insertelement <4 x i32> poison, i32 [[LowSum]], i64 0
54-
// CHECK-NEXT: [[HLSL_ADDUINT64_UPTO1:%.*]] = insertelement <4 x i32> [[HLSL_ADDUINT64_UPTO0]], i32 [[HighSumPlusCarry]], i64 1
55-
// CHECK-NEXT: [[LowA1:%.*]] = extractelement <4 x i32> [[A_LOAD]], i64 2
56-
// CHECK-NEXT: [[HighA1:%.*]] = extractelement <4 x i32> [[A_LOAD]], i64 3
57-
// CHECK-NEXT: [[LowB1:%.*]] = extractelement <4 x i32> [[B_LOAD]], i64 2
58-
// CHECK-NEXT: [[HighB1:%.*]] = extractelement <4 x i32> [[B_LOAD]], i64 3
59-
// CHECK-NEXT: [[UAddc1:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[LowA1]], i32 [[LowB1]])
60-
// CHECK-NEXT: [[Carry1:%.*]] = extractvalue { i32, i1 } [[UAddc1]], 1
61-
// CHECK-NEXT: [[LowSum1:%.*]] = extractvalue { i32, i1 } [[UAddc1]], 0
62-
// CHECK-NEXT: [[CarryZExt1:%.*]] = zext i1 [[Carry1]] to i32
63-
// CHECK-NEXT: [[HighSum1:%.*]] = add i32 [[HighA1]], [[HighB1]]
64-
// CHECK-NEXT: [[HighSumPlusCarry1:%.*]] = add i32 [[HighSum1]], [[CarryZExt1]]
65-
// CHECK-NEXT: [[HLSL_ADDUINT64_UPTO2:%.*]] = insertelement <4 x i32> [[HLSL_ADDUINT64_UPTO1]], i32 [[LowSum1]], i64 2
66-
// CHECK-NEXT: [[HLSL_ADDUINT64:%.*]] = insertelement <4 x i32> [[HLSL_ADDUINT64_UPTO2]], i32 [[HighSumPlusCarry1]], i64 3
41+
// CHECK-NEXT: [[TMP0:%.*]] = load <4 x i32>, ptr [[A_ADDR]], align 16
42+
// CHECK-NEXT: [[TMP1:%.*]] = load <4 x i32>, ptr [[B_ADDR]], align 16
43+
// CHECK-NEXT: [[LOWA:%.*]] = shufflevector <4 x i32> [[TMP0]], <4 x i32> poison, <2 x i32> <i32 0, i32 2>
44+
// CHECK-NEXT: [[HIGHA:%.*]] = shufflevector <4 x i32> [[TMP0]], <4 x i32> poison, <2 x i32> <i32 1, i32 3>
45+
// CHECK-NEXT: [[LOWB:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <2 x i32> <i32 0, i32 2>
46+
// CHECK-NEXT: [[HIGHB:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <2 x i32> <i32 1, i32 3>
47+
// CHECK-NEXT: [[TMP2:%.*]] = call { <2 x i32>, <2 x i1> } @llvm.uadd.with.overflow.v2i32(<2 x i32> [[LOWA]], <2 x i32> [[LOWB]])
48+
// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { <2 x i32>, <2 x i1> } [[TMP2]], 1
49+
// CHECK-NEXT: [[TMP4:%.*]] = extractvalue { <2 x i32>, <2 x i1> } [[TMP2]], 0
50+
// CHECK-NEXT: [[CARRYZEXT:%.*]] = zext <2 x i1> [[TMP3]] to <2 x i32>
51+
// CHECK-NEXT: [[HIGHSUM:%.*]] = add <2 x i32> [[HIGHA]], [[HIGHB]]
52+
// CHECK-NEXT: [[HIGHSUMPLUSCARRY:%.*]] = add <2 x i32> [[HIGHSUM]], [[CARRYZEXT]]
53+
// CHECK-NEXT: [[HLSL_ADDUINT64:%.*]] = shufflevector <2 x i32> [[TMP4]], <2 x i32> [[HIGHSUMPLUSCARRY]], <4 x i32> <i32 0, i32 2, i32 1, i32 3>
6754
// CHECK-NEXT: ret <4 x i32> [[HLSL_ADDUINT64]]
6855
//
6956
uint4 test_AddUint64_uint4(uint4 a, uint4 b) {

llvm/test/CodeGen/DirectX/UAddc.ll

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
1-
; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt -S -scalarizer -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
23

34
; CHECK: %dx.types.i32c = type { i32, i1 }
45

56
define noundef i32 @test_UAddc(i32 noundef %a, i32 noundef %b) {
67
; CHECK-LABEL: define noundef i32 @test_UAddc(
78
; CHECK-SAME: i32 noundef [[A:%.*]], i32 noundef [[B:%.*]]) {
8-
; CHECK-NEXT: [[UAddc:%.*]] = call %dx.types.i32c @dx.op.binaryWithCarryOrBorrow.i32(i32 44, i32 [[A]], i32 [[B]])
9-
; CHECK-NEXT: [[Carry:%.*]] = extractvalue %dx.types.i32c [[UAddc]], 1
10-
; CHECK-NEXT: [[Sum:%.*]] = extractvalue %dx.types.i32c [[UAddc]], 0
11-
; CHECK-NEXT: [[CarryZExt:%.*]] = zext i1 [[Carry]] to i32
12-
; CHECK-NEXT: [[Result:%.*]] = add i32 [[Sum]], [[CarryZExt]]
13-
; CHECK-NEXT: ret i32 [[Result]]
14-
;
9+
; CHECK-NEXT: [[UADDC1:%.*]] = call [[DX_TYPES_I32C:%.*]] @[[DX_OP_BINARYWITHCARRYORBORROW_I32:[a-zA-Z0-9_$\"\\.-]*[a-zA-Z_$\"\\.-][a-zA-Z0-9_$\"\\.-]*]](i32 44, i32 [[A]], i32 [[B]]) #[[ATTR0:[0-9]+]]
10+
; CHECK-NEXT: [[CARRY:%.*]] = extractvalue [[DX_TYPES_I32C]] [[UADDC1]], 1
11+
; CHECK-NEXT: [[SUM:%.*]] = extractvalue [[DX_TYPES_I32C]] [[UADDC1]], 0
12+
; CHECK-NEXT: [[CARRY_ZEXT:%.*]] = zext i1 [[CARRY]] to i32
13+
; CHECK-NEXT: [[RESULT:%.*]] = add i32 [[SUM]], [[CARRY_ZEXT]]
14+
; CHECK-NEXT: ret i32 [[RESULT]]
15+
;
1516
%uaddc = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %a, i32 %b)
1617
%carry = extractvalue { i32, i1 } %uaddc, 1
1718
%sum = extractvalue { i32, i1 } %uaddc, 0
@@ -20,21 +21,52 @@ define noundef i32 @test_UAddc(i32 noundef %a, i32 noundef %b) {
2021
ret i32 %result
2122
}
2223

24+
define noundef <2 x i32> @test_UAddc_vec2(<2 x i32> noundef %a, <2 x i32> noundef %b) {
25+
; CHECK-LABEL: define noundef <2 x i32> @test_UAddc_vec2(
26+
; CHECK-SAME: <2 x i32> noundef [[A:%.*]], <2 x i32> noundef [[B:%.*]]) {
27+
; CHECK-NEXT: [[A_I0:%.*]] = extractelement <2 x i32> [[A]], i64 0
28+
; CHECK-NEXT: [[B_I0:%.*]] = extractelement <2 x i32> [[B]], i64 0
29+
; CHECK-NEXT: [[UADDC_I09:%.*]] = call [[DX_TYPES_I32C:%.*]] @[[DX_OP_BINARYWITHCARRYORBORROW_I32]](i32 44, i32 [[A_I0]], i32 [[B_I0]]) #[[ATTR0]]
30+
; CHECK-NEXT: [[A_I1:%.*]] = extractelement <2 x i32> [[A]], i64 1
31+
; CHECK-NEXT: [[B_I1:%.*]] = extractelement <2 x i32> [[B]], i64 1
32+
; CHECK-NEXT: [[UADDC_I18:%.*]] = call [[DX_TYPES_I32C]] @[[DX_OP_BINARYWITHCARRYORBORROW_I32]](i32 44, i32 [[A_I1]], i32 [[B_I1]]) #[[ATTR0]]
33+
; CHECK-NEXT: [[CARRY_ELEM1:%.*]] = extractvalue [[DX_TYPES_I32C]] [[UADDC_I09]], 1
34+
; CHECK-NEXT: [[CARRY_ELEM11:%.*]] = extractvalue [[DX_TYPES_I32C]] [[UADDC_I18]], 1
35+
; CHECK-NEXT: [[CARRY_UPTO0:%.*]] = insertelement <2 x i1> poison, i1 [[CARRY_ELEM1]], i64 0
36+
; CHECK-NEXT: [[CARRY:%.*]] = insertelement <2 x i1> [[CARRY_UPTO0]], i1 [[CARRY_ELEM11]], i64 1
37+
; CHECK-NEXT: [[CARRY_I0:%.*]] = extractelement <2 x i1> [[CARRY]], i64 0
38+
; CHECK-NEXT: [[CARRY_I1:%.*]] = extractelement <2 x i1> [[CARRY]], i64 1
39+
; CHECK-NEXT: [[SUM_ELEM0:%.*]] = extractvalue [[DX_TYPES_I32C]] [[UADDC_I09]], 0
40+
; CHECK-NEXT: [[SUM_ELEM02:%.*]] = extractvalue [[DX_TYPES_I32C]] [[UADDC_I18]], 0
41+
; CHECK-NEXT: [[CARRY_ZEXT_I0:%.*]] = zext i1 [[CARRY_I0]] to i32
42+
; CHECK-NEXT: [[CARRY_ZEXT_I1:%.*]] = zext i1 [[CARRY_I1]] to i32
43+
; CHECK-NEXT: [[RESULT_I0:%.*]] = add i32 [[SUM_ELEM0]], [[CARRY_ZEXT_I0]]
44+
; CHECK-NEXT: [[RESULT_I1:%.*]] = add i32 [[SUM_ELEM02]], [[CARRY_ZEXT_I1]]
45+
; CHECK-NEXT: [[RESULT_UPTO0:%.*]] = insertelement <2 x i32> poison, i32 [[RESULT_I0]], i64 0
46+
; CHECK-NEXT: [[RESULT:%.*]] = insertelement <2 x i32> [[RESULT_UPTO0]], i32 [[RESULT_I1]], i64 1
47+
; CHECK-NEXT: ret <2 x i32> [[RESULT]]
48+
;
49+
%uaddc = call { <2 x i32>, <2 x i1> } @llvm.uadd.with.overflow.v2i32(<2 x i32> %a, <2 x i32> %b)
50+
%carry = extractvalue { <2 x i32>, <2 x i1> } %uaddc, 1
51+
%sum = extractvalue { <2 x i32>, <2 x i1> } %uaddc, 0
52+
%carry_zext = zext <2 x i1> %carry to <2 x i32>
53+
%result = add <2 x i32> %sum, %carry_zext
54+
ret <2 x i32> %result
55+
}
2356

2457
define noundef i32 @test_UAddc_insert(i32 noundef %a, i32 noundef %b) {
2558
; CHECK-LABEL: define noundef i32 @test_UAddc_insert(
2659
; CHECK-SAME: i32 noundef [[A:%.*]], i32 noundef [[B:%.*]]) {
27-
; CHECK-NEXT: [[UAddc:%.*]] = call %dx.types.i32c @dx.op.binaryWithCarryOrBorrow.i32(i32 44, i32 [[A]], i32 [[B]])
28-
; CHECK-NEXT: insertvalue %dx.types.i32c [[UAddc]], i32 [[A]], 0
29-
; CHECK-NEXT: [[Result:%.*]] = extractvalue %dx.types.i32c [[UAddc]], 0
30-
; CHECK-NEXT: ret i32 [[Result]]
31-
;
60+
; CHECK-NEXT: [[UADDC1:%.*]] = call [[DX_TYPES_I32C:%.*]] @[[DX_OP_BINARYWITHCARRYORBORROW_I32]](i32 44, i32 [[A]], i32 [[B]]) #[[ATTR0]]
61+
; CHECK-NEXT: [[TMP1:%.*]] = insertvalue [[DX_TYPES_I32C]] [[UADDC1]], i32 [[A]], 0
62+
; CHECK-NEXT: [[RESULT:%.*]] = extractvalue [[DX_TYPES_I32C]] [[UADDC1]], 0
63+
; CHECK-NEXT: ret i32 [[RESULT]]
64+
;
3265
%uaddc = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %a, i32 %b)
3366
insertvalue { i32, i1 } %uaddc, i32 %a, 0
3467
%result = extractvalue { i32, i1 } %uaddc, 0
3568
ret i32 %result
3669
}
3770

3871
declare { i32, i1 } @llvm.uadd.with.overflow.i32(i32, i32)
39-
; CHECK: declare %dx.types.i32c @dx.op.binaryWithCarryOrBorrow.i32(i32, i32, i32)
4072

0 commit comments

Comments
 (0)