Skip to content

Commit 6bc7308

Browse files
MacDueSterling-Augustine
authored andcommitted
[IR] Allow fast math flags on calls with homogeneous FP struct types (llvm#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`).
1 parent a9e168b commit 6bc7308

File tree

10 files changed

+179
-71
lines changed

10 files changed

+179
-71
lines changed

clang/test/CodeGen/X86/cx-complex-range.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1220,7 +1220,7 @@ _Complex _Float16 mulf16(_Complex _Float16 a, _Complex _Float16 b) {
12201220
// FULL_FAST-NEXT: [[C_IMAG:%.*]] = load half, ptr [[C_IMAGP]], align 2
12211221
// FULL_FAST-NEXT: [[CONV:%.*]] = fpext half [[C_REAL]] to x86_fp80
12221222
// FULL_FAST-NEXT: [[CONV1:%.*]] = fpext half [[C_IMAG]] to x86_fp80
1223-
// 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]]
1223+
// 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]]
12241224
// FULL_FAST-NEXT: [[TMP0:%.*]] = extractvalue { x86_fp80, x86_fp80 } [[CALL]], 0
12251225
// FULL_FAST-NEXT: [[TMP1:%.*]] = extractvalue { x86_fp80, x86_fp80 } [[CALL]], 1
12261226
// FULL_FAST-NEXT: [[CONV2:%.*]] = fptrunc x86_fp80 [[TMP0]] to half

clang/test/CodeGen/cx-complex-range.c

Lines changed: 21 additions & 21 deletions
Large diffs are not rendered by default.

clang/test/CodeGen/nofpclass.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -519,7 +519,7 @@ _Complex float defined_complex_func(_Complex float a, _Complex double b, _Comple
519519
}
520520

521521
// CFINITEONLY: Function Attrs: noinline nounwind optnone
522-
// CFINITEONLY-LABEL: define dso_local { double, double } @defined_complex_func_f64_ret
522+
// CFINITEONLY-LABEL: define dso_local nofpclass(nan inf) { double, double } @defined_complex_func_f64_ret
523523
// CFINITEONLY-SAME: (double noundef nofpclass(nan inf) [[C_COERCE0:%.*]], double noundef nofpclass(nan inf) [[C_COERCE1:%.*]]) #[[ATTR0]] {
524524
// CFINITEONLY-NEXT: entry:
525525
// CFINITEONLY-NEXT: [[RETVAL:%.*]] = alloca { double, double }, align 8
@@ -548,7 +548,7 @@ _Complex float defined_complex_func(_Complex float a, _Complex double b, _Comple
548548
// CFINITEONLY-NEXT: [[ISNAN_CMP5:%.*]] = fcmp nnan ninf uno double [[MUL_I]], [[MUL_I]]
549549
// CFINITEONLY-NEXT: br i1 [[ISNAN_CMP5]], label [[COMPLEX_MUL_LIBCALL:%.*]], label [[COMPLEX_MUL_CONT]], !prof [[PROF2]]
550550
// CFINITEONLY: complex_mul_libcall:
551-
// 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]+]]
551+
// 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]+]]
552552
// CFINITEONLY-NEXT: [[TMP2:%.*]] = extractvalue { double, double } [[CALL]], 0
553553
// CFINITEONLY-NEXT: [[TMP3:%.*]] = extractvalue { double, double } [[CALL]], 1
554554
// CFINITEONLY-NEXT: br label [[COMPLEX_MUL_CONT]]
@@ -563,7 +563,7 @@ _Complex float defined_complex_func(_Complex float a, _Complex double b, _Comple
563563
// CFINITEONLY-NEXT: ret { double, double } [[TMP4]]
564564
//
565565
// CLFINITEONLY: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
566-
// CLFINITEONLY-LABEL: define dso_local { double, double } @defined_complex_func_f64_ret
566+
// CLFINITEONLY-LABEL: define dso_local nofpclass(nan inf) { double, double } @defined_complex_func_f64_ret
567567
// CLFINITEONLY-SAME: (double noundef nofpclass(nan inf) [[C_COERCE0:%.*]], double noundef nofpclass(nan inf) [[C_COERCE1:%.*]]) local_unnamed_addr #[[ATTR0]] {
568568
// CLFINITEONLY-NEXT: entry:
569569
// 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
576576
// CLFINITEONLY-NEXT: ret { double, double } [[DOTFCA_1_INSERT]]
577577
//
578578
// NONANS: Function Attrs: noinline nounwind optnone
579-
// NONANS-LABEL: define dso_local { double, double } @defined_complex_func_f64_ret
579+
// NONANS-LABEL: define dso_local nofpclass(nan) { double, double } @defined_complex_func_f64_ret
580580
// NONANS-SAME: (double noundef nofpclass(nan) [[C_COERCE0:%.*]], double noundef nofpclass(nan) [[C_COERCE1:%.*]]) #[[ATTR0]] {
581581
// NONANS-NEXT: entry:
582582
// NONANS-NEXT: [[RETVAL:%.*]] = alloca { double, double }, align 8
@@ -605,7 +605,7 @@ _Complex float defined_complex_func(_Complex float a, _Complex double b, _Comple
605605
// NONANS-NEXT: [[ISNAN_CMP5:%.*]] = fcmp nnan uno double [[MUL_I]], [[MUL_I]]
606606
// NONANS-NEXT: br i1 [[ISNAN_CMP5]], label [[COMPLEX_MUL_LIBCALL:%.*]], label [[COMPLEX_MUL_CONT]], !prof [[PROF2]]
607607
// NONANS: complex_mul_libcall:
608-
// 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]+]]
608+
// 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]+]]
609609
// NONANS-NEXT: [[TMP2:%.*]] = extractvalue { double, double } [[CALL]], 0
610610
// NONANS-NEXT: [[TMP3:%.*]] = extractvalue { double, double } [[CALL]], 1
611611
// NONANS-NEXT: br label [[COMPLEX_MUL_CONT]]
@@ -620,7 +620,7 @@ _Complex float defined_complex_func(_Complex float a, _Complex double b, _Comple
620620
// NONANS-NEXT: ret { double, double } [[TMP4]]
621621
//
622622
// NOINFS: Function Attrs: noinline nounwind optnone
623-
// NOINFS-LABEL: define dso_local { double, double } @defined_complex_func_f64_ret
623+
// NOINFS-LABEL: define dso_local nofpclass(inf) { double, double } @defined_complex_func_f64_ret
624624
// NOINFS-SAME: (double noundef nofpclass(inf) [[C_COERCE0:%.*]], double noundef nofpclass(inf) [[C_COERCE1:%.*]]) #[[ATTR0]] {
625625
// NOINFS-NEXT: entry:
626626
// NOINFS-NEXT: [[RETVAL:%.*]] = alloca { double, double }, align 8
@@ -649,7 +649,7 @@ _Complex float defined_complex_func(_Complex float a, _Complex double b, _Comple
649649
// NOINFS-NEXT: [[ISNAN_CMP5:%.*]] = fcmp ninf uno double [[MUL_I]], [[MUL_I]]
650650
// NOINFS-NEXT: br i1 [[ISNAN_CMP5]], label [[COMPLEX_MUL_LIBCALL:%.*]], label [[COMPLEX_MUL_CONT]], !prof [[PROF2]]
651651
// NOINFS: complex_mul_libcall:
652-
// 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]+]]
652+
// 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]+]]
653653
// NOINFS-NEXT: [[TMP2:%.*]] = extractvalue { double, double } [[CALL]], 0
654654
// NOINFS-NEXT: [[TMP3:%.*]] = extractvalue { double, double } [[CALL]], 1
655655
// NOINFS-NEXT: br label [[COMPLEX_MUL_CONT]]

llvm/docs/LangRef.rst

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1499,11 +1499,12 @@ Currently, only the following parameter attributes are defined:
14991499
``nofpclass(<test mask>)``
15001500
This attribute applies to parameters and return values with
15011501
floating-point and vector of floating-point types, as well as
1502-
arrays of such types. The test mask has the same format as the
1503-
second argument to the :ref:`llvm.is.fpclass <llvm.is.fpclass>`,
1504-
and indicates which classes of floating-point values are not
1505-
permitted for the value. For example a bitmask of 3 indicates
1506-
the parameter may not be a NaN.
1502+
:ref:`supported aggregates <fastmath_return_types>` of such types
1503+
(matching the supported types for :ref:`fast-math flags <fastmath>`).
1504+
The test mask has the same format as the second argument to the
1505+
:ref:`llvm.is.fpclass <llvm.is.fpclass>`, and indicates which classes
1506+
of floating-point values are not permitted for the value. For example
1507+
a bitmask of 3 indicates the parameter may not be a NaN.
15071508

15081509
If the value is a floating-point class indicated by the
15091510
``nofpclass`` test mask, a :ref:`poison value <poisonvalues>` is
@@ -3685,9 +3686,9 @@ Fast-Math Flags
36853686

36863687
LLVM IR floating-point operations (:ref:`fneg <i_fneg>`, :ref:`fadd <i_fadd>`,
36873688
:ref:`fsub <i_fsub>`, :ref:`fmul <i_fmul>`, :ref:`fdiv <i_fdiv>`,
3688-
:ref:`frem <i_frem>`, :ref:`fcmp <i_fcmp>`), :ref:`phi <i_phi>`,
3689-
:ref:`select <i_select>` and :ref:`call <i_call>`
3690-
may use the following flags to enable otherwise unsafe
3689+
:ref:`frem <i_frem>`, :ref:`fcmp <i_fcmp>`), and :ref:`phi <i_phi>`,
3690+
:ref:`select <i_select>`, or :ref:`call <i_call>` instructions that return
3691+
floating-point types may use the following flags to enable otherwise unsafe
36913692
floating-point transformations.
36923693

36933694
``fast``
@@ -3709,6 +3710,16 @@ floating-point transformations.
37093710
argument or zero result as insignificant. This does not imply that -0.0
37103711
is poison and/or guaranteed to not exist in the operation.
37113712

3713+
Note: For :ref:`phi <i_phi>`, :ref:`select <i_select>`, and :ref:`call <i_call>`
3714+
instructions, the following return types are considered to be floating-point
3715+
types:
3716+
3717+
.. _fastmath_return_types:
3718+
3719+
- Floating-point scalar or vector types
3720+
- Array types (nested to any depth) of floating-point scalar or vector types
3721+
- Homogeneous literal struct types of floating-point scalar or vector types
3722+
37123723
Rewrite-based flags
37133724
^^^^^^^^^^^^^^^^^^^
37143725

@@ -4343,7 +4354,7 @@ recursive, can be opaqued, and are never uniqued.
43434354
:Examples:
43444355

43454356
+------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
4346-
| ``{ i32, i32, i32 }`` | A triple of three ``i32`` values |
4357+
| ``{ i32, i32, i32 }`` | A triple of three ``i32`` values (this is a "homogeneous" struct as all element types are the same) |
43474358
+------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
43484359
| ``{ float, ptr }`` | A pair, where the first element is a ``float`` and the second element is a :ref:`pointer <t_pointer>`. |
43494360
+------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
@@ -12472,9 +12483,8 @@ instruction's return value on the same edge).
1247212483
The optional ``fast-math-flags`` marker indicates that the phi has one
1247312484
or more :ref:`fast-math-flags <fastmath>`. These are optimization hints
1247412485
to enable otherwise unsafe floating-point optimizations. Fast-math-flags
12475-
are only valid for phis that return a floating-point scalar or vector
12476-
type, or an array (nested to any depth) of floating-point scalar or vector
12477-
types.
12486+
are only valid for phis that return :ref:`supported floating-point types
12487+
<fastmath_return_types>`.
1247812488

1247912489
Semantics:
1248012490
""""""""""
@@ -12523,8 +12533,8 @@ class <t_firstclass>` type.
1252312533
#. The optional ``fast-math flags`` marker indicates that the select has one or more
1252412534
:ref:`fast-math flags <fastmath>`. These are optimization hints to enable
1252512535
otherwise unsafe floating-point optimizations. Fast-math flags are only valid
12526-
for selects that return a floating-point scalar or vector type, or an array
12527-
(nested to any depth) of floating-point scalar or vector types.
12536+
for selects that return :ref:`supported floating-point types
12537+
<fastmath_return_types>`..
1252812538

1252912539
Semantics:
1253012540
""""""""""
@@ -12762,8 +12772,7 @@ This instruction requires several arguments:
1276212772
#. The optional ``fast-math flags`` marker indicates that the call has one or more
1276312773
:ref:`fast-math flags <fastmath>`, which are optimization hints to enable
1276412774
otherwise unsafe floating-point optimizations. Fast-math flags are only valid
12765-
for calls that return a floating-point scalar or vector type, or an array
12766-
(nested to any depth) of floating-point scalar or vector types.
12775+
for calls that return :ref:`supported floating-point types <fastmath_return_types>`.
1276712776

1276812777
#. The optional "cconv" marker indicates which :ref:`calling
1276912778
convention <callingconv>` the call should use. If none is
@@ -20527,8 +20536,8 @@ the explicit vector length.
2052720536
#. The optional ``fast-math flags`` marker indicates that the select has one or
2052820537
more :ref:`fast-math flags <fastmath>`. These are optimization hints to
2052920538
enable otherwise unsafe floating-point optimizations. Fast-math flags are
20530-
only valid for selects that return a floating-point scalar or vector type,
20531-
or an array (nested to any depth) of floating-point scalar or vector types.
20539+
only valid for selects that return :ref:`supported floating-point types
20540+
<fastmath_return_types>`.
2053220541

2053320542
Semantics:
2053420543
""""""""""
@@ -20585,8 +20594,8 @@ is the pivot.
2058520594
#. The optional ``fast-math flags`` marker indicates that the merge has one or
2058620595
more :ref:`fast-math flags <fastmath>`. These are optimization hints to
2058720596
enable otherwise unsafe floating-point optimizations. Fast-math flags are
20588-
only valid for merges that return a floating-point scalar or vector type,
20589-
or an array (nested to any depth) of floating-point scalar or vector types.
20597+
only valid for merges that return :ref:`supported floating-point types
20598+
<fastmath_return_types>`.
2059020599

2059120600
Semantics:
2059220601
""""""""""

llvm/include/llvm/IR/DerivedTypes.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,10 @@ class StructType : public Type {
301301
/// {<vscale x 2 x i32>, <vscale x 4 x i64>}}
302302
bool containsHomogeneousScalableVectorTypes() const;
303303

304+
/// Return true if this struct is non-empty and all element types are the
305+
/// same.
306+
bool containsHomogeneousTypes() const;
307+
304308
/// Return true if this is a named struct that has a non-empty name.
305309
bool hasName() const { return SymbolTableEntry != nullptr; }
306310

llvm/include/llvm/IR/Operator.h

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,21 @@ class FPMathOperator : public Operator {
268268
SubclassOptionalData = FMF.Flags;
269269
}
270270

271+
/// Returns true if `Ty` is composed of a single kind of float-poing type
272+
/// (possibly repeated within an aggregate).
273+
static bool isComposedOfHomogeneousFloatingPointTypes(Type *Ty) {
274+
if (auto *StructTy = dyn_cast<StructType>(Ty)) {
275+
if (!StructTy->isLiteral() || !StructTy->containsHomogeneousTypes())
276+
return false;
277+
Ty = StructTy->elements().front();
278+
} else if (auto *ArrayTy = dyn_cast<ArrayType>(Ty)) {
279+
do {
280+
Ty = ArrayTy->getElementType();
281+
} while ((ArrayTy = dyn_cast<ArrayType>(Ty)));
282+
}
283+
return Ty->isFPOrFPVectorTy();
284+
};
285+
271286
public:
272287
/// Test if this operation allows all non-strict floating-point transforms.
273288
bool isFast() const {
@@ -326,6 +341,13 @@ class FPMathOperator : public Operator {
326341
/// precision.
327342
float getFPAccuracy() const;
328343

344+
/// Returns true if `Ty` is a supported floating-point type for phi, select,
345+
/// or call FPMathOperators.
346+
static bool isSupportedFloatingPointType(Type *Ty) {
347+
return Ty->isFPOrFPVectorTy() ||
348+
isComposedOfHomogeneousFloatingPointTypes(Ty);
349+
}
350+
329351
static bool classof(const Value *V) {
330352
unsigned Opcode;
331353
if (auto *I = dyn_cast<Instruction>(V))
@@ -350,10 +372,7 @@ class FPMathOperator : public Operator {
350372
case Instruction::PHI:
351373
case Instruction::Select:
352374
case Instruction::Call: {
353-
Type *Ty = V->getType();
354-
while (ArrayType *ArrTy = dyn_cast<ArrayType>(Ty))
355-
Ty = ArrTy->getElementType();
356-
return Ty->isFPOrFPVectorTy();
375+
return isSupportedFloatingPointType(V->getType());
357376
}
358377
default:
359378
return false;

llvm/lib/IR/Attributes.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "llvm/IR/ConstantRangeList.h"
2929
#include "llvm/IR/Function.h"
3030
#include "llvm/IR/LLVMContext.h"
31+
#include "llvm/IR/Operator.h"
3132
#include "llvm/IR/Type.h"
3233
#include "llvm/Support/Compiler.h"
3334
#include "llvm/Support/ErrorHandling.h"
@@ -2296,12 +2297,8 @@ bool AttrBuilder::operator==(const AttrBuilder &B) const {
22962297

22972298
/// Returns true if this is a type legal for the 'nofpclass' attribute. This
22982299
/// follows the same type rules as FPMathOperator.
2299-
///
2300-
/// TODO: Consider relaxing to any FP type struct fields.
23012300
bool AttributeFuncs::isNoFPClassCompatibleType(Type *Ty) {
2302-
while (ArrayType *ArrTy = dyn_cast<ArrayType>(Ty))
2303-
Ty = ArrTy->getElementType();
2304-
return Ty->isFPOrFPVectorTy();
2301+
return FPMathOperator::isSupportedFloatingPointType(Ty);
23052302
}
23062303

23072304
/// Which attributes cannot be applied to a type.

llvm/lib/IR/Type.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -430,13 +430,14 @@ bool StructType::containsScalableVectorType(
430430
}
431431

432432
bool StructType::containsHomogeneousScalableVectorTypes() const {
433-
Type *FirstTy = getNumElements() > 0 ? elements()[0] : nullptr;
434-
if (!FirstTy || !isa<ScalableVectorType>(FirstTy))
433+
if (getNumElements() <= 0 || !isa<ScalableVectorType>(elements().front()))
435434
return false;
436-
for (Type *Ty : elements())
437-
if (Ty != FirstTy)
438-
return false;
439-
return true;
435+
return containsHomogeneousTypes();
436+
}
437+
438+
bool StructType::containsHomogeneousTypes() const {
439+
ArrayRef<Type *> ElementTys = elements();
440+
return !ElementTys.empty() && all_equal(ElementTys);
440441
}
441442

442443
void StructType::setBody(ArrayRef<Type*> Elements, bool isPacked) {

llvm/test/Bitcode/compatibility.ll

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1122,6 +1122,26 @@ define void @fastMathFlagsForArrayCalls([2 x float] %f, [2 x double] %d1, [2 x <
11221122
ret void
11231123
}
11241124

1125+
declare { float, float } @fmf_struct_f32()
1126+
declare { double, double, double } @fmf_struct_f64()
1127+
declare { <4 x double> } @fmf_struct_v4f64()
1128+
1129+
; CHECK-LABEL: fastMathFlagsForStructCalls(
1130+
define void @fastMathFlagsForStructCalls() {
1131+
%call.fast = call fast { float, float } @fmf_struct_f32()
1132+
; CHECK: %call.fast = call fast { float, float } @fmf_struct_f32()
1133+
1134+
; Throw in some other attributes to make sure those stay in the right places.
1135+
1136+
%call.nsz.arcp = notail call nsz arcp { double, double, double } @fmf_struct_f64()
1137+
; CHECK: %call.nsz.arcp = notail call nsz arcp { double, double, double } @fmf_struct_f64()
1138+
1139+
%call.nnan.ninf = tail call nnan ninf fastcc { <4 x double> } @fmf_struct_v4f64()
1140+
; CHECK: %call.nnan.ninf = tail call nnan ninf fastcc { <4 x double> } @fmf_struct_v4f64()
1141+
1142+
ret void
1143+
}
1144+
11251145
;; Type System
11261146
%opaquety = type opaque
11271147
define void @typesystem() {
@@ -2077,9 +2097,14 @@ declare nofpclass(sub zero) float @nofpclass_sub_zero(float nofpclass(sub zero))
20772097
; CHECK: declare nofpclass(inf sub) float @nofpclass_sub_inf(float nofpclass(inf sub))
20782098
declare nofpclass(sub inf) float @nofpclass_sub_inf(float nofpclass(sub inf))
20792099

2100+
; CHECK: declare nofpclass(nan) { float, float } @nofpclass_struct({ double } nofpclass(nan))
2101+
declare nofpclass(nan) { float, float } @nofpclass_struct({ double } nofpclass(nan))
2102+
20802103
declare float @unknown_fpclass_func(float)
20812104

2082-
define float @nofpclass_callsites(float %arg) {
2105+
declare { <4 x double>, <4 x double>, <4 x double> } @unknown_fpclass_struct_func({ float })
2106+
2107+
define float @nofpclass_callsites(float %arg, { float } %arg1) {
20832108
; CHECK: %call0 = call nofpclass(nan) float @unknown_fpclass_func(float nofpclass(ninf) %arg)
20842109
%call0 = call nofpclass(nan) float @unknown_fpclass_func(float nofpclass(ninf) %arg)
20852110

@@ -2088,6 +2113,10 @@ define float @nofpclass_callsites(float %arg) {
20882113

20892114
; CHECK: %call2 = call nofpclass(zero) float @unknown_fpclass_func(float nofpclass(norm) %arg)
20902115
%call2 = call nofpclass(zero) float @unknown_fpclass_func(float nofpclass(norm) %arg)
2116+
2117+
; CHECK: %call3 = call nofpclass(pinf) { <4 x double>, <4 x double>, <4 x double> } @unknown_fpclass_struct_func({ float } nofpclass(all) %arg1)
2118+
%call3 = call nofpclass(pinf) { <4 x double>, <4 x double>, <4 x double> } @unknown_fpclass_struct_func({ float } nofpclass(all) %arg1)
2119+
20912120
%add0 = fadd float %call0, %call1
20922121
%add1 = fadd float %add0, %call2
20932122
ret float %add1

0 commit comments

Comments
 (0)