Commit bd4356d5 by Karl Schimpf

Add FABS intrinsic to the integrated ARM assembler.

Adds the non-vector forms of fabs. BUG= https://bugs.chromium.org/p/nativeclient/issues/detail?id=4334 R=eholk@chromium.org, stichnot@chromium.org Review URL: https://codereview.chromium.org/1657193003 .
parent e295575d
......@@ -1036,17 +1036,17 @@ void Assembler::vdivd(DRegister dd, DRegister dn, DRegister dm,
Condition cond) {
EmitVFPddd(cond, B23, dd, dn, dm);
}
#endif
// Moved to Arm32::AssemblerARM32::vabss().
void Assembler::vabss(SRegister sd, SRegister sm, Condition cond) {
EmitVFPsss(cond, B23 | B21 | B20 | B7 | B6, sd, S0, sm);
}
// Moved to Arm32::AssemblerARM32::vabsd().
void Assembler::vabsd(DRegister dd, DRegister dm, Condition cond) {
EmitVFPddd(cond, B23 | B21 | B20 | B7 | B6, dd, D0, dm);
}
#endif
void Assembler::vnegs(SRegister sd, SRegister sm, Condition cond) {
EmitVFPsss(cond, B23 | B21 | B20 | B16 | B6, sd, S0, sm);
......
......@@ -734,8 +734,12 @@ class Assembler : public ValueObject {
void vcugtqi(OperandSize sz, QRegister qd, QRegister qn, QRegister qm);
void vcgtqs(QRegister qd, QRegister qn, QRegister qm);
#if 0
// Moved to Arm32::AssemblerARM32::vabss().
void vabss(SRegister sd, SRegister sm, Condition cond = AL);
// Moved to Arm32::AssemblerARM32::vabss().
void vabsd(DRegister dd, DRegister dm, Condition cond = AL);
#endif
void vabsqs(QRegister qd, QRegister qm);
void vnegs(SRegister sd, SRegister sm, Condition cond = AL);
void vnegd(DRegister dd, DRegister dm, Condition cond = AL);
......
......@@ -2141,6 +2141,34 @@ void AssemblerARM32::uxt(const Operand *OpRd, const Operand *OpSrc0,
emitSignExtend(Cond, UxtOpcode, OpRd, OpSrc0, UxtName);
}
void AssemblerARM32::vabss(const Operand *OpSd, const Operand *OpSm,
CondARM32::Cond Cond) {
// VABS - ARM section A8.8.280, encoding A2:
// vabs<c>.f32 <Sd>, <Sm>
//
// cccc11101D110000dddd101011M0mmmm where cccc=Cond, ddddD=Sd, and mmmmM=Sm.
constexpr const char *Vabss = "vabss";
IValueT Sd = encodeSRegister(OpSd, "Sd", Vabss);
IValueT Sm = encodeSRegister(OpSm, "Sm", Vabss);
constexpr IValueT S0 = 0;
constexpr IValueT VabssOpcode = B23 | B21 | B20 | B7 | B6;
emitVFPsss(Cond, VabssOpcode, Sd, S0, Sm);
}
void AssemblerARM32::vabsd(const Operand *OpDd, const Operand *OpDm,
CondARM32::Cond Cond) {
// VABS - ARM section A8.8.280, encoding A2:
// vabs<c>.f64 <Dd>, <Dm>
//
// cccc11101D110000dddd101111M0mmmm where cccc=Cond, Ddddd=Dd, and Mmmmm=Dm.
constexpr const char *Vabsd = "vabsd";
IValueT Dd = encodeDRegister(OpDd, "Dd", Vabsd);
IValueT Dm = encodeDRegister(OpDm, "Dm", Vabsd);
constexpr IValueT D0 = 0;
constexpr IValueT VabsdOpcode = B23 | B21 | B20 | B7 | B6;
emitVFPddd(Cond, VabsdOpcode, Dd, D0, Dm);
}
void AssemblerARM32::vadds(const Operand *OpSd, const Operand *OpSn,
const Operand *OpSm, CondARM32::Cond Cond) {
// VADD (floating-point) - ARM section A8.8.283, encoding A2:
......
......@@ -312,6 +312,10 @@ public:
// Implements uxtb/uxth depending on type of OpSrc0.
void uxt(const Operand *OpRd, const Operand *OpSrc0, CondARM32::Cond Cond);
void vabss(const Operand *OpSd, const Operand *OpSm, CondARM32::Cond Cond);
void vabsd(const Operand *OpSd, const Operand *OpSm, CondARM32::Cond Cond);
void vaddd(const Operand *OpDd, const Operand *OpDn, const Operand *OpDm,
CondARM32::Cond Cond);
......
......@@ -2228,6 +2228,26 @@ void InstARM32Vabs::emit(const Cfg *Func) const {
getSrc(0)->emit(Func);
}
void InstARM32Vabs::emitIAS(const Cfg *Func) const {
assert(getSrcSize() == 1);
auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
const Variable *Dest = getDest();
switch (Dest->getType()) {
default:
// TODO(kschimpf): Implement vector fabs.
Asm->setNeedsTextFixup();
break;
case IceType_f32:
Asm->vabss(Dest, getSrc(0), getPredicate());
break;
case IceType_f64:
Asm->vabsd(Dest, getSrc(0), getPredicate());
break;
}
if (Asm->needsTextFixup())
emitUsingTextFixup(Func);
}
void InstARM32Vabs::dump(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
......
......@@ -1412,6 +1412,7 @@ public:
InstARM32Vabs(Func, Dest, Src, Predicate);
}
void emit(const Cfg *Func) const override;
void emitIAS(const Cfg *Func) const override;
void dump(const Cfg *Func) const override;
static bool classof(const Inst *Inst) { return isClassof(Inst, Vabs); }
......
; Show that we translate intrinsics for fabs on float and double.
; REQUIRES: allow_dump
; Compile using standalone assembler.
; RUN: %p2i --filetype=asm -i %s --target=arm32 --args -Om1 \
; RUN: -reg-use s20,d22 \
; RUN: | FileCheck %s --check-prefix=ASM
; Show bytes in assembled standalone code.
; RUN: %p2i --filetype=asm -i %s --target=arm32 --assemble --disassemble \
; RUN: --args -Om1 \
; RUN: -reg-use s20,d22 \
; RUN: | FileCheck %s --check-prefix=DIS
; Compile using integrated assembler.
; RUN: %p2i --filetype=iasm -i %s --target=arm32 --args -Om1 \
; RUN: -reg-use s20,d22 \
; RUN: | FileCheck %s --check-prefix=IASM
; Show bytes in assembled integrated code.
; RUN: %p2i --filetype=iasm -i %s --target=arm32 --assemble --disassemble \
; RUN: --args -Om1 \
; RUN: -reg-use s20,d22 \
; RUN: | FileCheck %s --check-prefix=DIS
declare float @llvm.fabs.f32(float)
declare double @llvm.fabs.f64(double)
define internal float @test_fabs_float(float %x) {
; ASM-LABEL: test_fabs_float:
; DIS-LABEL: 00000000 <test_fabs_float>:
; IASM-LABEL: test_fabs_float:
entry:
%r = call float @llvm.fabs.f32(float %x)
; ASM: vabs.f32 s20, s20
; DIS: 10: eeb0aaca
; IASM-NOT: vabs.f32
ret float %r
}
define internal double @test_fabs_double(double %x) {
; ASM-LABEL: test_fabs_double:
; DIS-LABEL: 00000030 <test_fabs_double>:
; IASM-LABEL: test_fabs_double:
entry:
%r = call double @llvm.fabs.f64(double %x)
; ASM: vabs.f64 d22, d22
; DIS: 3c: eef06be6
; IASM-NOT: vabs.64
ret double %r
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment