[IR] Allow fast math flags on calls with homogeneous FP struct types (#110506)
This extends FPMathOperator to allow calls that return literal structs of homogeneous floating-point or vector-of-floating-point types. The intended use case for this is to support FP intrinsics that return multiple values (such as `llvm.sincos`).
This commit is contained in:
parent
66f84c8b8a
commit
95f00a63ce
@ -1220,7 +1220,7 @@ _Complex _Float16 mulf16(_Complex _Float16 a, _Complex _Float16 b) {
|
||||
// FULL_FAST-NEXT: [[C_IMAG:%.*]] = load half, ptr [[C_IMAGP]], align 2
|
||||
// FULL_FAST-NEXT: [[CONV:%.*]] = fpext half [[C_REAL]] to x86_fp80
|
||||
// FULL_FAST-NEXT: [[CONV1:%.*]] = fpext half [[C_IMAG]] to x86_fp80
|
||||
// FULL_FAST-NEXT: [[CALL:%.*]] = call { x86_fp80, x86_fp80 } @__divxc3(x86_fp80 noundef nofpclass(nan inf) [[B_REAL]], x86_fp80 noundef nofpclass(nan inf) [[B_IMAG]], x86_fp80 noundef nofpclass(nan inf) [[CONV]], x86_fp80 noundef nofpclass(nan inf) [[CONV1]]) #[[ATTR1]]
|
||||
// FULL_FAST-NEXT: [[CALL:%.*]] = call reassoc nnan ninf nsz arcp afn nofpclass(nan inf) { x86_fp80, x86_fp80 } @__divxc3(x86_fp80 noundef nofpclass(nan inf) [[B_REAL]], x86_fp80 noundef nofpclass(nan inf) [[B_IMAG]], x86_fp80 noundef nofpclass(nan inf) [[CONV]], x86_fp80 noundef nofpclass(nan inf) [[CONV1]]) #[[ATTR1]]
|
||||
// FULL_FAST-NEXT: [[TMP0:%.*]] = extractvalue { x86_fp80, x86_fp80 } [[CALL]], 0
|
||||
// FULL_FAST-NEXT: [[TMP1:%.*]] = extractvalue { x86_fp80, x86_fp80 } [[CALL]], 1
|
||||
// FULL_FAST-NEXT: [[CONV2:%.*]] = fptrunc x86_fp80 [[TMP0]] to half
|
||||
|
||||
@ -1382,7 +1382,7 @@ _Complex float mulf(_Complex float a, _Complex float b) {
|
||||
// AVRFP64-NEXT: store double [[AGG_RESULT_IMAG]], ptr [[AGG_RESULT_IMAGP4]], align 1
|
||||
// AVRFP64-NEXT: ret void
|
||||
//
|
||||
// BASIC_FAST-LABEL: define dso_local { double, double } @divd(
|
||||
// BASIC_FAST-LABEL: define dso_local nofpclass(nan inf) { double, double } @divd(
|
||||
// BASIC_FAST-SAME: double noundef nofpclass(nan inf) [[A_COERCE0:%.*]], double noundef nofpclass(nan inf) [[A_COERCE1:%.*]], double noundef nofpclass(nan inf) [[B_COERCE0:%.*]], double noundef nofpclass(nan inf) [[B_COERCE1:%.*]]) #[[ATTR1:[0-9]+]] {
|
||||
// BASIC_FAST-NEXT: entry:
|
||||
// BASIC_FAST-NEXT: [[RETVAL:%.*]] = alloca { double, double }, align 8
|
||||
@ -1422,7 +1422,7 @@ _Complex float mulf(_Complex float a, _Complex float b) {
|
||||
// BASIC_FAST-NEXT: [[TMP15:%.*]] = load { double, double }, ptr [[RETVAL]], align 8
|
||||
// BASIC_FAST-NEXT: ret { double, double } [[TMP15]]
|
||||
//
|
||||
// FULL_FAST-LABEL: define dso_local { double, double } @divd(
|
||||
// FULL_FAST-LABEL: define dso_local nofpclass(nan inf) { double, double } @divd(
|
||||
// FULL_FAST-SAME: double noundef nofpclass(nan inf) [[A_COERCE0:%.*]], double noundef nofpclass(nan inf) [[A_COERCE1:%.*]], double noundef nofpclass(nan inf) [[B_COERCE0:%.*]], double noundef nofpclass(nan inf) [[B_COERCE1:%.*]]) #[[ATTR1:[0-9]+]] {
|
||||
// FULL_FAST-NEXT: entry:
|
||||
// FULL_FAST-NEXT: [[RETVAL:%.*]] = alloca { double, double }, align 8
|
||||
@ -1444,7 +1444,7 @@ _Complex float mulf(_Complex float a, _Complex float b) {
|
||||
// FULL_FAST-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8
|
||||
// FULL_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[B]], i32 0, i32 1
|
||||
// FULL_FAST-NEXT: [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 8
|
||||
// FULL_FAST-NEXT: [[CALL:%.*]] = call { double, double } @__divdc3(double noundef nofpclass(nan inf) [[A_REAL]], double noundef nofpclass(nan inf) [[A_IMAG]], double noundef nofpclass(nan inf) [[B_REAL]], double noundef nofpclass(nan inf) [[B_IMAG]]) #[[ATTR2]]
|
||||
// FULL_FAST-NEXT: [[CALL:%.*]] = call reassoc nnan ninf nsz arcp afn nofpclass(nan inf) { double, double } @__divdc3(double noundef nofpclass(nan inf) [[A_REAL]], double noundef nofpclass(nan inf) [[A_IMAG]], double noundef nofpclass(nan inf) [[B_REAL]], double noundef nofpclass(nan inf) [[B_IMAG]]) #[[ATTR2]]
|
||||
// FULL_FAST-NEXT: [[TMP4:%.*]] = extractvalue { double, double } [[CALL]], 0
|
||||
// FULL_FAST-NEXT: [[TMP5:%.*]] = extractvalue { double, double } [[CALL]], 1
|
||||
// FULL_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[RETVAL]], i32 0, i32 0
|
||||
@ -1454,7 +1454,7 @@ _Complex float mulf(_Complex float a, _Complex float b) {
|
||||
// FULL_FAST-NEXT: [[TMP6:%.*]] = load { double, double }, ptr [[RETVAL]], align 8
|
||||
// FULL_FAST-NEXT: ret { double, double } [[TMP6]]
|
||||
//
|
||||
// IMPRVD_FAST-LABEL: define dso_local { double, double } @divd(
|
||||
// IMPRVD_FAST-LABEL: define dso_local nofpclass(nan inf) { double, double } @divd(
|
||||
// IMPRVD_FAST-SAME: double noundef nofpclass(nan inf) [[A_COERCE0:%.*]], double noundef nofpclass(nan inf) [[A_COERCE1:%.*]], double noundef nofpclass(nan inf) [[B_COERCE0:%.*]], double noundef nofpclass(nan inf) [[B_COERCE1:%.*]]) #[[ATTR2:[0-9]+]] {
|
||||
// IMPRVD_FAST-NEXT: entry:
|
||||
// IMPRVD_FAST-NEXT: [[RETVAL:%.*]] = alloca { double, double }, align 8
|
||||
@ -1512,7 +1512,7 @@ _Complex float mulf(_Complex float a, _Complex float b) {
|
||||
// IMPRVD_FAST-NEXT: [[TMP26:%.*]] = load { double, double }, ptr [[RETVAL]], align 8
|
||||
// IMPRVD_FAST-NEXT: ret { double, double } [[TMP26]]
|
||||
//
|
||||
// PRMTD_FAST-LABEL: define dso_local { double, double } @divd(
|
||||
// PRMTD_FAST-LABEL: define dso_local nofpclass(nan inf) { double, double } @divd(
|
||||
// PRMTD_FAST-SAME: double noundef nofpclass(nan inf) [[A_COERCE0:%.*]], double noundef nofpclass(nan inf) [[A_COERCE1:%.*]], double noundef nofpclass(nan inf) [[B_COERCE0:%.*]], double noundef nofpclass(nan inf) [[B_COERCE1:%.*]]) #[[ATTR1:[0-9]+]] {
|
||||
// PRMTD_FAST-NEXT: entry:
|
||||
// PRMTD_FAST-NEXT: [[RETVAL:%.*]] = alloca { double, double }, align 8
|
||||
@ -1934,7 +1934,7 @@ _Complex double divd(_Complex double a, _Complex double b) {
|
||||
// AVRFP64-NEXT: store double [[AGG_RESULT_IMAG]], ptr [[AGG_RESULT_IMAGP4]], align 1
|
||||
// AVRFP64-NEXT: ret void
|
||||
//
|
||||
// BASIC_FAST-LABEL: define dso_local { double, double } @muld(
|
||||
// BASIC_FAST-LABEL: define dso_local nofpclass(nan inf) { double, double } @muld(
|
||||
// BASIC_FAST-SAME: double noundef nofpclass(nan inf) [[A_COERCE0:%.*]], double noundef nofpclass(nan inf) [[A_COERCE1:%.*]], double noundef nofpclass(nan inf) [[B_COERCE0:%.*]], double noundef nofpclass(nan inf) [[B_COERCE1:%.*]]) #[[ATTR1]] {
|
||||
// BASIC_FAST-NEXT: entry:
|
||||
// BASIC_FAST-NEXT: [[RETVAL:%.*]] = alloca { double, double }, align 8
|
||||
@ -1969,7 +1969,7 @@ _Complex double divd(_Complex double a, _Complex double b) {
|
||||
// BASIC_FAST-NEXT: [[TMP4:%.*]] = load { double, double }, ptr [[RETVAL]], align 8
|
||||
// BASIC_FAST-NEXT: ret { double, double } [[TMP4]]
|
||||
//
|
||||
// FULL_FAST-LABEL: define dso_local { double, double } @muld(
|
||||
// FULL_FAST-LABEL: define dso_local nofpclass(nan inf) { double, double } @muld(
|
||||
// FULL_FAST-SAME: double noundef nofpclass(nan inf) [[A_COERCE0:%.*]], double noundef nofpclass(nan inf) [[A_COERCE1:%.*]], double noundef nofpclass(nan inf) [[B_COERCE0:%.*]], double noundef nofpclass(nan inf) [[B_COERCE1:%.*]]) #[[ATTR1]] {
|
||||
// FULL_FAST-NEXT: entry:
|
||||
// FULL_FAST-NEXT: [[RETVAL:%.*]] = alloca { double, double }, align 8
|
||||
@ -2003,7 +2003,7 @@ _Complex double divd(_Complex double a, _Complex double b) {
|
||||
// FULL_FAST-NEXT: [[ISNAN_CMP1:%.*]] = fcmp reassoc nnan ninf nsz arcp afn uno double [[MUL_I]], [[MUL_I]]
|
||||
// FULL_FAST-NEXT: br i1 [[ISNAN_CMP1]], label [[COMPLEX_MUL_LIBCALL:%.*]], label [[COMPLEX_MUL_CONT]], !prof [[PROF2]]
|
||||
// FULL_FAST: complex_mul_libcall:
|
||||
// FULL_FAST-NEXT: [[CALL:%.*]] = call { double, double } @__muldc3(double noundef nofpclass(nan inf) [[A_REAL]], double noundef nofpclass(nan inf) [[A_IMAG]], double noundef nofpclass(nan inf) [[B_REAL]], double noundef nofpclass(nan inf) [[B_IMAG]]) #[[ATTR2]]
|
||||
// FULL_FAST-NEXT: [[CALL:%.*]] = call reassoc nnan ninf nsz arcp afn nofpclass(nan inf) { double, double } @__muldc3(double noundef nofpclass(nan inf) [[A_REAL]], double noundef nofpclass(nan inf) [[A_IMAG]], double noundef nofpclass(nan inf) [[B_REAL]], double noundef nofpclass(nan inf) [[B_IMAG]]) #[[ATTR2]]
|
||||
// FULL_FAST-NEXT: [[TMP4:%.*]] = extractvalue { double, double } [[CALL]], 0
|
||||
// FULL_FAST-NEXT: [[TMP5:%.*]] = extractvalue { double, double } [[CALL]], 1
|
||||
// FULL_FAST-NEXT: br label [[COMPLEX_MUL_CONT]]
|
||||
@ -2017,7 +2017,7 @@ _Complex double divd(_Complex double a, _Complex double b) {
|
||||
// FULL_FAST-NEXT: [[TMP6:%.*]] = load { double, double }, ptr [[RETVAL]], align 8
|
||||
// FULL_FAST-NEXT: ret { double, double } [[TMP6]]
|
||||
//
|
||||
// IMPRVD_FAST-LABEL: define dso_local { double, double } @muld(
|
||||
// IMPRVD_FAST-LABEL: define dso_local nofpclass(nan inf) { double, double } @muld(
|
||||
// IMPRVD_FAST-SAME: double noundef nofpclass(nan inf) [[A_COERCE0:%.*]], double noundef nofpclass(nan inf) [[A_COERCE1:%.*]], double noundef nofpclass(nan inf) [[B_COERCE0:%.*]], double noundef nofpclass(nan inf) [[B_COERCE1:%.*]]) #[[ATTR2]] {
|
||||
// IMPRVD_FAST-NEXT: entry:
|
||||
// IMPRVD_FAST-NEXT: [[RETVAL:%.*]] = alloca { double, double }, align 8
|
||||
@ -2052,7 +2052,7 @@ _Complex double divd(_Complex double a, _Complex double b) {
|
||||
// IMPRVD_FAST-NEXT: [[TMP4:%.*]] = load { double, double }, ptr [[RETVAL]], align 8
|
||||
// IMPRVD_FAST-NEXT: ret { double, double } [[TMP4]]
|
||||
//
|
||||
// PRMTD_FAST-LABEL: define dso_local { double, double } @muld(
|
||||
// PRMTD_FAST-LABEL: define dso_local nofpclass(nan inf) { double, double } @muld(
|
||||
// PRMTD_FAST-SAME: double noundef nofpclass(nan inf) [[A_COERCE0:%.*]], double noundef nofpclass(nan inf) [[A_COERCE1:%.*]], double noundef nofpclass(nan inf) [[B_COERCE0:%.*]], double noundef nofpclass(nan inf) [[B_COERCE1:%.*]]) #[[ATTR1]] {
|
||||
// PRMTD_FAST-NEXT: entry:
|
||||
// PRMTD_FAST-NEXT: [[RETVAL:%.*]] = alloca { double, double }, align 8
|
||||
@ -2493,7 +2493,7 @@ _Complex double muld(_Complex double a, _Complex double b) {
|
||||
// AVRFP64-NEXT: store double [[AGG_RESULT_IMAG]], ptr [[AGG_RESULT_IMAGP4]], align 1
|
||||
// AVRFP64-NEXT: ret void
|
||||
//
|
||||
// BASIC_FAST-LABEL: define dso_local { x86_fp80, x86_fp80 } @divld(
|
||||
// BASIC_FAST-LABEL: define dso_local nofpclass(nan inf) { x86_fp80, x86_fp80 } @divld(
|
||||
// BASIC_FAST-SAME: ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[A:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]]) #[[ATTR1]] {
|
||||
// BASIC_FAST-NEXT: entry:
|
||||
// BASIC_FAST-NEXT: [[RETVAL:%.*]] = alloca { x86_fp80, x86_fp80 }, align 16
|
||||
@ -2523,7 +2523,7 @@ _Complex double muld(_Complex double a, _Complex double b) {
|
||||
// BASIC_FAST-NEXT: [[TMP11:%.*]] = load { x86_fp80, x86_fp80 }, ptr [[RETVAL]], align 16
|
||||
// BASIC_FAST-NEXT: ret { x86_fp80, x86_fp80 } [[TMP11]]
|
||||
//
|
||||
// FULL_FAST-LABEL: define dso_local { x86_fp80, x86_fp80 } @divld(
|
||||
// FULL_FAST-LABEL: define dso_local nofpclass(nan inf) { x86_fp80, x86_fp80 } @divld(
|
||||
// FULL_FAST-SAME: ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[A:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]]) #[[ATTR1]] {
|
||||
// FULL_FAST-NEXT: entry:
|
||||
// FULL_FAST-NEXT: [[RETVAL:%.*]] = alloca { x86_fp80, x86_fp80 }, align 16
|
||||
@ -2535,7 +2535,7 @@ _Complex double muld(_Complex double a, _Complex double b) {
|
||||
// FULL_FAST-NEXT: [[B_REAL:%.*]] = load x86_fp80, ptr [[B_REALP]], align 16
|
||||
// FULL_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 1
|
||||
// FULL_FAST-NEXT: [[B_IMAG:%.*]] = load x86_fp80, ptr [[B_IMAGP]], align 16
|
||||
// FULL_FAST-NEXT: [[CALL:%.*]] = call { x86_fp80, x86_fp80 } @__divxc3(x86_fp80 noundef nofpclass(nan inf) [[A_REAL]], x86_fp80 noundef nofpclass(nan inf) [[A_IMAG]], x86_fp80 noundef nofpclass(nan inf) [[B_REAL]], x86_fp80 noundef nofpclass(nan inf) [[B_IMAG]]) #[[ATTR2]]
|
||||
// FULL_FAST-NEXT: [[CALL:%.*]] = call reassoc nnan ninf nsz arcp afn nofpclass(nan inf) { x86_fp80, x86_fp80 } @__divxc3(x86_fp80 noundef nofpclass(nan inf) [[A_REAL]], x86_fp80 noundef nofpclass(nan inf) [[A_IMAG]], x86_fp80 noundef nofpclass(nan inf) [[B_REAL]], x86_fp80 noundef nofpclass(nan inf) [[B_IMAG]]) #[[ATTR2]]
|
||||
// FULL_FAST-NEXT: [[TMP0:%.*]] = extractvalue { x86_fp80, x86_fp80 } [[CALL]], 0
|
||||
// FULL_FAST-NEXT: [[TMP1:%.*]] = extractvalue { x86_fp80, x86_fp80 } [[CALL]], 1
|
||||
// FULL_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { x86_fp80, x86_fp80 }, ptr [[RETVAL]], i32 0, i32 0
|
||||
@ -2545,7 +2545,7 @@ _Complex double muld(_Complex double a, _Complex double b) {
|
||||
// FULL_FAST-NEXT: [[TMP2:%.*]] = load { x86_fp80, x86_fp80 }, ptr [[RETVAL]], align 16
|
||||
// FULL_FAST-NEXT: ret { x86_fp80, x86_fp80 } [[TMP2]]
|
||||
//
|
||||
// IMPRVD_FAST-LABEL: define dso_local { x86_fp80, x86_fp80 } @divld(
|
||||
// IMPRVD_FAST-LABEL: define dso_local nofpclass(nan inf) { x86_fp80, x86_fp80 } @divld(
|
||||
// IMPRVD_FAST-SAME: ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[A:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]]) #[[ATTR2]] {
|
||||
// IMPRVD_FAST-NEXT: entry:
|
||||
// IMPRVD_FAST-NEXT: [[RETVAL:%.*]] = alloca { x86_fp80, x86_fp80 }, align 16
|
||||
@ -2593,7 +2593,7 @@ _Complex double muld(_Complex double a, _Complex double b) {
|
||||
// IMPRVD_FAST-NEXT: [[TMP22:%.*]] = load { x86_fp80, x86_fp80 }, ptr [[RETVAL]], align 16
|
||||
// IMPRVD_FAST-NEXT: ret { x86_fp80, x86_fp80 } [[TMP22]]
|
||||
//
|
||||
// PRMTD_FAST-LABEL: define dso_local { x86_fp80, x86_fp80 } @divld(
|
||||
// PRMTD_FAST-LABEL: define dso_local nofpclass(nan inf) { x86_fp80, x86_fp80 } @divld(
|
||||
// PRMTD_FAST-SAME: ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[A:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]]) #[[ATTR1]] {
|
||||
// PRMTD_FAST-NEXT: entry:
|
||||
// PRMTD_FAST-NEXT: [[RETVAL:%.*]] = alloca { x86_fp80, x86_fp80 }, align 16
|
||||
@ -2979,7 +2979,7 @@ _Complex long double divld(_Complex long double a, _Complex long double b) {
|
||||
// AVRFP64-NEXT: store double [[AGG_RESULT_IMAG]], ptr [[AGG_RESULT_IMAGP4]], align 1
|
||||
// AVRFP64-NEXT: ret void
|
||||
//
|
||||
// BASIC_FAST-LABEL: define dso_local { x86_fp80, x86_fp80 } @mulld(
|
||||
// BASIC_FAST-LABEL: define dso_local nofpclass(nan inf) { x86_fp80, x86_fp80 } @mulld(
|
||||
// BASIC_FAST-SAME: ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[A:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]]) #[[ATTR1]] {
|
||||
// BASIC_FAST-NEXT: entry:
|
||||
// BASIC_FAST-NEXT: [[RETVAL:%.*]] = alloca { x86_fp80, x86_fp80 }, align 16
|
||||
@ -3004,7 +3004,7 @@ _Complex long double divld(_Complex long double a, _Complex long double b) {
|
||||
// BASIC_FAST-NEXT: [[TMP0:%.*]] = load { x86_fp80, x86_fp80 }, ptr [[RETVAL]], align 16
|
||||
// BASIC_FAST-NEXT: ret { x86_fp80, x86_fp80 } [[TMP0]]
|
||||
//
|
||||
// FULL_FAST-LABEL: define dso_local { x86_fp80, x86_fp80 } @mulld(
|
||||
// FULL_FAST-LABEL: define dso_local nofpclass(nan inf) { x86_fp80, x86_fp80 } @mulld(
|
||||
// FULL_FAST-SAME: ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[A:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]]) #[[ATTR1]] {
|
||||
// FULL_FAST-NEXT: entry:
|
||||
// FULL_FAST-NEXT: [[RETVAL:%.*]] = alloca { x86_fp80, x86_fp80 }, align 16
|
||||
@ -3028,7 +3028,7 @@ _Complex long double divld(_Complex long double a, _Complex long double b) {
|
||||
// FULL_FAST-NEXT: [[ISNAN_CMP1:%.*]] = fcmp reassoc nnan ninf nsz arcp afn uno x86_fp80 [[MUL_I]], [[MUL_I]]
|
||||
// FULL_FAST-NEXT: br i1 [[ISNAN_CMP1]], label [[COMPLEX_MUL_LIBCALL:%.*]], label [[COMPLEX_MUL_CONT]], !prof [[PROF2]]
|
||||
// FULL_FAST: complex_mul_libcall:
|
||||
// FULL_FAST-NEXT: [[CALL:%.*]] = call { x86_fp80, x86_fp80 } @__mulxc3(x86_fp80 noundef nofpclass(nan inf) [[A_REAL]], x86_fp80 noundef nofpclass(nan inf) [[A_IMAG]], x86_fp80 noundef nofpclass(nan inf) [[B_REAL]], x86_fp80 noundef nofpclass(nan inf) [[B_IMAG]]) #[[ATTR2]]
|
||||
// FULL_FAST-NEXT: [[CALL:%.*]] = call reassoc nnan ninf nsz arcp afn nofpclass(nan inf) { x86_fp80, x86_fp80 } @__mulxc3(x86_fp80 noundef nofpclass(nan inf) [[A_REAL]], x86_fp80 noundef nofpclass(nan inf) [[A_IMAG]], x86_fp80 noundef nofpclass(nan inf) [[B_REAL]], x86_fp80 noundef nofpclass(nan inf) [[B_IMAG]]) #[[ATTR2]]
|
||||
// FULL_FAST-NEXT: [[TMP0:%.*]] = extractvalue { x86_fp80, x86_fp80 } [[CALL]], 0
|
||||
// FULL_FAST-NEXT: [[TMP1:%.*]] = extractvalue { x86_fp80, x86_fp80 } [[CALL]], 1
|
||||
// FULL_FAST-NEXT: br label [[COMPLEX_MUL_CONT]]
|
||||
@ -3042,7 +3042,7 @@ _Complex long double divld(_Complex long double a, _Complex long double b) {
|
||||
// FULL_FAST-NEXT: [[TMP2:%.*]] = load { x86_fp80, x86_fp80 }, ptr [[RETVAL]], align 16
|
||||
// FULL_FAST-NEXT: ret { x86_fp80, x86_fp80 } [[TMP2]]
|
||||
//
|
||||
// IMPRVD_FAST-LABEL: define dso_local { x86_fp80, x86_fp80 } @mulld(
|
||||
// IMPRVD_FAST-LABEL: define dso_local nofpclass(nan inf) { x86_fp80, x86_fp80 } @mulld(
|
||||
// IMPRVD_FAST-SAME: ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[A:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]]) #[[ATTR2]] {
|
||||
// IMPRVD_FAST-NEXT: entry:
|
||||
// IMPRVD_FAST-NEXT: [[RETVAL:%.*]] = alloca { x86_fp80, x86_fp80 }, align 16
|
||||
@ -3067,7 +3067,7 @@ _Complex long double divld(_Complex long double a, _Complex long double b) {
|
||||
// IMPRVD_FAST-NEXT: [[TMP0:%.*]] = load { x86_fp80, x86_fp80 }, ptr [[RETVAL]], align 16
|
||||
// IMPRVD_FAST-NEXT: ret { x86_fp80, x86_fp80 } [[TMP0]]
|
||||
//
|
||||
// PRMTD_FAST-LABEL: define dso_local { x86_fp80, x86_fp80 } @mulld(
|
||||
// PRMTD_FAST-LABEL: define dso_local nofpclass(nan inf) { x86_fp80, x86_fp80 } @mulld(
|
||||
// PRMTD_FAST-SAME: ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[A:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]]) #[[ATTR1]] {
|
||||
// PRMTD_FAST-NEXT: entry:
|
||||
// PRMTD_FAST-NEXT: [[RETVAL:%.*]] = alloca { x86_fp80, x86_fp80 }, align 16
|
||||
@ -3753,7 +3753,7 @@ _Complex long double mulld(_Complex long double a, _Complex long double b) {
|
||||
// FULL_FAST-NEXT: [[C_IMAG:%.*]] = load float, ptr [[C_IMAGP]], align 4
|
||||
// FULL_FAST-NEXT: [[CONV:%.*]] = fpext float [[C_REAL]] to x86_fp80
|
||||
// FULL_FAST-NEXT: [[CONV1:%.*]] = fpext float [[C_IMAG]] to x86_fp80
|
||||
// FULL_FAST-NEXT: [[CALL:%.*]] = call { x86_fp80, x86_fp80 } @__divxc3(x86_fp80 noundef nofpclass(nan inf) [[B_REAL]], x86_fp80 noundef nofpclass(nan inf) [[B_IMAG]], x86_fp80 noundef nofpclass(nan inf) [[CONV]], x86_fp80 noundef nofpclass(nan inf) [[CONV1]]) #[[ATTR2]]
|
||||
// FULL_FAST-NEXT: [[CALL:%.*]] = call reassoc nnan ninf nsz arcp afn nofpclass(nan inf) { x86_fp80, x86_fp80 } @__divxc3(x86_fp80 noundef nofpclass(nan inf) [[B_REAL]], x86_fp80 noundef nofpclass(nan inf) [[B_IMAG]], x86_fp80 noundef nofpclass(nan inf) [[CONV]], x86_fp80 noundef nofpclass(nan inf) [[CONV1]]) #[[ATTR2]]
|
||||
// FULL_FAST-NEXT: [[TMP0:%.*]] = extractvalue { x86_fp80, x86_fp80 } [[CALL]], 0
|
||||
// FULL_FAST-NEXT: [[TMP1:%.*]] = extractvalue { x86_fp80, x86_fp80 } [[CALL]], 1
|
||||
// FULL_FAST-NEXT: [[CONV2:%.*]] = fptrunc x86_fp80 [[TMP0]] to float
|
||||
|
||||
@ -519,7 +519,7 @@ _Complex float defined_complex_func(_Complex float a, _Complex double b, _Comple
|
||||
}
|
||||
|
||||
// CFINITEONLY: Function Attrs: noinline nounwind optnone
|
||||
// CFINITEONLY-LABEL: define dso_local { double, double } @defined_complex_func_f64_ret
|
||||
// CFINITEONLY-LABEL: define dso_local nofpclass(nan inf) { double, double } @defined_complex_func_f64_ret
|
||||
// CFINITEONLY-SAME: (double noundef nofpclass(nan inf) [[C_COERCE0:%.*]], double noundef nofpclass(nan inf) [[C_COERCE1:%.*]]) #[[ATTR0]] {
|
||||
// CFINITEONLY-NEXT: entry:
|
||||
// CFINITEONLY-NEXT: [[RETVAL:%.*]] = alloca { double, double }, align 8
|
||||
@ -548,7 +548,7 @@ _Complex float defined_complex_func(_Complex float a, _Complex double b, _Comple
|
||||
// CFINITEONLY-NEXT: [[ISNAN_CMP5:%.*]] = fcmp nnan ninf uno double [[MUL_I]], [[MUL_I]]
|
||||
// CFINITEONLY-NEXT: br i1 [[ISNAN_CMP5]], label [[COMPLEX_MUL_LIBCALL:%.*]], label [[COMPLEX_MUL_CONT]], !prof [[PROF2]]
|
||||
// CFINITEONLY: complex_mul_libcall:
|
||||
// CFINITEONLY-NEXT: [[CALL:%.*]] = call { double, double } @__muldc3(double noundef nofpclass(nan inf) [[C_REAL]], double noundef nofpclass(nan inf) [[C_IMAG]], double noundef nofpclass(nan inf) [[C_REAL2]], double noundef nofpclass(nan inf) [[C_IMAG4]]) #[[ATTR7:[0-9]+]]
|
||||
// CFINITEONLY-NEXT: [[CALL:%.*]] = call nnan ninf nofpclass(nan inf) { double, double } @__muldc3(double noundef nofpclass(nan inf) [[C_REAL]], double noundef nofpclass(nan inf) [[C_IMAG]], double noundef nofpclass(nan inf) [[C_REAL2]], double noundef nofpclass(nan inf) [[C_IMAG4]]) #[[ATTR7:[0-9]+]]
|
||||
// CFINITEONLY-NEXT: [[TMP2:%.*]] = extractvalue { double, double } [[CALL]], 0
|
||||
// CFINITEONLY-NEXT: [[TMP3:%.*]] = extractvalue { double, double } [[CALL]], 1
|
||||
// CFINITEONLY-NEXT: br label [[COMPLEX_MUL_CONT]]
|
||||
@ -563,7 +563,7 @@ _Complex float defined_complex_func(_Complex float a, _Complex double b, _Comple
|
||||
// CFINITEONLY-NEXT: ret { double, double } [[TMP4]]
|
||||
//
|
||||
// CLFINITEONLY: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
||||
// CLFINITEONLY-LABEL: define dso_local { double, double } @defined_complex_func_f64_ret
|
||||
// CLFINITEONLY-LABEL: define dso_local nofpclass(nan inf) { double, double } @defined_complex_func_f64_ret
|
||||
// CLFINITEONLY-SAME: (double noundef nofpclass(nan inf) [[C_COERCE0:%.*]], double noundef nofpclass(nan inf) [[C_COERCE1:%.*]]) local_unnamed_addr #[[ATTR0]] {
|
||||
// CLFINITEONLY-NEXT: entry:
|
||||
// CLFINITEONLY-NEXT: [[MUL_AD:%.*]] = fmul nnan ninf double [[C_COERCE0]], [[C_COERCE1]]
|
||||
@ -576,7 +576,7 @@ _Complex float defined_complex_func(_Complex float a, _Complex double b, _Comple
|
||||
// CLFINITEONLY-NEXT: ret { double, double } [[DOTFCA_1_INSERT]]
|
||||
//
|
||||
// NONANS: Function Attrs: noinline nounwind optnone
|
||||
// NONANS-LABEL: define dso_local { double, double } @defined_complex_func_f64_ret
|
||||
// NONANS-LABEL: define dso_local nofpclass(nan) { double, double } @defined_complex_func_f64_ret
|
||||
// NONANS-SAME: (double noundef nofpclass(nan) [[C_COERCE0:%.*]], double noundef nofpclass(nan) [[C_COERCE1:%.*]]) #[[ATTR0]] {
|
||||
// NONANS-NEXT: entry:
|
||||
// NONANS-NEXT: [[RETVAL:%.*]] = alloca { double, double }, align 8
|
||||
@ -605,7 +605,7 @@ _Complex float defined_complex_func(_Complex float a, _Complex double b, _Comple
|
||||
// NONANS-NEXT: [[ISNAN_CMP5:%.*]] = fcmp nnan uno double [[MUL_I]], [[MUL_I]]
|
||||
// NONANS-NEXT: br i1 [[ISNAN_CMP5]], label [[COMPLEX_MUL_LIBCALL:%.*]], label [[COMPLEX_MUL_CONT]], !prof [[PROF2]]
|
||||
// NONANS: complex_mul_libcall:
|
||||
// NONANS-NEXT: [[CALL:%.*]] = call { double, double } @__muldc3(double noundef nofpclass(nan) [[C_REAL]], double noundef nofpclass(nan) [[C_IMAG]], double noundef nofpclass(nan) [[C_REAL2]], double noundef nofpclass(nan) [[C_IMAG4]]) #[[ATTR7:[0-9]+]]
|
||||
// NONANS-NEXT: [[CALL:%.*]] = call nnan nofpclass(nan) { double, double } @__muldc3(double noundef nofpclass(nan) [[C_REAL]], double noundef nofpclass(nan) [[C_IMAG]], double noundef nofpclass(nan) [[C_REAL2]], double noundef nofpclass(nan) [[C_IMAG4]]) #[[ATTR7:[0-9]+]]
|
||||
// NONANS-NEXT: [[TMP2:%.*]] = extractvalue { double, double } [[CALL]], 0
|
||||
// NONANS-NEXT: [[TMP3:%.*]] = extractvalue { double, double } [[CALL]], 1
|
||||
// NONANS-NEXT: br label [[COMPLEX_MUL_CONT]]
|
||||
@ -620,7 +620,7 @@ _Complex float defined_complex_func(_Complex float a, _Complex double b, _Comple
|
||||
// NONANS-NEXT: ret { double, double } [[TMP4]]
|
||||
//
|
||||
// NOINFS: Function Attrs: noinline nounwind optnone
|
||||
// NOINFS-LABEL: define dso_local { double, double } @defined_complex_func_f64_ret
|
||||
// NOINFS-LABEL: define dso_local nofpclass(inf) { double, double } @defined_complex_func_f64_ret
|
||||
// NOINFS-SAME: (double noundef nofpclass(inf) [[C_COERCE0:%.*]], double noundef nofpclass(inf) [[C_COERCE1:%.*]]) #[[ATTR0]] {
|
||||
// NOINFS-NEXT: entry:
|
||||
// NOINFS-NEXT: [[RETVAL:%.*]] = alloca { double, double }, align 8
|
||||
@ -649,7 +649,7 @@ _Complex float defined_complex_func(_Complex float a, _Complex double b, _Comple
|
||||
// NOINFS-NEXT: [[ISNAN_CMP5:%.*]] = fcmp ninf uno double [[MUL_I]], [[MUL_I]]
|
||||
// NOINFS-NEXT: br i1 [[ISNAN_CMP5]], label [[COMPLEX_MUL_LIBCALL:%.*]], label [[COMPLEX_MUL_CONT]], !prof [[PROF2]]
|
||||
// NOINFS: complex_mul_libcall:
|
||||
// NOINFS-NEXT: [[CALL:%.*]] = call { double, double } @__muldc3(double noundef nofpclass(inf) [[C_REAL]], double noundef nofpclass(inf) [[C_IMAG]], double noundef nofpclass(inf) [[C_REAL2]], double noundef nofpclass(inf) [[C_IMAG4]]) #[[ATTR7:[0-9]+]]
|
||||
// NOINFS-NEXT: [[CALL:%.*]] = call ninf nofpclass(inf) { double, double } @__muldc3(double noundef nofpclass(inf) [[C_REAL]], double noundef nofpclass(inf) [[C_IMAG]], double noundef nofpclass(inf) [[C_REAL2]], double noundef nofpclass(inf) [[C_IMAG4]]) #[[ATTR7:[0-9]+]]
|
||||
// NOINFS-NEXT: [[TMP2:%.*]] = extractvalue { double, double } [[CALL]], 0
|
||||
// NOINFS-NEXT: [[TMP3:%.*]] = extractvalue { double, double } [[CALL]], 1
|
||||
// NOINFS-NEXT: br label [[COMPLEX_MUL_CONT]]
|
||||
|
||||
@ -1499,11 +1499,12 @@ Currently, only the following parameter attributes are defined:
|
||||
``nofpclass(<test mask>)``
|
||||
This attribute applies to parameters and return values with
|
||||
floating-point and vector of floating-point types, as well as
|
||||
arrays of such types. The test mask has the same format as the
|
||||
second argument to the :ref:`llvm.is.fpclass <llvm.is.fpclass>`,
|
||||
and indicates which classes of floating-point values are not
|
||||
permitted for the value. For example a bitmask of 3 indicates
|
||||
the parameter may not be a NaN.
|
||||
:ref:`supported aggregates <fastmath_return_types>` of such types
|
||||
(matching the supported types for :ref:`fast-math flags <fastmath>`).
|
||||
The test mask has the same format as the second argument to the
|
||||
:ref:`llvm.is.fpclass <llvm.is.fpclass>`, and indicates which classes
|
||||
of floating-point values are not permitted for the value. For example
|
||||
a bitmask of 3 indicates the parameter may not be a NaN.
|
||||
|
||||
If the value is a floating-point class indicated by the
|
||||
``nofpclass`` test mask, a :ref:`poison value <poisonvalues>` is
|
||||
@ -3685,9 +3686,9 @@ Fast-Math Flags
|
||||
|
||||
LLVM IR floating-point operations (:ref:`fneg <i_fneg>`, :ref:`fadd <i_fadd>`,
|
||||
:ref:`fsub <i_fsub>`, :ref:`fmul <i_fmul>`, :ref:`fdiv <i_fdiv>`,
|
||||
:ref:`frem <i_frem>`, :ref:`fcmp <i_fcmp>`), :ref:`phi <i_phi>`,
|
||||
:ref:`select <i_select>` and :ref:`call <i_call>`
|
||||
may use the following flags to enable otherwise unsafe
|
||||
:ref:`frem <i_frem>`, :ref:`fcmp <i_fcmp>`), and :ref:`phi <i_phi>`,
|
||||
:ref:`select <i_select>`, or :ref:`call <i_call>` instructions that return
|
||||
floating-point types may use the following flags to enable otherwise unsafe
|
||||
floating-point transformations.
|
||||
|
||||
``fast``
|
||||
@ -3709,6 +3710,16 @@ floating-point transformations.
|
||||
argument or zero result as insignificant. This does not imply that -0.0
|
||||
is poison and/or guaranteed to not exist in the operation.
|
||||
|
||||
Note: For :ref:`phi <i_phi>`, :ref:`select <i_select>`, and :ref:`call <i_call>`
|
||||
instructions, the following return types are considered to be floating-point
|
||||
types:
|
||||
|
||||
.. _fastmath_return_types:
|
||||
|
||||
- Floating-point scalar or vector types
|
||||
- Array types (nested to any depth) of floating-point scalar or vector types
|
||||
- Homogeneous literal struct types of floating-point scalar or vector types
|
||||
|
||||
Rewrite-based flags
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
@ -4343,7 +4354,7 @@ recursive, can be opaqued, and are never uniqued.
|
||||
:Examples:
|
||||
|
||||
+------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| ``{ i32, i32, i32 }`` | A triple of three ``i32`` values |
|
||||
| ``{ i32, i32, i32 }`` | A triple of three ``i32`` values (this is a "homogeneous" struct as all element types are the same) |
|
||||
+------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| ``{ float, ptr }`` | A pair, where the first element is a ``float`` and the second element is a :ref:`pointer <t_pointer>`. |
|
||||
+------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
@ -12472,9 +12483,8 @@ instruction's return value on the same edge).
|
||||
The optional ``fast-math-flags`` marker indicates that the phi has one
|
||||
or more :ref:`fast-math-flags <fastmath>`. These are optimization hints
|
||||
to enable otherwise unsafe floating-point optimizations. Fast-math-flags
|
||||
are only valid for phis that return a floating-point scalar or vector
|
||||
type, or an array (nested to any depth) of floating-point scalar or vector
|
||||
types.
|
||||
are only valid for phis that return :ref:`supported floating-point types
|
||||
<fastmath_return_types>`.
|
||||
|
||||
Semantics:
|
||||
""""""""""
|
||||
@ -12523,8 +12533,8 @@ class <t_firstclass>` type.
|
||||
#. The optional ``fast-math flags`` marker indicates that the select has one or more
|
||||
:ref:`fast-math flags <fastmath>`. These are optimization hints to enable
|
||||
otherwise unsafe floating-point optimizations. Fast-math flags are only valid
|
||||
for selects that return a floating-point scalar or vector type, or an array
|
||||
(nested to any depth) of floating-point scalar or vector types.
|
||||
for selects that return :ref:`supported floating-point types
|
||||
<fastmath_return_types>`..
|
||||
|
||||
Semantics:
|
||||
""""""""""
|
||||
@ -12762,8 +12772,7 @@ This instruction requires several arguments:
|
||||
#. The optional ``fast-math flags`` marker indicates that the call has one or more
|
||||
:ref:`fast-math flags <fastmath>`, which are optimization hints to enable
|
||||
otherwise unsafe floating-point optimizations. Fast-math flags are only valid
|
||||
for calls that return a floating-point scalar or vector type, or an array
|
||||
(nested to any depth) of floating-point scalar or vector types.
|
||||
for calls that return :ref:`supported floating-point types <fastmath_return_types>`.
|
||||
|
||||
#. The optional "cconv" marker indicates which :ref:`calling
|
||||
convention <callingconv>` the call should use. If none is
|
||||
@ -20527,8 +20536,8 @@ the explicit vector length.
|
||||
#. The optional ``fast-math flags`` marker indicates that the select has one or
|
||||
more :ref:`fast-math flags <fastmath>`. These are optimization hints to
|
||||
enable otherwise unsafe floating-point optimizations. Fast-math flags are
|
||||
only valid for selects that return a floating-point scalar or vector type,
|
||||
or an array (nested to any depth) of floating-point scalar or vector types.
|
||||
only valid for selects that return :ref:`supported floating-point types
|
||||
<fastmath_return_types>`.
|
||||
|
||||
Semantics:
|
||||
""""""""""
|
||||
@ -20585,8 +20594,8 @@ is the pivot.
|
||||
#. The optional ``fast-math flags`` marker indicates that the merge has one or
|
||||
more :ref:`fast-math flags <fastmath>`. These are optimization hints to
|
||||
enable otherwise unsafe floating-point optimizations. Fast-math flags are
|
||||
only valid for merges that return a floating-point scalar or vector type,
|
||||
or an array (nested to any depth) of floating-point scalar or vector types.
|
||||
only valid for merges that return :ref:`supported floating-point types
|
||||
<fastmath_return_types>`.
|
||||
|
||||
Semantics:
|
||||
""""""""""
|
||||
|
||||
@ -301,6 +301,10 @@ public:
|
||||
/// {<vscale x 2 x i32>, <vscale x 4 x i64>}}
|
||||
bool containsHomogeneousScalableVectorTypes() const;
|
||||
|
||||
/// Return true if this struct is non-empty and all element types are the
|
||||
/// same.
|
||||
bool containsHomogeneousTypes() const;
|
||||
|
||||
/// Return true if this is a named struct that has a non-empty name.
|
||||
bool hasName() const { return SymbolTableEntry != nullptr; }
|
||||
|
||||
|
||||
@ -268,6 +268,21 @@ private:
|
||||
SubclassOptionalData = FMF.Flags;
|
||||
}
|
||||
|
||||
/// Returns true if `Ty` is composed of a single kind of float-poing type
|
||||
/// (possibly repeated within an aggregate).
|
||||
static bool isComposedOfHomogeneousFloatingPointTypes(Type *Ty) {
|
||||
if (auto *StructTy = dyn_cast<StructType>(Ty)) {
|
||||
if (!StructTy->isLiteral() || !StructTy->containsHomogeneousTypes())
|
||||
return false;
|
||||
Ty = StructTy->elements().front();
|
||||
} else if (auto *ArrayTy = dyn_cast<ArrayType>(Ty)) {
|
||||
do {
|
||||
Ty = ArrayTy->getElementType();
|
||||
} while ((ArrayTy = dyn_cast<ArrayType>(Ty)));
|
||||
}
|
||||
return Ty->isFPOrFPVectorTy();
|
||||
};
|
||||
|
||||
public:
|
||||
/// Test if this operation allows all non-strict floating-point transforms.
|
||||
bool isFast() const {
|
||||
@ -326,6 +341,13 @@ public:
|
||||
/// precision.
|
||||
float getFPAccuracy() const;
|
||||
|
||||
/// Returns true if `Ty` is a supported floating-point type for phi, select,
|
||||
/// or call FPMathOperators.
|
||||
static bool isSupportedFloatingPointType(Type *Ty) {
|
||||
return Ty->isFPOrFPVectorTy() ||
|
||||
isComposedOfHomogeneousFloatingPointTypes(Ty);
|
||||
}
|
||||
|
||||
static bool classof(const Value *V) {
|
||||
unsigned Opcode;
|
||||
if (auto *I = dyn_cast<Instruction>(V))
|
||||
@ -350,10 +372,7 @@ public:
|
||||
case Instruction::PHI:
|
||||
case Instruction::Select:
|
||||
case Instruction::Call: {
|
||||
Type *Ty = V->getType();
|
||||
while (ArrayType *ArrTy = dyn_cast<ArrayType>(Ty))
|
||||
Ty = ArrTy->getElementType();
|
||||
return Ty->isFPOrFPVectorTy();
|
||||
return isSupportedFloatingPointType(V->getType());
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
|
||||
@ -28,6 +28,7 @@
|
||||
#include "llvm/IR/ConstantRangeList.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/IR/Operator.h"
|
||||
#include "llvm/IR/Type.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
@ -2296,12 +2297,8 @@ bool AttrBuilder::operator==(const AttrBuilder &B) const {
|
||||
|
||||
/// Returns true if this is a type legal for the 'nofpclass' attribute. This
|
||||
/// follows the same type rules as FPMathOperator.
|
||||
///
|
||||
/// TODO: Consider relaxing to any FP type struct fields.
|
||||
bool AttributeFuncs::isNoFPClassCompatibleType(Type *Ty) {
|
||||
while (ArrayType *ArrTy = dyn_cast<ArrayType>(Ty))
|
||||
Ty = ArrTy->getElementType();
|
||||
return Ty->isFPOrFPVectorTy();
|
||||
return FPMathOperator::isSupportedFloatingPointType(Ty);
|
||||
}
|
||||
|
||||
/// Which attributes cannot be applied to a type.
|
||||
|
||||
@ -430,13 +430,14 @@ bool StructType::containsScalableVectorType(
|
||||
}
|
||||
|
||||
bool StructType::containsHomogeneousScalableVectorTypes() const {
|
||||
Type *FirstTy = getNumElements() > 0 ? elements()[0] : nullptr;
|
||||
if (!FirstTy || !isa<ScalableVectorType>(FirstTy))
|
||||
if (getNumElements() <= 0 || !isa<ScalableVectorType>(elements().front()))
|
||||
return false;
|
||||
for (Type *Ty : elements())
|
||||
if (Ty != FirstTy)
|
||||
return false;
|
||||
return true;
|
||||
return containsHomogeneousTypes();
|
||||
}
|
||||
|
||||
bool StructType::containsHomogeneousTypes() const {
|
||||
ArrayRef<Type *> ElementTys = elements();
|
||||
return !ElementTys.empty() && all_equal(ElementTys);
|
||||
}
|
||||
|
||||
void StructType::setBody(ArrayRef<Type*> Elements, bool isPacked) {
|
||||
|
||||
@ -1122,6 +1122,26 @@ define void @fastMathFlagsForArrayCalls([2 x float] %f, [2 x double] %d1, [2 x <
|
||||
ret void
|
||||
}
|
||||
|
||||
declare { float, float } @fmf_struct_f32()
|
||||
declare { double, double, double } @fmf_struct_f64()
|
||||
declare { <4 x double> } @fmf_struct_v4f64()
|
||||
|
||||
; CHECK-LABEL: fastMathFlagsForStructCalls(
|
||||
define void @fastMathFlagsForStructCalls() {
|
||||
%call.fast = call fast { float, float } @fmf_struct_f32()
|
||||
; CHECK: %call.fast = call fast { float, float } @fmf_struct_f32()
|
||||
|
||||
; Throw in some other attributes to make sure those stay in the right places.
|
||||
|
||||
%call.nsz.arcp = notail call nsz arcp { double, double, double } @fmf_struct_f64()
|
||||
; CHECK: %call.nsz.arcp = notail call nsz arcp { double, double, double } @fmf_struct_f64()
|
||||
|
||||
%call.nnan.ninf = tail call nnan ninf fastcc { <4 x double> } @fmf_struct_v4f64()
|
||||
; CHECK: %call.nnan.ninf = tail call nnan ninf fastcc { <4 x double> } @fmf_struct_v4f64()
|
||||
|
||||
ret void
|
||||
}
|
||||
|
||||
;; Type System
|
||||
%opaquety = type opaque
|
||||
define void @typesystem() {
|
||||
@ -2077,9 +2097,14 @@ declare nofpclass(sub zero) float @nofpclass_sub_zero(float nofpclass(sub zero))
|
||||
; CHECK: declare nofpclass(inf sub) float @nofpclass_sub_inf(float nofpclass(inf sub))
|
||||
declare nofpclass(sub inf) float @nofpclass_sub_inf(float nofpclass(sub inf))
|
||||
|
||||
; CHECK: declare nofpclass(nan) { float, float } @nofpclass_struct({ double } nofpclass(nan))
|
||||
declare nofpclass(nan) { float, float } @nofpclass_struct({ double } nofpclass(nan))
|
||||
|
||||
declare float @unknown_fpclass_func(float)
|
||||
|
||||
define float @nofpclass_callsites(float %arg) {
|
||||
declare { <4 x double>, <4 x double>, <4 x double> } @unknown_fpclass_struct_func({ float })
|
||||
|
||||
define float @nofpclass_callsites(float %arg, { float } %arg1) {
|
||||
; CHECK: %call0 = call nofpclass(nan) float @unknown_fpclass_func(float nofpclass(ninf) %arg)
|
||||
%call0 = call nofpclass(nan) float @unknown_fpclass_func(float nofpclass(ninf) %arg)
|
||||
|
||||
@ -2088,6 +2113,10 @@ define float @nofpclass_callsites(float %arg) {
|
||||
|
||||
; CHECK: %call2 = call nofpclass(zero) float @unknown_fpclass_func(float nofpclass(norm) %arg)
|
||||
%call2 = call nofpclass(zero) float @unknown_fpclass_func(float nofpclass(norm) %arg)
|
||||
|
||||
; CHECK: %call3 = call nofpclass(pinf) { <4 x double>, <4 x double>, <4 x double> } @unknown_fpclass_struct_func({ float } nofpclass(all) %arg1)
|
||||
%call3 = call nofpclass(pinf) { <4 x double>, <4 x double>, <4 x double> } @unknown_fpclass_struct_func({ float } nofpclass(all) %arg1)
|
||||
|
||||
%add0 = fadd float %call0, %call1
|
||||
%add1 = fadd float %add0, %call2
|
||||
ret float %add1
|
||||
|
||||
@ -1559,12 +1559,61 @@ TEST(InstructionsTest, FPCallIsFPMathOperator) {
|
||||
CallInst::Create(AVFFnTy, AVFCallee, {}, ""));
|
||||
EXPECT_TRUE(isa<FPMathOperator>(AVFCall));
|
||||
|
||||
Type *AAVFTy = ArrayType::get(AVFTy, 2);
|
||||
FunctionType *AAVFFnTy = FunctionType::get(AAVFTy, {});
|
||||
Value *AAVFCallee = Constant::getNullValue(PtrTy);
|
||||
std::unique_ptr<CallInst> AAVFCall(
|
||||
CallInst::Create(AAVFFnTy, AAVFCallee, {}, ""));
|
||||
EXPECT_TRUE(isa<FPMathOperator>(AAVFCall));
|
||||
Type *StructITy = StructType::get(ITy, ITy);
|
||||
FunctionType *StructIFnTy = FunctionType::get(StructITy, {});
|
||||
Value *StructICallee = Constant::getNullValue(PtrTy);
|
||||
std::unique_ptr<CallInst> StructICall(
|
||||
CallInst::Create(StructIFnTy, StructICallee, {}, ""));
|
||||
EXPECT_FALSE(isa<FPMathOperator>(StructICall));
|
||||
|
||||
Type *EmptyStructTy = StructType::get(C);
|
||||
FunctionType *EmptyStructFnTy = FunctionType::get(EmptyStructTy, {});
|
||||
Value *EmptyStructCallee = Constant::getNullValue(PtrTy);
|
||||
std::unique_ptr<CallInst> EmptyStructCall(
|
||||
CallInst::Create(EmptyStructFnTy, EmptyStructCallee, {}, ""));
|
||||
EXPECT_FALSE(isa<FPMathOperator>(EmptyStructCall));
|
||||
|
||||
Type *NamedStructFTy = StructType::create({FTy, FTy}, "AStruct");
|
||||
FunctionType *NamedStructFFnTy = FunctionType::get(NamedStructFTy, {});
|
||||
Value *NamedStructFCallee = Constant::getNullValue(PtrTy);
|
||||
std::unique_ptr<CallInst> NamedStructFCall(
|
||||
CallInst::Create(NamedStructFFnTy, NamedStructFCallee, {}, ""));
|
||||
EXPECT_FALSE(isa<FPMathOperator>(NamedStructFCall));
|
||||
|
||||
Type *MixedStructTy = StructType::get(FTy, ITy);
|
||||
FunctionType *MixedStructFnTy = FunctionType::get(MixedStructTy, {});
|
||||
Value *MixedStructCallee = Constant::getNullValue(PtrTy);
|
||||
std::unique_ptr<CallInst> MixedStructCall(
|
||||
CallInst::Create(MixedStructFnTy, MixedStructCallee, {}, ""));
|
||||
EXPECT_FALSE(isa<FPMathOperator>(MixedStructCall));
|
||||
|
||||
Type *StructFTy = StructType::get(FTy, FTy, FTy);
|
||||
FunctionType *StructFFnTy = FunctionType::get(StructFTy, {});
|
||||
Value *StructFCallee = Constant::getNullValue(PtrTy);
|
||||
std::unique_ptr<CallInst> StructFCall(
|
||||
CallInst::Create(StructFFnTy, StructFCallee, {}, ""));
|
||||
EXPECT_TRUE(isa<FPMathOperator>(StructFCall));
|
||||
|
||||
Type *StructVFTy = StructType::get(VFTy, VFTy, VFTy, VFTy);
|
||||
FunctionType *StructVFFnTy = FunctionType::get(StructVFTy, {});
|
||||
Value *StructVFCallee = Constant::getNullValue(PtrTy);
|
||||
std::unique_ptr<CallInst> StructVFCall(
|
||||
CallInst::Create(StructVFFnTy, StructVFCallee, {}, ""));
|
||||
EXPECT_TRUE(isa<FPMathOperator>(StructVFCall));
|
||||
|
||||
Type *NestedStructFTy = StructType::get(StructFTy, StructFTy, StructFTy);
|
||||
FunctionType *NestedStructFFnTy = FunctionType::get(NestedStructFTy, {});
|
||||
Value *NestedStructFCallee = Constant::getNullValue(PtrTy);
|
||||
std::unique_ptr<CallInst> NestedStructFCall(
|
||||
CallInst::Create(NestedStructFFnTy, NestedStructFCallee, {}, ""));
|
||||
EXPECT_FALSE(isa<FPMathOperator>(NestedStructFCall));
|
||||
|
||||
Type *AStructFTy = ArrayType::get(StructFTy, 5);
|
||||
FunctionType *AStructFFnTy = FunctionType::get(AStructFTy, {});
|
||||
Value *AStructFCallee = Constant::getNullValue(PtrTy);
|
||||
std::unique_ptr<CallInst> AStructFCall(
|
||||
CallInst::Create(AStructFFnTy, AStructFCallee, {}, ""));
|
||||
EXPECT_FALSE(isa<FPMathOperator>(AStructFCall));
|
||||
}
|
||||
|
||||
TEST(InstructionsTest, FNegInstruction) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user