OSDN Git Service

Add VCMP{s,sz,d,dz} Instructions to ARM integrated assembler.
authorKarl Schimpf <kschimpf@google.com>
Mon, 11 Jan 2016 18:12:20 +0000 (10:12 -0800)
committerKarl Schimpf <kschimpf@google.com>
Mon, 11 Jan 2016 18:12:20 +0000 (10:12 -0800)
Also fixes bug in emitVFPddd.

BUG= https://bugs.chromium.org/p/nativeclient/issues/detail?id=4334
R=stichnot@chromium.org

Review URL: https://codereview.chromium.org/1564393002 .

src/DartARM32/assembler_arm.cc
src/DartARM32/assembler_arm.h
src/IceAssemblerARM32.cpp
src/IceAssemblerARM32.h
src/IceInstARM32.cpp
src/IceInstARM32.h
tests_lit/assembler/arm32/vcmp.ll [new file with mode: 0644]

index 990c083..4dca55a 100644 (file)
@@ -1153,26 +1153,27 @@ void Assembler::vcvtdu(DRegister dd, SRegister sm, Condition cond) {
   EmitVFPds(cond, B23 | B21 | B20 | B19 | B8 | B6, dd, sm);
 }
 
-
+#if 0
+// Moved to ARM23::AssemblerARM32::vcmps().
 void Assembler::vcmps(SRegister sd, SRegister sm, Condition cond) {
   EmitVFPsss(cond, B23 | B21 | B20 | B18 | B6, sd, S0, sm);
 }
 
-
+// Moved to ARM23::AssemblerARM32::vcmpd().
 void Assembler::vcmpd(DRegister dd, DRegister dm, Condition cond) {
   EmitVFPddd(cond, B23 | B21 | B20 | B18 | B6, dd, D0, dm);
 }
 
-
+// Moved to ARM23::AssemblerARM32::vcmpsz().
 void Assembler::vcmpsz(SRegister sd, Condition cond) {
   EmitVFPsss(cond, B23 | B21 | B20 | B18 | B16 | B6, sd, S0, S0);
 }
 
-
+// Moved to ARM23::AssemblerARM32::vcmpdz().
 void Assembler::vcmpdz(DRegister dd, Condition cond) {
   EmitVFPddd(cond, B23 | B21 | B20 | B18 | B16 | B6, dd, D0, D0);
 }
-
+#endif
 
 void Assembler::vmrs(Register rd, Condition cond) {
   ASSERT(TargetCPUFeatures::vfp_supported());
index e103282..de8d4da 100644 (file)
@@ -729,10 +729,17 @@ class Assembler : public ValueObject {
   void vcvtsu(SRegister sd, SRegister sm, Condition cond = AL);
   void vcvtdu(DRegister dd, SRegister sm, Condition cond = AL);
 
+#if 0
+  // Moved to ARM23::AssemblerARM32::vcmps().
   void vcmps(SRegister sd, SRegister sm, Condition cond = AL);
+  // Moved to ARM23::AssemblerARM32::vcmpd().
   void vcmpd(DRegister dd, DRegister dm, Condition cond = AL);
+  // Moved to ARM23::AssemblerARM32::vcmpsz().
   void vcmpsz(SRegister sd, Condition cond = AL);
+  // Moved to ARM23::AssemblerARM32::vcmpdz().
   void vcmpdz(DRegister dd, Condition cond = AL);
+#endif
+
   void vmrs(Register rd, Condition cond = AL);
   void vmstat(Condition cond = AL);
 
index 51cbf8d..1d0cf7e 100644 (file)
@@ -1010,7 +1010,7 @@ void AssemblerARM32::emitVFPddd(CondARM32::Cond Cond, IValueT Opcode,
   const IValueT Encoding =
       Opcode | VFPOpcode | (encodeCondition(Cond) << kConditionShift) |
       (getYInRegYXXXX(Dd) << 22) | (getXXXXInRegYXXXX(Dn) << 16) |
-      (getXXXXInRegYXXXX(Dn) << 12) | (getYInRegYXXXX(Dn) << 7) |
+      (getXXXXInRegYXXXX(Dd) << 12) | (getYInRegYXXXX(Dn) << 7) |
       (getYInRegYXXXX(Dm) << 5) | getXXXXInRegYXXXX(Dm);
   emitInst(Encoding);
 }
@@ -2071,6 +2071,44 @@ void AssemblerARM32::vaddd(const Operand *OpDd, const Operand *OpDn,
   emitVFPddd(Cond, VadddOpcode, Dd, Dn, Dm);
 }
 
+void AssemblerARM32::vcmpd(const Operand *OpDd, const Operand *OpDm,
+                           CondARM32::Cond Cond) {
+  constexpr const char *Vcmpd = "vcmpd";
+  IValueT Dd = encodeDRegister(OpDd, "Dd", Vcmpd);
+  IValueT Dm = encodeDRegister(OpDm, "Dm", Vcmpd);
+  constexpr IValueT VcmpdOpcode = B23 | B21 | B20 | B18 | B6;
+  constexpr IValueT Dn = 0;
+  emitVFPddd(Cond, VcmpdOpcode, Dd, Dn, Dm);
+}
+
+void AssemblerARM32::vcmpdz(const Operand *OpDd, CondARM32::Cond Cond) {
+  constexpr const char *Vcmpdz = "vcmpdz";
+  IValueT Dd = encodeDRegister(OpDd, "Dd", Vcmpdz);
+  constexpr IValueT VcmpdzOpcode = B23 | B21 | B20 | B18 | B16 | B6;
+  constexpr IValueT Dn = 0;
+  constexpr IValueT Dm = 0;
+  emitVFPddd(Cond, VcmpdzOpcode, Dd, Dn, Dm);
+}
+
+void AssemblerARM32::vcmps(const Operand *OpSd, const Operand *OpSm,
+                           CondARM32::Cond Cond) {
+  constexpr const char *Vcmps = "vcmps";
+  IValueT Sd = encodeSRegister(OpSd, "Sd", Vcmps);
+  IValueT Sm = encodeSRegister(OpSm, "Sm", Vcmps);
+  constexpr IValueT VcmpsOpcode = B23 | B21 | B20 | B18 | B6;
+  constexpr IValueT Sn = 0;
+  emitVFPsss(Cond, VcmpsOpcode, Sd, Sn, Sm);
+}
+
+void AssemblerARM32::vcmpsz(const Operand *OpSd, CondARM32::Cond Cond) {
+  constexpr const char *Vcmpsz = "vcmps";
+  IValueT Sd = encodeSRegister(OpSd, "Sd", Vcmpsz);
+  constexpr IValueT VcmpszOpcode = B23 | B21 | B20 | B18 | B16 | B6;
+  constexpr IValueT Sn = 0;
+  constexpr IValueT Sm = 0;
+  emitVFPsss(Cond, VcmpszOpcode, Sd, Sn, Sm);
+}
+
 void AssemblerARM32::emitVFPsd(CondARM32::Cond Cond, IValueT Opcode, IValueT Sd,
                                IValueT Dm) {
   assert(Sd < RegARM32::getNumSRegs());
index 86b2bd0..955bde7 100644 (file)
@@ -318,6 +318,16 @@ public:
   void vadds(const Operand *OpSd, const Operand *OpSn, const Operand *OpSm,
              CondARM32::Cond Cond);
 
+  void vcmpd(const Operand *OpDd, const Operand *OpDm, CondARM32::Cond cond);
+
+  // Second argument of compare is zero (+0.0).
+  void vcmpdz(const Operand *OpDd, CondARM32::Cond cond);
+
+  void vcmps(const Operand *OpSd, const Operand *OpSm, CondARM32::Cond cond);
+
+  // Second argument of compare is zero (+0.0).
+  void vcmpsz(const Operand *OpSd, CondARM32::Cond cond);
+
   void vcvtsd(const Operand *OpSd, const Operand *OpDm, CondARM32::Cond Cond);
 
   void vcvtds(const Operand *OpDd, const Operand *OpSm, CondARM32::Cond Cond);
index b4214bc..075dd4d 100644 (file)
@@ -1864,6 +1864,39 @@ void InstARM32Vcmp::emit(const Cfg *Func) const {
   getSrc(1)->emit(Func);
 }
 
+void InstARM32Vcmp::emitIAS(const Cfg *Func) const {
+  assert(getSrcSize() == 2);
+  const Operand *Src0 = getSrc(0);
+  const Type Ty = Src0->getType();
+  const Operand *Src1 = getSrc(1);
+  const CondARM32::Cond Cond = getPredicate();
+  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
+  if (llvm::isa<OperandARM32FlexFpZero>(Src1)) {
+    switch (Ty) {
+    case IceType_f32:
+      Asm->vcmpsz(Src0, Cond);
+      break;
+    case IceType_f64:
+      Asm->vcmpdz(Src0, Cond);
+      break;
+    default:
+      llvm::report_fatal_error("Vcvt on non floating value");
+    }
+  } else {
+    switch (Ty) {
+    case IceType_f32:
+      Asm->vcmps(Src0, Src1, Cond);
+      break;
+    case IceType_f64:
+      Asm->vcmpd(Src0, Src1, Cond);
+      break;
+    default:
+      llvm::report_fatal_error("Vcvt on non floating value");
+    }
+  }
+  assert(!Asm->needsTextFixup());
+}
+
 void InstARM32Vcmp::dump(const Cfg *Func) const {
   if (!BuildDefs::dump())
     return;
index 719e446..6a9aa35 100644 (file)
@@ -1362,6 +1362,7 @@ public:
         InstARM32Vcmp(Func, Src0, Src1, 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, Vcmp); }
 
diff --git a/tests_lit/assembler/arm32/vcmp.ll b/tests_lit/assembler/arm32/vcmp.ll
new file mode 100644 (file)
index 0000000..c1d1236
--- /dev/null
@@ -0,0 +1,98 @@
+; Show that we know how to translate vcmp.
+
+; REQUIRES: allow_dump
+
+; TODO(kschimpf): Use include registers for compare instructions, so that the
+; test is less brittle.
+
+; Compile using standalone assembler.
+; RUN: %p2i --filetype=asm -i %s --target=arm32 --args -Om1 \
+; 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 | FileCheck %s --check-prefix=DIS
+
+; Compile using integrated assembler.
+; RUN: %p2i --filetype=iasm -i %s --target=arm32 --args -Om1 \
+; 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 | FileCheck %s --check-prefix=DIS
+
+define internal i32 @vcmpFloat(float %v1, float %v2) {
+; ASM-LABEL: vcmpFloat:
+; DIS-LABEL: 00000000 <vcmpFloat>:
+; IASM-LABEL: vcmpFloat:
+
+entry:
+; ASM-NEXT: .LvcmpFloat$entry:
+; IASM-NEXT: .LvcmpFloat$entry:
+
+  %cmp = fcmp olt float %v1, %v2
+
+; ASM:      vcmp.f32        s0, s1
+; DIS:   14:      eeb40a60
+; IASM-NOT: vcmp
+
+  %res = zext i1 %cmp to i32
+  ret i32 %res
+}
+
+define internal i32 @vcmpFloatToZero(float %v) {
+; ASM-LABEL: vcmpFloatToZero:
+; DIS-LABEL: 00000040 <vcmpFloatToZero>:
+; IASM-LABEL: vcmpFloatToZero:
+
+entry:
+; ASM-NEXT: .LvcmpFloatToZero$entry:
+; IASM-NEXT: .LvcmpFloatToZero$entry:
+
+  %cmp = fcmp olt float %v, 0.0
+
+; ASM:      vcmp.f32        s0, #0.0
+; DIS:   4c:      eeb50a40
+; IASM-NOT: vcmp
+
+  %res = zext i1 %cmp to i32
+  ret i32 %res
+}
+
+define internal i32 @vcmpDouble(double %v1, double %v2) {
+; ASM-LABEL: vcmpDouble:
+; DIS-LABEL: 00000080 <vcmpDouble>:
+; IASM-LABEL: vcmpDouble:
+
+entry:
+; ASM-NEXT: .LvcmpDouble$entry:
+; IASM-NEXT: .LvcmpDouble$entry:
+
+  %cmp = fcmp olt double %v1, %v2
+
+; ASM:      vcmp.f64        d31, d30
+; DIS:   94:      eef4fb6e
+; IASM-NOT: vcmp
+
+  %res = zext i1 %cmp to i32
+  ret i32 %res
+}
+
+define internal i32 @vcmpDoubleToZero(double %v) {
+; ASM-LABEL: vcmpDoubleToZero:
+; DIS-LABEL: 000000c0 <vcmpDoubleToZero>:
+; IASM-LABEL: vcmpDoubleToZero:
+
+entry:
+; ASM-NEXT: .LvcmpDoubleToZero$entry:
+; IASM-NEXT: .LvcmpDoubleToZero$entry:
+
+  %cmp = fcmp olt double %v, 0.0
+
+; ASM:      vcmp.f64        d31, #0.0
+; DIS:   cc:      eef5fb40
+; IASM-NOT: vcmp
+
+  %res = zext i1 %cmp to i32
+  ret i32 %res
+}