mirror of
https://github.com/RPCS3/llvm.git
synced 2025-02-24 12:50:42 +00:00
[WebAssembly] Fix libcall signature lookup
RuntimeLibcallSignatures previously manually initialized all the libcall names into an array and searched it linearly for the first match to lookup the corresponding index. r322802 switched that to initializing a map keyed by the libcall name. Neither of these approaches works correctly because some libcall numbers use the same name on different platforms (e.g. the "l" suffixed functions use f80 or f128 or ppcf128). This change fixes that by ensuring that each name only goes into the map once. It also adds tests. Differential Revision: https://reviews.llvm.org/D42271 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@322971 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
4f82436e1d
commit
667e26447a
@ -296,9 +296,12 @@ struct RuntimeLibcallSignatureTable {
|
||||
Table[RTLIB::UO_F32] = i32_func_f32_f32;
|
||||
Table[RTLIB::UO_F64] = i32_func_f64_f64;
|
||||
Table[RTLIB::UO_F128] = i32_func_i64_i64_i64_i64;
|
||||
Table[RTLIB::O_F32] = i32_func_f32_f32;
|
||||
Table[RTLIB::O_F64] = i32_func_f64_f64;
|
||||
Table[RTLIB::O_F128] = i32_func_i64_i64_i64_i64;
|
||||
// O_FXX has the weird property that it uses the same libcall name as UO_FXX
|
||||
// This breaks our name-based lookup. Fortunately only the UO family of
|
||||
// libcalls appears to be actually used.
|
||||
Table[RTLIB::O_F32] = unsupported;
|
||||
Table[RTLIB::O_F64] = unsupported;
|
||||
Table[RTLIB::O_F128] = unsupported;
|
||||
|
||||
// Memory
|
||||
Table[RTLIB::MEMCPY] = iPTR_func_iPTR_iPTR_iPTR;
|
||||
@ -455,26 +458,24 @@ struct RuntimeLibcallSignatureTable {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
StringRef StringRefOrEmpty(const char* arg) {
|
||||
if (arg) return StringRef(arg);
|
||||
return StringRef();
|
||||
}
|
||||
ManagedStatic<RuntimeLibcallSignatureTable> RuntimeLibcallSignatures;
|
||||
|
||||
// Maps libcall names to their RTLIB::Libcall number. Builds the map in a
|
||||
// constructor for use with ManagedStatic
|
||||
struct StaticLibcallNameMap {
|
||||
StringMap<RTLIB::Libcall> Map;
|
||||
StaticLibcallNameMap() {
|
||||
#define HANDLE_LIBCALL(code, name) \
|
||||
Map[StringRefOrEmpty(name)] = RTLIB::code;
|
||||
#include "llvm/CodeGen/RuntimeLibcalls.def"
|
||||
#define HANDLE_LIBCALL(code, name) \
|
||||
if (name && RuntimeLibcallSignatures->Table[RTLIB::code] != unsupported) { \
|
||||
assert(Map.find(StringRef::withNullAsEmpty(name)) == Map.end() && \
|
||||
"duplicate libcall names in name map"); \
|
||||
Map[StringRef::withNullAsEmpty(name)] = RTLIB::code; \
|
||||
}
|
||||
#include "llvm/CodeGen/RuntimeLibcalls.def"
|
||||
#undef HANDLE_LIBCALL
|
||||
}
|
||||
};
|
||||
|
||||
ManagedStatic<RuntimeLibcallSignatureTable> RuntimeLibcallSignatures;
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
|
||||
|
107
test/CodeGen/WebAssembly/libcalls.ll
Normal file
107
test/CodeGen/WebAssembly/libcalls.ll
Normal file
@ -0,0 +1,107 @@
|
||||
; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
|
||||
|
||||
; Test a subset of compiler-rt/libm libcalls expected to be emitted by the wasm backend
|
||||
|
||||
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
|
||||
target triple = "wasm32-unknown-unknown-wasm"
|
||||
|
||||
declare fp128 @llvm.sqrt.f128(fp128)
|
||||
declare fp128 @llvm.floor.f128(fp128)
|
||||
declare fp128 @llvm.trunc.f128(fp128)
|
||||
declare fp128 @llvm.nearbyint.f128(fp128)
|
||||
declare fp128 @llvm.pow.f128(fp128, fp128)
|
||||
|
||||
declare double @llvm.cos.f64(double)
|
||||
declare double @llvm.log10.f64(double)
|
||||
|
||||
|
||||
; CHECK-LABEL: fp128libcalls:
|
||||
define fp128 @fp128libcalls(fp128 %x, fp128 %y) {
|
||||
; compiler-rt call
|
||||
; CHECK: call __addtf3
|
||||
%a = fadd fp128 %x, %y
|
||||
; CHECK: call __multf3
|
||||
%b = fmul fp128 %a, %y
|
||||
; CHECK: call __divtf3
|
||||
%c = fdiv fp128 %b, %y
|
||||
; libm calls
|
||||
; CHECK: call sqrtl
|
||||
%d = call fp128 @llvm.sqrt.f128(fp128 %c)
|
||||
; CHECK: call floorl
|
||||
%e = call fp128 @llvm.floor.f128(fp128 %d)
|
||||
; CHECK: call powl
|
||||
%f = call fp128 @llvm.pow.f128(fp128 %e, fp128 %y)
|
||||
; CHECK: call truncl
|
||||
%g = call fp128 @llvm.trunc.f128(fp128 %f)
|
||||
; CHECK: call nearbyintl
|
||||
%h = call fp128 @llvm.nearbyint.f128(fp128 %g)
|
||||
ret fp128 %h
|
||||
}
|
||||
|
||||
; CHECK-LABEL: i128libcalls:
|
||||
define i128 @i128libcalls(i128 %x, i128 %y) {
|
||||
; Basic ops should be expanded
|
||||
; CHECK_NOT: call
|
||||
%a = add i128 %x, %y
|
||||
; CHECK: call __multi3
|
||||
%b = mul i128 %a, %y
|
||||
; CHECK: call __umodti3
|
||||
%c = urem i128 %b, %y
|
||||
ret i128 %c
|
||||
}
|
||||
|
||||
; CHECK-LABEL: f64libcalls:
|
||||
define double @f64libcalls(double %x, double %y) {
|
||||
; CHECK: f64.call $push{{[0-9]}}=, cos@FUNCTION
|
||||
%a = call double @llvm.cos.f64(double %x)
|
||||
; CHECK: f64.call $push{{[0-9]}}=, log10@FUNCTION
|
||||
%b = call double @llvm.log10.f64(double %a)
|
||||
ret double %b
|
||||
}
|
||||
|
||||
; fcmp ord and unord (RTLIB::O_F32 / RTLIB::UO_F32 etc) are a special case (see
|
||||
; comment in WebAssemblyRunimeLibcallSignatures.cpp) so check them separately.
|
||||
; no libcalls are needed for f32 and f64
|
||||
|
||||
; CHECK-LABEL: unordd:
|
||||
define i1 @unordd(double %x, double %y) {
|
||||
; CHECK-NOT: call
|
||||
; CHECK: f64.ne
|
||||
%a = fcmp uno double %x, %y
|
||||
; CHECK-NOT: call
|
||||
; CHECK: f64.eq
|
||||
%b = fcmp ord double %x, %y
|
||||
; CHECK: i32.xor
|
||||
%c = xor i1 %a, %b
|
||||
ret i1 %c
|
||||
}
|
||||
|
||||
; CHECK-LABEL: unordf:
|
||||
define i1 @unordf(float %x, float %y) {
|
||||
; CHECK-NOT: call
|
||||
; CHECK: f32.ne
|
||||
%a = fcmp uno float %x, %y
|
||||
; CHECK-NOT: call
|
||||
; CHECK: f32.eq
|
||||
%b = fcmp ord float %x, %y
|
||||
; CHECK: i32.xor
|
||||
%c = xor i1 %a, %b
|
||||
ret i1 %c
|
||||
}
|
||||
|
||||
; CHECK-LABEL: unordt:
|
||||
define i1 @unordt(fp128 %x, fp128 %y) {
|
||||
; CHECK: i32.call $push[[CALL:[0-9]]]=, __unordtf2
|
||||
; CHECK-NEXT: i32.const $push[[ZERO:[0-9]+]]=, 0
|
||||
; CHECK-NEXT: i32.ne $push{{[0-9]}}=, $pop[[CALL]], $pop[[ZERO]]
|
||||
%a = fcmp uno fp128 %x, %y
|
||||
ret i1 %a
|
||||
}
|
||||
|
||||
; CHECK-LABEL: ordt:
|
||||
define i1 @ordt(fp128 %x, fp128 %y) {
|
||||
; CHECK: i32.call $push[[CALL:[0-9]]]=, __unordtf2
|
||||
; CHECK-NEXT: i32.eqz $push{{[0-9]}}=, $pop[[CALL]]
|
||||
%a = fcmp ord fp128 %x, %y
|
||||
ret i1 %a
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user