blob: f83b7b46e585945d6696863fd870116c58326283 [file] [edit]
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt -S -dxil-intrinsic-expansion -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
; Verify the {u,s}mul.with.overflow intrinsics are expanded away, since DXIL has
; no llvm.*.with.overflow op. The overflow check is computed without a wider
; integer type so that no 64-bit ops are introduced.
define { i32, i1 } @umul_i32(i32 %a, i32 %b) {
; CHECK-LABEL: define { i32, i1 } @umul_i32(
; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
; CHECK-NEXT: [[TMP2:%.*]] = call { i32, i32 } @llvm.dx.umul.i32(i32 [[A]], i32 [[B]])
; CHECK-NEXT: [[TMP17:%.*]] = extractvalue { i32, i32 } [[TMP2]], 0
; CHECK-NEXT: [[TMP1:%.*]] = extractvalue { i32, i32 } [[TMP2]], 1
; CHECK-NEXT: [[TMP18:%.*]] = icmp ne i32 [[TMP17]], 0
; CHECK-NEXT: [[TMP19:%.*]] = insertvalue { i32, i1 } poison, i32 [[TMP1]], 0
; CHECK-NEXT: [[TMP20:%.*]] = insertvalue { i32, i1 } [[TMP19]], i1 [[TMP18]], 1
; CHECK-NEXT: ret { i32, i1 } [[TMP20]]
;
%r = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %a, i32 %b)
ret { i32, i1 } %r
}
define { <4 x i32>, <4 x i1> } @umul_v4i32(<4 x i32> %a, <4 x i32> %b) {
; CHECK-LABEL: define { <4 x i32>, <4 x i1> } @umul_v4i32(
; CHECK-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) {
; CHECK-NEXT: [[TMP2:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.dx.umul.v4i32(<4 x i32> [[A]], <4 x i32> [[B]])
; CHECK-NEXT: [[TMP17:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[TMP2]], 0
; CHECK-NEXT: [[TMP1:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[TMP2]], 1
; CHECK-NEXT: [[TMP18:%.*]] = icmp ne <4 x i32> [[TMP17]], zeroinitializer
; CHECK-NEXT: [[TMP19:%.*]] = insertvalue { <4 x i32>, <4 x i1> } poison, <4 x i32> [[TMP1]], 0
; CHECK-NEXT: [[TMP20:%.*]] = insertvalue { <4 x i32>, <4 x i1> } [[TMP19]], <4 x i1> [[TMP18]], 1
; CHECK-NEXT: ret { <4 x i32>, <4 x i1> } [[TMP20]]
;
%r = call { <4 x i32>, <4 x i1> } @llvm.umul.with.overflow.v4i32(<4 x i32> %a, <4 x i32> %b)
ret { <4 x i32>, <4 x i1> } %r
}
define { i32, i1 } @smul_i32(i32 %a, i32 %b) {
; CHECK-LABEL: define { i32, i1 } @smul_i32(
; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
; CHECK-NEXT: [[TMP2:%.*]] = call { i32, i32 } @llvm.dx.imul.i32(i32 [[A]], i32 [[B]])
; CHECK-NEXT: [[TMP23:%.*]] = extractvalue { i32, i32 } [[TMP2]], 0
; CHECK-NEXT: [[TMP1:%.*]] = extractvalue { i32, i32 } [[TMP2]], 1
; CHECK-NEXT: [[TMP24:%.*]] = ashr i32 [[TMP1]], 31
; CHECK-NEXT: [[TMP25:%.*]] = icmp ne i32 [[TMP23]], [[TMP24]]
; CHECK-NEXT: [[TMP26:%.*]] = insertvalue { i32, i1 } poison, i32 [[TMP1]], 0
; CHECK-NEXT: [[TMP27:%.*]] = insertvalue { i32, i1 } [[TMP26]], i1 [[TMP25]], 1
; CHECK-NEXT: ret { i32, i1 } [[TMP27]]
;
%r = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %a, i32 %b)
ret { i32, i1 } %r
}
; Narrow overloads widen to a 2*BW multiply, since that stays within 32 bits.
define { i16, i1 } @umul_i16(i16 %a, i16 %b) {
; CHECK-LABEL: define { i16, i1 } @umul_i16(
; CHECK-SAME: i16 [[A:%.*]], i16 [[B:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = mul i16 [[A]], [[B]]
; CHECK-NEXT: [[TMP2:%.*]] = zext i16 [[A]] to i32
; CHECK-NEXT: [[TMP3:%.*]] = zext i16 [[B]] to i32
; CHECK-NEXT: [[TMP4:%.*]] = mul i32 [[TMP2]], [[TMP3]]
; CHECK-NEXT: [[TMP5:%.*]] = lshr i32 [[TMP4]], 16
; CHECK-NEXT: [[TMP6:%.*]] = icmp ne i32 [[TMP5]], 0
; CHECK-NEXT: [[TMP7:%.*]] = insertvalue { i16, i1 } poison, i16 [[TMP1]], 0
; CHECK-NEXT: [[TMP8:%.*]] = insertvalue { i16, i1 } [[TMP7]], i1 [[TMP6]], 1
; CHECK-NEXT: ret { i16, i1 } [[TMP8]]
;
%r = call { i16, i1 } @llvm.umul.with.overflow.i16(i16 %a, i16 %b)
ret { i16, i1 } %r
}
define { i16, i1 } @smul_i16(i16 %a, i16 %b) {
; CHECK-LABEL: define { i16, i1 } @smul_i16(
; CHECK-SAME: i16 [[A:%.*]], i16 [[B:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = mul i16 [[A]], [[B]]
; CHECK-NEXT: [[TMP2:%.*]] = sext i16 [[A]] to i32
; CHECK-NEXT: [[TMP3:%.*]] = sext i16 [[B]] to i32
; CHECK-NEXT: [[TMP4:%.*]] = mul i32 [[TMP2]], [[TMP3]]
; CHECK-NEXT: [[TMP5:%.*]] = sext i16 [[TMP1]] to i32
; CHECK-NEXT: [[TMP6:%.*]] = icmp ne i32 [[TMP4]], [[TMP5]]
; CHECK-NEXT: [[TMP7:%.*]] = insertvalue { i16, i1 } poison, i16 [[TMP1]], 0
; CHECK-NEXT: [[TMP8:%.*]] = insertvalue { i16, i1 } [[TMP7]], i1 [[TMP6]], 1
; CHECK-NEXT: ret { i16, i1 } [[TMP8]]
;
%r = call { i16, i1 } @llvm.smul.with.overflow.i16(i16 %a, i16 %b)
ret { i16, i1 } %r
}