1,437 changes: 1,437 additions & 0 deletions clang/test/CodeGen/nofpclass.c

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions llvm/include/llvm/IR/Attributes.h
Original file line number Diff line number Diff line change
Expand Up @@ -1265,6 +1265,10 @@ enum AttributeSafetyKind : uint8_t {
ASK_ALL = ASK_SAFE_TO_DROP | ASK_UNSAFE_TO_DROP,
};

/// Returns true if this is a type legal for the 'nofpclass' attribute. This
/// follows the same type rules as FPMathOperator.
bool isNoFPClassCompatibleType(Type *Ty);

/// Which attributes cannot be applied to a type. The argument \p ASK indicates,
/// if only attributes that are known to be safely droppable are contained in
/// the mask; only attributes that might be unsafe to drop (e.g., ABI-related
Expand Down
23 changes: 13 additions & 10 deletions llvm/lib/IR/Attributes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -266,16 +266,6 @@ bool Attribute::isExistingAttribute(StringRef Name) {
.Default(false);
}

/// 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.
static bool isNoFPClassCompatibleType(Type *Ty) {
while (ArrayType *ArrTy = dyn_cast<ArrayType>(Ty))
Ty = ArrTy->getElementType();
return Ty->isFPOrFPVectorTy();
}

//===----------------------------------------------------------------------===//
// Attribute Accessor Methods
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -1850,6 +1840,9 @@ AttrBuilder &AttrBuilder::addMemoryAttr(MemoryEffects ME) {
}

AttrBuilder &AttrBuilder::addNoFPClassAttr(FPClassTest Mask) {
if (Mask == fcNone)
return *this;

return addRawIntAttr(Attribute::NoFPClass, Mask);
}

Expand Down Expand Up @@ -1935,6 +1928,16 @@ bool AttrBuilder::operator==(const AttrBuilder &B) const {
// AttributeFuncs Function Defintions
//===----------------------------------------------------------------------===//

/// 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();
}

/// Which attributes cannot be applied to a type.
AttributeMask AttributeFuncs::typeIncompatible(Type *Ty,
AttributeSafetyKind ASK) {
Expand Down
945 changes: 945 additions & 0 deletions llvm/test/CodeGen/AMDGPU/llvm.is.fpclass.f16.ll

Large diffs are not rendered by default.

1,011 changes: 988 additions & 23 deletions llvm/test/CodeGen/X86/is_fpclass.ll

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions llvm/test/Linker/Inputs/nofpclass.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
define float @declared_as_nonan(float %arg) {
%add = fadd float %arg, 1.0
ret float %add
}
30 changes: 30 additions & 0 deletions llvm/test/Linker/nofpclass.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
; RUN: llvm-link %s %S/Inputs/nofpclass.ll -S -o - | FileCheck -check-prefix=ORDER1 %s
; RUN: llvm-link %S/Inputs/nofpclass.ll %s -S -o - | FileCheck -check-prefix=ORDER2 %s

; Make sure nofpclass is dropped if the function was declared as
; nofpclass, but not defined with nofpclass.

; ORDER1: define float @caller(float %arg) {
; ORDER1-NEXT: %result = call float @declared_as_nonan(float %arg)
; ORDER1-NEXT: ret float %result

; ORDER1: define float @declared_as_nonan(float %arg) {
; ORDER1-NEXT: %add = fadd float %arg, 1.000000e+00
; ORDER1-NEXT: ret float %add


; ORDER2: define float @declared_as_nonan(float %arg) {
; ORDER2-NEXT: %add = fadd float %arg, 1.000000e+00
; ORDER2-NEXT: ret float %add

; ORDER2: define float @caller(float %arg) {
; ORDER2-NEXT: %result = call float @declared_as_nonan(float %arg)
; ORDER2-NEXT: ret float %result


declare nofpclass(nan) float @declared_as_nonan(float nofpclass(nan))

define float @caller(float %arg) {
%result = call float @declared_as_nonan(float %arg)
ret float %result
}
616 changes: 616 additions & 0 deletions llvm/test/Transforms/Attributor/nofpclass.ll

Large diffs are not rendered by default.