[WebAssembly] Add SIMD integer abs builtins

Summary:
Since the conditional operator cannot be used with vector conditions
in C, we need a builtin to be able to express this operation in C
source.

Reviewers: aheejin

Subscribers: dschuff, sbc100, jgravelle-google, sunfish, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D76538
This commit is contained in:
Thomas Lively 2020-03-20 19:30:56 -07:00
parent 85c30f3374
commit de6cd3e836
3 changed files with 37 additions and 0 deletions

View File

@ -98,6 +98,10 @@ TARGET_BUILTIN(__builtin_wasm_sub_saturate_u_i8x16, "V16cV16cV16c", "nc", "simd1
TARGET_BUILTIN(__builtin_wasm_sub_saturate_s_i16x8, "V8sV8sV8s", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_sub_saturate_u_i16x8, "V8sV8sV8s", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_abs_i8x16, "V16cV16c", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_abs_i16x8, "V8sV8s", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_abs_i32x4, "V4iV4i", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_min_s_i8x16, "V16cV16cV16c", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_min_u_i8x16, "V16cV16cV16c", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_max_s_i8x16, "V16cV16cV16c", "nc", "simd128")

View File

@ -15050,6 +15050,15 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID,
Function *Callee = CGM.getIntrinsic(IntNo, ConvertType(E->getType()));
return Builder.CreateCall(Callee, {LHS, RHS});
}
case WebAssembly::BI__builtin_wasm_abs_i8x16:
case WebAssembly::BI__builtin_wasm_abs_i16x8:
case WebAssembly::BI__builtin_wasm_abs_i32x4: {
Value *Vec = EmitScalarExpr(E->getArg(0));
Value *Neg = Builder.CreateNeg(Vec, "neg");
Constant *Zero = llvm::Constant::getNullValue(Vec->getType());
Value *ICmp = Builder.CreateICmpSLT(Vec, Zero, "abscond");
return Builder.CreateSelect(ICmp, Neg, Vec, "abs");
}
case WebAssembly::BI__builtin_wasm_min_s_i8x16:
case WebAssembly::BI__builtin_wasm_min_u_i8x16:
case WebAssembly::BI__builtin_wasm_max_s_i8x16:

View File

@ -338,6 +338,30 @@ i8x16 sub_saturate_u_i8x16(i8x16 x, i8x16 y) {
// WEBASSEMBLY-NEXT: ret
}
i8x16 abs_i8x16(i8x16 v) {
return __builtin_wasm_abs_i8x16(v);
// WEBASSEMBLY: %neg = sub <16 x i8> zeroinitializer, %v
// WEBASSEMBLY: %abscond = icmp slt <16 x i8> %v, zeroinitializer
// WEBASSEMBLY: %abs = select <16 x i1> %abscond, <16 x i8> %neg, <16 x i8> %v
// WEBASSEMBLY: ret <16 x i8> %abs
}
i16x8 abs_i16x8(i16x8 v) {
return __builtin_wasm_abs_i16x8(v);
// WEBASSEMBLY: %neg = sub <8 x i16> zeroinitializer, %v
// WEBASSEMBLY: %abscond = icmp slt <8 x i16> %v, zeroinitializer
// WEBASSEMBLY: %abs = select <8 x i1> %abscond, <8 x i16> %neg, <8 x i16> %v
// WEBASSEMBLY: ret <8 x i16> %abs
}
i32x4 abs_i32x4(i32x4 v) {
return __builtin_wasm_abs_i32x4(v);
// WEBASSEMBLY: %neg = sub <4 x i32> zeroinitializer, %v
// WEBASSEMBLY: %abscond = icmp slt <4 x i32> %v, zeroinitializer
// WEBASSEMBLY: %abs = select <4 x i1> %abscond, <4 x i32> %neg, <4 x i32> %v
// WEBASSEMBLY: ret <4 x i32> %abs
}
i8x16 min_s_i8x16(i8x16 x, i8x16 y) {
return __builtin_wasm_min_s_i8x16(x, y);
// WEBASSEMBLY: %0 = icmp slt <16 x i8> %x, %y