Skip to content

Commit

Permalink
clang: Use new frexp intrinsic for builtins and add f16 version
Browse files Browse the repository at this point in the history
  • Loading branch information
arsenm committed Jun 28, 2023
1 parent 003b58f commit 85bdea0
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 17 deletions.
1 change: 1 addition & 0 deletions clang/include/clang/Basic/Builtins.def
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ BUILTIN(__builtin_frexp , "ddi*" , "Fn")
BUILTIN(__builtin_frexpf, "ffi*" , "Fn")
BUILTIN(__builtin_frexpl, "LdLdi*", "Fn")
BUILTIN(__builtin_frexpf128, "LLdLLdi*", "Fn")
BUILTIN(__builtin_frexpf16, "hhi*" , "Fn")
BUILTIN(__builtin_huge_val, "d", "ncE")
BUILTIN(__builtin_huge_valf, "f", "ncE")
BUILTIN(__builtin_huge_vall, "Ld", "ncE")
Expand Down
24 changes: 24 additions & 0 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,24 @@ emitMaybeConstrainedFPToIntRoundBuiltin(CodeGenFunction &CGF, const CallExpr *E,
}
}

static Value *emitFrexpBuiltin(CodeGenFunction &CGF, const CallExpr *E,
llvm::Intrinsic::ID IntrinsicID) {
llvm::Value *Src0 = CGF.EmitScalarExpr(E->getArg(0));
llvm::Value *Src1 = CGF.EmitScalarExpr(E->getArg(1));

QualType IntPtrTy = E->getArg(1)->getType()->getPointeeType();
llvm::Type *IntTy = CGF.ConvertType(IntPtrTy);
llvm::Function *F =
CGF.CGM.getIntrinsic(IntrinsicID, {Src0->getType(), IntTy});
llvm::Value *Call = CGF.Builder.CreateCall(F, Src0);

llvm::Value *Exp = CGF.Builder.CreateExtractValue(Call, 1);
LValue LV = CGF.MakeNaturalAlignAddrLValue(Src1, IntPtrTy);
CGF.EmitStoreOfScalar(Exp, LV);

return CGF.Builder.CreateExtractValue(Call, 0);
}

/// EmitFAbs - Emit a call to @llvm.fabs().
static Value *EmitFAbs(CodeGenFunction &CGF, Value *V) {
Function *F = CGF.CGM.getIntrinsic(Intrinsic::fabs, V->getType());
Expand Down Expand Up @@ -3062,6 +3080,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
{ Src0->getType(), Src1->getType() });
return RValue::get(Builder.CreateCall(F, { Src0, Src1 }));
}
case Builtin::BI__builtin_frexp:
case Builtin::BI__builtin_frexpf:
case Builtin::BI__builtin_frexpl:
case Builtin::BI__builtin_frexpf128:
case Builtin::BI__builtin_frexpf16:
return RValue::get(emitFrexpBuiltin(*this, E, Intrinsic::frexp));
case Builtin::BI__builtin_isgreater:
case Builtin::BI__builtin_isgreaterequal:
case Builtin::BI__builtin_isless:
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CodeGen/aix-builtin-mapping.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ int main()
}

// CHECK: %call = call double @modf(double noundef 1.000000e+00, ptr noundef %DummyLongDouble) #3
// CHECK: %call1 = call double @frexp(double noundef 0.000000e+00, ptr noundef %DummyInt) #3
// CHECK: %{{.+}} = call { double, i32 } @llvm.frexp.f64.i32(double 0.000000e+00)
// CHECK: %{{.+}} = call double @llvm.ldexp.f64.i32(double 1.000000e+00, i32 1)
10 changes: 7 additions & 3 deletions clang/test/CodeGen/builtin-attributes.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
int printf(const char *, ...);
void exit(int);

float frexpf(float, int*);
double frexp(double, int*);
long double frexpl(long double, int*);

// CHECK: declare i32 @printf(ptr noundef, ...)
void f0() {
printf("a\n");
Expand Down Expand Up @@ -49,9 +53,9 @@ char* f2(char* a, char* b) {
// CHECK: ret
int f3(double x) {
int e;
__builtin_frexp(x, &e);
__builtin_frexpf(x, &e);
__builtin_frexpl(x, &e);
frexp(x, &e);
frexpf(x, &e);
frexpl(x, &e);
__builtin_modf(x, &e);
__builtin_modff(x, &e);
__builtin_modfl(x, &e);
Expand Down
8 changes: 4 additions & 4 deletions clang/test/CodeGen/math-builtins-long.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ void foo(long double f, long double *l, int *i, const char *c) {
// PPCF128: call fp128 @llvm.fabs.f128(fp128 %{{.+}})
__builtin_fabsl(f);

// F80: call x86_fp80 @frexpl(x86_fp80 noundef %{{.+}}, ptr noundef %{{.+}})
// PPC: call ppc_fp128 @frexpl(ppc_fp128 noundef %{{.+}}, ptr noundef %{{.+}})
// X86F128: call fp128 @frexpl(fp128 noundef %{{.+}}, ptr noundef %{{.+}})
// PPCF128: call fp128 @frexpf128(fp128 noundef %{{.+}}, ptr noundef %{{.+}})
// F80: call { x86_fp80, i32 } @llvm.frexp.f80.i32(x86_fp80 %{{.+}})
// PPC: call { ppc_fp128, i32 } @llvm.frexp.ppcf128.i32(ppc_fp128 %{{.+}})
// X86F128: call { fp128, i32 } @llvm.frexp.f128.i32(fp128 %{{.+}})
// PPCF128: call { fp128, i32 } @llvm.frexp.f128.i32(fp128 %{{.+}})
__builtin_frexpl(f,i);

// F80: store x86_fp80 0xK7FFF8000000000000000, ptr
Expand Down
42 changes: 33 additions & 9 deletions clang/test/CodeGen/math-builtins.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,30 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) {
// NO__ERRNO: frem float
// NO__ERRNO: frem x86_fp80
// NO__ERRNO: frem fp128

// NO__ERRNO: [[FREXP_F64:%.+]] = call { double, i32 } @llvm.frexp.f64.i32(double %{{.+}})
// NO__ERRNO-NEXT: [[FREXP_F64_1:%.+]] = extractvalue { double, i32 } [[FREXP_F64]], 1
// NO__ERRNO-NEXT: store i32 [[FREXP_F64_1]], ptr %{{.+}}, align 4
// NO__ERRNO-NEXT: [[FREXP_F64_0:%.+]] = extractvalue { double, i32 } [[FREXP_F64]], 0

// NO__ERRNO: [[FREXP_F32:%.+]] = call { float, i32 } @llvm.frexp.f32.i32(float %{{.+}})
// NO__ERRNO-NEXT: [[FREXP_F32_1:%.+]] = extractvalue { float, i32 } [[FREXP_F32]], 1
// NO__ERRNO-NEXT: store i32 [[FREXP_F32_1]], ptr %{{.+}}, align 4
// NO__ERRNO-NEXT: [[FREXP_F32_0:%.+]] = extractvalue { float, i32 } [[FREXP_F32]], 0


// NO__ERRNO: [[FREXP_F80:%.+]] = call { x86_fp80, i32 } @llvm.frexp.f80.i32(x86_fp80 %{{.+}})
// NO__ERRNO-NEXT: [[FREXP_F80_1:%.+]] = extractvalue { x86_fp80, i32 } [[FREXP_F80]], 1
// NO__ERRNO-NEXT: store i32 [[FREXP_F80_1]], ptr %{{.+}}, align 4
// NO__ERRNO-NEXT: [[FREXP_F80_0:%.+]] = extractvalue { x86_fp80, i32 } [[FREXP_F80]], 0


// NO__ERRNO: [[FREXP_F128:%.+]] = call { fp128, i32 } @llvm.frexp.f128.i32(fp128 %{{.+}})
// NO__ERRNO-NEXT: [[FREXP_F128_1:%.+]] = extractvalue { fp128, i32 } [[FREXP_F128]], 1
// NO__ERRNO-NEXT: store i32 [[FREXP_F128_1]], ptr %{{.+}}, align 4
// NO__ERRNO-NEXT: [[FREXP_F128_0:%.+]] = extractvalue { fp128, i32 } [[FREXP_F128]], 0


// HAS_ERRNO: declare double @fmod(double noundef, double noundef) [[NOT_READNONE:#[0-9]+]]
// HAS_ERRNO: declare float @fmodf(float noundef, float noundef) [[NOT_READNONE]]
// HAS_ERRNO: declare x86_fp80 @fmodl(x86_fp80 noundef, x86_fp80 noundef) [[NOT_READNONE]]
Expand Down Expand Up @@ -52,14 +76,14 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) {

__builtin_frexp(f,i); __builtin_frexpf(f,i); __builtin_frexpl(f,i); __builtin_frexpf128(f,i);

// NO__ERRNO: declare double @frexp(double noundef, ptr noundef) [[NOT_READNONE:#[0-9]+]]
// NO__ERRNO: declare float @frexpf(float noundef, ptr noundef) [[NOT_READNONE]]
// NO__ERRNO: declare x86_fp80 @frexpl(x86_fp80 noundef, ptr noundef) [[NOT_READNONE]]
// NO__ERRNO: declare fp128 @frexpf128(fp128 noundef, ptr noundef) [[NOT_READNONE]]
// HAS_ERRNO: declare double @frexp(double noundef, ptr noundef) [[NOT_READNONE]]
// HAS_ERRNO: declare float @frexpf(float noundef, ptr noundef) [[NOT_READNONE]]
// HAS_ERRNO: declare x86_fp80 @frexpl(x86_fp80 noundef, ptr noundef) [[NOT_READNONE]]
// HAS_ERRNO: declare fp128 @frexpf128(fp128 noundef, ptr noundef) [[NOT_READNONE]]
// NO__ERRNO: declare { double, i32 } @llvm.frexp.f64.i32(double) [[READNONE_INTRINSIC]]
// NO__ERRNO: declare { float, i32 } @llvm.frexp.f32.i32(float) [[READNONE_INTRINSIC]]
// NO__ERRNO: declare { x86_fp80, i32 } @llvm.frexp.f80.i32(x86_fp80) [[READNONE_INTRINSIC]]
// NO__ERRNO: declare { fp128, i32 } @llvm.frexp.f128.i32(fp128) [[READNONE_INTRINSIC]]
// HAS_ERRNO: declare { double, i32 } @llvm.frexp.f64.i32(double) [[READNONE_INTRINSIC]]
// HAS_ERRNO: declare { float, i32 } @llvm.frexp.f32.i32(float) [[READNONE_INTRINSIC]]
// HAS_ERRNO: declare { x86_fp80, i32 } @llvm.frexp.f80.i32(x86_fp80) [[READNONE_INTRINSIC]]
// HAS_ERRNO: declare { fp128, i32 } @llvm.frexp.f128.i32(fp128) [[READNONE_INTRINSIC]]

__builtin_huge_val(); __builtin_huge_valf(); __builtin_huge_vall(); __builtin_huge_valf128();

Expand Down Expand Up @@ -88,7 +112,7 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) {

__builtin_modf(f,d); __builtin_modff(f,fp); __builtin_modfl(f,l); __builtin_modff128(f,l);

// NO__ERRNO: declare double @modf(double noundef, ptr noundef) [[NOT_READNONE]]
// NO__ERRNO: declare double @modf(double noundef, ptr noundef) [[NOT_READNONE:#[0-9]+]]
// NO__ERRNO: declare float @modff(float noundef, ptr noundef) [[NOT_READNONE]]
// NO__ERRNO: declare x86_fp80 @modfl(x86_fp80 noundef, ptr noundef) [[NOT_READNONE]]
// NO__ERRNO: declare fp128 @modff128(fp128 noundef, ptr noundef) [[NOT_READNONE]]
Expand Down
30 changes: 30 additions & 0 deletions clang/test/CodeGenOpenCL/builtins-generic-amdgcn.cl
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,33 @@ float test_builtin_ldexpf(float v, int e) {
double test_builtin_ldexp(double v, int e) {
return __builtin_ldexp(v, e);
}

// CHECK-LABEL: @test_builtin_frexpf16(
// CHECK: [[VAL:%.+]] = tail call { half, i32 } @llvm.frexp.f16.i32(half %v)
// CHECK: [[EXTRACT_1:%.+]] = extractvalue { half, i32 } [[VAL]], 1
// CHECK: store i32 [[EXTRACT_1]], ptr addrspace(5)
// CHECK: [[EXTRACT_0:%.+]] = extractvalue { half, i32 } [[VAL]], 0
// CHECK: ret half [[EXTRACT_0]]
half test_builtin_frexpf16(half v, int* e) {
return __builtin_frexpf16(v, e);
}

// CHECK-LABEL: @test_builtin_frexpf(
// CHECK: [[VAL:%.+]] = tail call { float, i32 } @llvm.frexp.f32.i32(float %v)
// CHECK: [[EXTRACT_1:%.+]] = extractvalue { float, i32 } [[VAL]], 1
// CHECK: store i32 [[EXTRACT_1]], ptr addrspace(5)
// CHECK: [[EXTRACT_0:%.+]] = extractvalue { float, i32 } [[VAL]], 0
// CHECK: ret float [[EXTRACT_0]]
float test_builtin_frexpf(float v, int* e) {
return __builtin_frexpf(v, e);
}

// CHECK-LABEL: @test_builtin_frexp(
// CHECK: [[VAL:%.+]] = tail call { double, i32 } @llvm.frexp.f64.i32(double %v)
// CHECK: [[EXTRACT_1:%.+]] = extractvalue { double, i32 } [[VAL]], 1
// CHECK: store i32 [[EXTRACT_1]], ptr addrspace(5)
// CHECK: [[EXTRACT_0:%.+]] = extractvalue { double, i32 } [[VAL]], 0
// CHECK: ret double [[EXTRACT_0]]
double test_builtin_frexp(double v, int* e) {
return __builtin_frexp(v, e);
}

1 comment on commit 85bdea0

@zmodem
Copy link
Collaborator

@zmodem zmodem commented on 85bdea0 Jun 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're seeing asserts after this in Android and Windows builds. See https://bugs.chromium.org/p/chromium/issues/detail?id=1459557#c1 for a reproducer.

Reverted in 0c545a4

Please sign in to comment.