forked from OSchip/llvm-project
[CFE, SystemZ] New target hook testFPKind() for checks of FP values.
The recent commit 00a6254
"Stop traping on sNaN in builtin_isnan" changed the
lowering in constrained FP mode of builtin_isnan from an FP comparison to
integer operations to avoid trapping.
SystemZ has a special instruction "Test Data Class" which is the preferred
way to do this check. This patch adds a new target hook "testFPKind()" that
lets SystemZ emit the s390_tdc intrinsic instead.
testFPKind() takes the BuiltinID as an argument and is expected to soon
handle more opcodes than just 'builtin_isnan'.
Review: Thomas Preud'homme, Ulrich Weigand
Differential Revision: https://reviews.llvm.org/D96568
This commit is contained in:
parent
bb260b1ca7
commit
e57bd1ff4f
|
@ -2997,6 +2997,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
|
|||
return RValue::get(Builder.CreateZExt(V, ConvertType(E->getType())));
|
||||
}
|
||||
|
||||
if (Value *Result = getTargetHooks().testFPKind(V, BuiltinID, Builder, CGM))
|
||||
return RValue::get(Result);
|
||||
|
||||
// NaN has all exp bits set and a non zero significand. Therefore:
|
||||
// isnan(V) == ((exp mask - (abs(V) & exp mask)) < 0)
|
||||
unsigned bitsize = Ty->getScalarSizeInBits();
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "clang/AST/RecordLayout.h"
|
||||
#include "clang/Basic/CodeGenOptions.h"
|
||||
#include "clang/Basic/DiagnosticFrontend.h"
|
||||
#include "clang/Basic/Builtins.h"
|
||||
#include "clang/CodeGen/CGFunctionInfo.h"
|
||||
#include "clang/CodeGen/SwiftCallingConv.h"
|
||||
#include "llvm/ADT/SmallBitVector.h"
|
||||
|
@ -30,6 +31,7 @@
|
|||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/IR/DataLayout.h"
|
||||
#include "llvm/IR/IntrinsicsNVPTX.h"
|
||||
#include "llvm/IR/IntrinsicsS390.h"
|
||||
#include "llvm/IR/Type.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <algorithm> // std::sort
|
||||
|
@ -7200,8 +7202,37 @@ public:
|
|||
SystemZTargetCodeGenInfo(CodeGenTypes &CGT, bool HasVector, bool SoftFloatABI)
|
||||
: TargetCodeGenInfo(
|
||||
std::make_unique<SystemZABIInfo>(CGT, HasVector, SoftFloatABI)) {}
|
||||
};
|
||||
|
||||
llvm::Value *testFPKind(llvm::Value *V, unsigned BuiltinID,
|
||||
CGBuilderTy &Builder,
|
||||
CodeGenModule &CGM) const override {
|
||||
assert(V->getType()->isFloatingPointTy() && "V should have an FP type.");
|
||||
// Only use TDC in constrained FP mode.
|
||||
if (!Builder.getIsFPConstrained())
|
||||
return nullptr;
|
||||
|
||||
llvm::Type *Ty = V->getType();
|
||||
if (Ty->isFloatTy() || Ty->isDoubleTy() || Ty->isFP128Ty()) {
|
||||
llvm::Module &M = CGM.getModule();
|
||||
auto &Ctx = M.getContext();
|
||||
llvm::Function *TDCFunc =
|
||||
llvm::Intrinsic::getDeclaration(&M, llvm::Intrinsic::s390_tdc, Ty);
|
||||
unsigned TDCBits = 0;
|
||||
switch (BuiltinID) {
|
||||
case Builtin::BI__builtin_isnan:
|
||||
TDCBits = 0xf;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (TDCBits)
|
||||
return Builder.CreateCall(
|
||||
TDCFunc,
|
||||
{V, llvm::ConstantInt::get(llvm::Type::getInt64Ty(Ctx), TDCBits)});
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
bool SystemZABIInfo::isPromotableIntegerTypeForABI(QualType Ty) const {
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#ifndef LLVM_CLANG_LIB_CODEGEN_TARGETINFO_H
|
||||
#define LLVM_CLANG_LIB_CODEGEN_TARGETINFO_H
|
||||
|
||||
#include "CGBuilder.h"
|
||||
#include "CodeGenModule.h"
|
||||
#include "CGValue.h"
|
||||
#include "clang/AST/Type.h"
|
||||
|
@ -126,6 +127,16 @@ public:
|
|||
return Address;
|
||||
}
|
||||
|
||||
/// Performs a target specific test of a floating point value for things
|
||||
/// like IsNaN, Infinity, ... Nullptr is returned if no implementation
|
||||
/// exists.
|
||||
virtual llvm::Value *
|
||||
testFPKind(llvm::Value *V, unsigned BuiltinID, CGBuilderTy &Builder,
|
||||
CodeGenModule &CGM) const {
|
||||
assert(V->getType()->isFloatingPointTy() && "V should have an FP type.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// Corrects the low-level LLVM type for a given constraint and "usual"
|
||||
/// type.
|
||||
///
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
|
||||
// REQUIRES: systemz-registered-target
|
||||
// RUN: %clang_cc1 %s -emit-llvm -ffp-exception-behavior=maytrap -o - -triple s390x-linux-gnu | FileCheck %s
|
||||
|
||||
#pragma float_control(except, on)
|
||||
|
||||
// CHECK-LABEL: @test_isnan_float(
|
||||
// CHECK-NEXT: entry:
|
||||
// CHECK-NEXT: [[F_ADDR:%.*]] = alloca float, align 4
|
||||
// CHECK-NEXT: store float [[F:%.*]], float* [[F_ADDR]], align 4
|
||||
// CHECK-NEXT: [[TMP0:%.*]] = load float, float* [[F_ADDR]], align 4
|
||||
// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.s390.tdc.f32(float [[TMP0]], i64 15) [[ATTR2:#.*]]
|
||||
// CHECK-NEXT: ret i32 [[TMP1]]
|
||||
//
|
||||
int test_isnan_float(float f) {
|
||||
return __builtin_isnan(f);
|
||||
}
|
||||
|
||||
// CHECK-LABEL: @test_isnan_double(
|
||||
// CHECK-NEXT: entry:
|
||||
// CHECK-NEXT: [[D_ADDR:%.*]] = alloca double, align 8
|
||||
// CHECK-NEXT: store double [[D:%.*]], double* [[D_ADDR]], align 8
|
||||
// CHECK-NEXT: [[TMP0:%.*]] = load double, double* [[D_ADDR]], align 8
|
||||
// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.s390.tdc.f64(double [[TMP0]], i64 15) [[ATTR2]]
|
||||
// CHECK-NEXT: ret i32 [[TMP1]]
|
||||
//
|
||||
int test_isnan_double(double d) {
|
||||
return __builtin_isnan(d);
|
||||
}
|
||||
|
||||
// CHECK-LABEL: @test_isnan_long_double(
|
||||
// CHECK-NEXT: entry:
|
||||
// CHECK-NEXT: [[LD_ADDR:%.*]] = alloca fp128, align 8
|
||||
// CHECK-NEXT: [[LD:%.*]] = load fp128, fp128* [[TMP0:%.*]], align 8
|
||||
// CHECK-NEXT: store fp128 [[LD]], fp128* [[LD_ADDR]], align 8
|
||||
// CHECK-NEXT: [[TMP1:%.*]] = load fp128, fp128* [[LD_ADDR]], align 8
|
||||
// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.s390.tdc.f128(fp128 [[TMP1]], i64 15) [[ATTR2]]
|
||||
// CHECK-NEXT: ret i32 [[TMP2]]
|
||||
//
|
||||
int test_isnan_long_double(long double ld) {
|
||||
return __builtin_isnan(ld);
|
||||
}
|
||||
|
Loading…
Reference in New Issue