OSDN Git Service

Subzero. Implements TargetDataARM32::lowerConstants.
authorJohn Porto <jpp@chromium.org>
Fri, 18 Sep 2015 15:43:02 +0000 (08:43 -0700)
committerJohn Porto <jpp@chromium.org>
Fri, 18 Sep 2015 15:43:02 +0000 (08:43 -0700)
BUG= https://code.google.com/p/nativeclient/issues/detail?id=4076
R=stichnot@chromium.org

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

src/IceCfg.cpp
src/IceOperand.h
src/IceTargetLoweringARM32.cpp
src/IceTargetLoweringARM32.h
tests_lit/llvm2ice_tests/bool-folding.ll

index 7b1b9af..330f638 100644 (file)
@@ -75,8 +75,7 @@ void Cfg::swapNodes(NodeList &NewNodes) {
     Nodes[I]->resetIndex(I);
 }
 
-template <>
-Variable *Cfg::makeVariable<Variable>(Type Ty) {
+template <> Variable *Cfg::makeVariable<Variable>(Type Ty) {
   SizeT Index = Variables.size();
   Variable *Var = Target->shouldSplitToVariable64On32(Ty)
                       ? Variable64On32::create(this, Ty, Index)
index 664ce1e..f624641 100644 (file)
@@ -545,8 +545,8 @@ class Variable64On32 : public Variable {
 
 public:
   static Variable64On32 *create(Cfg *Func, Type Ty, SizeT Index) {
-    return new (Func->allocate<Variable64On32>()) Variable64On32(
-        kVariable64On32, Ty, Index);
+    return new (Func->allocate<Variable64On32>())
+        Variable64On32(kVariable64On32, Ty, Index);
   }
 
   void setName(Cfg *Func, const IceString &NewName) override {
@@ -591,8 +591,7 @@ public:
   }
 
 protected:
-  Variable64On32(OperandKind K, Type Ty, SizeT Index)
-      : Variable(K, Ty, Index) {
+  Variable64On32(OperandKind K, Type Ty, SizeT Index) : Variable(K, Ty, Index) {
     assert(typeWidthInBytes(Ty) == 8);
   }
 
index 682048a..3fb5efc 100644 (file)
@@ -29,6 +29,8 @@
 #include "IceUtils.h"
 #include "llvm/Support/MathExtras.h"
 
+#include <algorithm>
+
 namespace Ice {
 
 namespace {
@@ -3112,16 +3114,125 @@ void TargetDataARM32::lowerGlobals(const VariableDeclarationList &Vars,
   }
 }
 
+namespace {
+template <typename T> struct ConstantPoolEmitterTraits;
+
+static_assert(sizeof(uint64_t) == 8,
+              "uint64_t is supposed to be 8 bytes wide.");
+
+// TODO(jpp): implement the following when implementing constant randomization:
+//  * template <> struct ConstantPoolEmitterTraits<uint8_t>
+//  * template <> struct ConstantPoolEmitterTraits<uint16_t>
+//  * template <> struct ConstantPoolEmitterTraits<uint32_t>
+template <> struct ConstantPoolEmitterTraits<float> {
+  using ConstantType = ConstantFloat;
+  static constexpr Type IceType = IceType_f32;
+  // AsmTag and TypeName can't be constexpr because llvm::StringRef is unhappy
+  // about them being constexpr.
+  static const char AsmTag[];
+  static const char TypeName[];
+  static uint64_t bitcastToUint64(float Value) {
+    static_assert(sizeof(Value) == sizeof(uint32_t),
+                  "Float should be 4 bytes.");
+    uint32_t IntValue = *reinterpret_cast<uint32_t *>(&Value);
+    return static_cast<uint64_t>(IntValue);
+  }
+};
+const char ConstantPoolEmitterTraits<float>::AsmTag[] = ".long";
+const char ConstantPoolEmitterTraits<float>::TypeName[] = "f32";
+
+template <> struct ConstantPoolEmitterTraits<double> {
+  using ConstantType = ConstantDouble;
+  static constexpr Type IceType = IceType_f64;
+  static const char AsmTag[];
+  static const char TypeName[];
+  static uint64_t bitcastToUint64(double Value) {
+    static_assert(sizeof(double) == sizeof(uint64_t),
+                  "Double should be 8 bytes.");
+    return *reinterpret_cast<uint64_t *>(&Value);
+  }
+};
+const char ConstantPoolEmitterTraits<double>::AsmTag[] = ".quad";
+const char ConstantPoolEmitterTraits<double>::TypeName[] = "f64";
+
+template <typename T>
+void emitConstant(
+    Ostream &Str,
+    const typename ConstantPoolEmitterTraits<T>::ConstantType *Const) {
+  using Traits = ConstantPoolEmitterTraits<T>;
+  Const->emitPoolLabel(Str);
+  Str << ":\n\t" << Traits::AsmTag << "\t0x";
+  T Value = Const->getValue();
+  Str.write_hex(Traits::bitcastToUint64(Value));
+  Str << "\t@" << Traits::TypeName << " " << Value << "\n";
+}
+
+template <typename T> void emitConstantPool(GlobalContext *Ctx) {
+  if (!BuildDefs::dump()) {
+    return;
+  }
+
+  using Traits = ConstantPoolEmitterTraits<T>;
+  static constexpr size_t MinimumAlignment = 4;
+  SizeT Align = std::max(MinimumAlignment, typeAlignInBytes(Traits::IceType));
+  assert((Align % 4) == 0 && "Constants should be aligned");
+  Ostream &Str = Ctx->getStrEmit();
+  ConstantList Pool = Ctx->getConstantPool(Traits::IceType);
+
+  Str << "\t.section\t.rodata.cst" << Align << ",\"aM\",%progbits," << Align
+      << "\n"
+      << "\t.align\t" << Align << "\n";
+
+  if (Ctx->getFlags().shouldReorderPooledConstants()) {
+    // TODO(jpp): add constant pooling.
+    UnimplementedError(Ctx->getFlags());
+  }
+
+  for (Constant *C : Pool) {
+    if (!C->getShouldBePooled()) {
+      continue;
+    }
+
+    emitConstant<T>(Str, llvm::dyn_cast<typename Traits::ConstantType>(C));
+  }
+}
+} // end of anonymous namespace
+
 void TargetDataARM32::lowerConstants() {
   if (Ctx->getFlags().getDisableTranslation())
     return;
-  UnimplementedError(Ctx->getFlags());
+  switch (Ctx->getFlags().getOutFileType()) {
+  case FT_Elf:
+    UnimplementedError(Ctx->getFlags());
+    break;
+  case FT_Asm: {
+    OstreamLocker L(Ctx);
+    emitConstantPool<float>(Ctx);
+    emitConstantPool<double>(Ctx);
+    break;
+  }
+  case FT_Iasm: {
+    UnimplementedError(Ctx->getFlags());
+    break;
+  }
+  }
 }
 
 void TargetDataARM32::lowerJumpTables() {
   if (Ctx->getFlags().getDisableTranslation())
     return;
-  UnimplementedError(Ctx->getFlags());
+  switch (Ctx->getFlags().getOutFileType()) {
+  case FT_Elf:
+    UnimplementedError(Ctx->getFlags());
+    break;
+  case FT_Asm:
+    // Already emitted from Cfg
+    break;
+  case FT_Iasm: {
+    UnimplementedError(Ctx->getFlags());
+    break;
+  }
+  }
 }
 
 TargetHeaderARM32::TargetHeaderARM32(GlobalContext *Ctx)
index 996b283..0071de2 100644 (file)
@@ -533,7 +533,6 @@ protected:
 
 private:
   ~TargetDataARM32() override = default;
-  template <typename T> static void emitConstantPool(GlobalContext *Ctx);
 };
 
 class TargetHeaderARM32 final : public TargetHeaderLowering {
index 13ee8c4..584c797 100644 (file)
@@ -4,6 +4,11 @@
 
 ; RUN: %p2i -i %s --filetype=obj --disassemble --args -O2 | FileCheck %s
 
+; RUN: %if --need=allow_dump --need=target_ARM32 --command %p2i --filetype=asm \
+; RUN:   --target arm32 -i %s --args -O2 --skip-unimplemented \
+; RUN:   | %if --need=allow_dump --need=target_ARM32 --command FileCheck %s \
+; RUN:   --check-prefix=ARM32
+
 declare void @use_value(i32)
 
 ; Basic cmp/branch folding.
@@ -20,6 +25,9 @@ branch2:
 ; CHECK-LABEL: fold_cmp_br
 ; CHECK: cmp
 ; CHECK: jge
+; ARM32-LABEL: fold_cmp_br
+; ARM32: cmp
+; ARM32: beq
 
 
 ; Cmp/branch folding with intervening instructions.
@@ -39,6 +47,13 @@ branch2:
 ; CHECK: call
 ; CHECK: cmp
 ; CHECK: jge
+; ARM32-LABEL: fold_cmp_br_intervening_insts
+; ARM32: push {{[{].*[}]}}
+; ARM32: movlt [[TMP:r[0-9]+]], #1
+; ARM32: mov [[P:r[4-7]]], [[TMP]]
+; ARM32: bl
+; ARM32: cmp [[P]], #0
+; ARM32: beq
 
 
 ; Cmp/branch non-folding because of live-out.
@@ -59,6 +74,11 @@ branch2:
 ; CHECK: set
 ; CHECK: cmp
 ; CHECK: je
+; ARM32-LABEL: no_fold_cmp_br_liveout
+; ARM32: cmp
+; ARM32: movlt [[REG:r[0-9]+]]
+; ARM32: cmp [[REG]], #0
+; ARM32: beq
 
 
 ; Cmp/branch non-folding because of extra non-whitelisted uses.
@@ -79,6 +99,14 @@ branch2:
 ; CHECK: movzx
 ; CHECK: cmp
 ; CHECK: je
+; ARM32-LABEL: no_fold_cmp_br_non_whitelist
+; ARM32: mov [[R:r[0-9]+]], #0
+; ARM32: cmp r0, r1
+; ARM32: movlt [[R]], #1
+; ARM32: mov [[R2:r[0-9]+]], [[R]]
+; ARM32: and [[R3:r[0-9]+]], [[R2]], #1
+; ARM32: cmp [[R]]
+; ARM32: beq
 
 
 ; Basic cmp/select folding.
@@ -92,6 +120,11 @@ entry:
 ; CHECK-LABEL: fold_cmp_select
 ; CHECK: cmp
 ; CHECK: cmovl
+; ARM32-LABEL: fold_cmp_select
+; ARM32: mov [[R:r[0-9]+]], #0
+; ARM32: cmp r0, r1
+; ARM32: movlt [[R]], #1
+; ARM32: cmp [[R]], #0
 
 
 ; 64-bit cmp/select folding.
@@ -108,6 +141,17 @@ entry:
 ; CHECK: cmp
 ; CHECK: cmovl
 ; CHECK: cmovl
+; ARM32-LABEL: fold_cmp_select_64
+; ARM32: mov [[R:r[0-9]+]], #0
+; ARM32: cmp r0, r2
+; ARM32: movlt [[R]], #1
+; ARM32: cmp [[R]], #0
+; ARM32: movne
+; ARM32: movne
+; ARM32-DAG: mov r0
+; ARM32-DAG: mov r1
+; ARM32: bx lr
+
 
 define i64 @fold_cmp_select_64_undef(i64 %arg1) {
 entry:
@@ -120,6 +164,16 @@ entry:
 ; CHECK: cmp
 ; CHECK: cmovl
 ; CHECK: cmovl
+; ARM32-LABEL: fold_cmp_select_64_undef
+; ARM32: cmp {{r[0-9]+}}, r0
+; ARM32: movlt [[R:r[0-9]+]], #1
+; ARM32: cmp [[R]]
+; ARM32: movne
+; ARM32: movne
+; ARM32-DAG: mov r0
+; ARM32-DAG: mov r1
+; ARM32: bx lr
+
 
 ; Cmp/select folding with intervening instructions.
 define i32 @fold_cmp_select_intervening_insts(i32 %arg1, i32 %arg2) {
@@ -135,6 +189,17 @@ entry:
 ; CHECK: call
 ; CHECK: cmp
 ; CHECK: cmovl
+; ARM32-LABEL: fold_cmp_select_intervening_insts
+; ARM32: mov [[RES0:r[4-7]+]], r0
+; ARM32: mov [[RES1:r[4-7]+]], r1
+; ARM32: mov [[R:r[0-9]+]], #0
+; ARM32: cmp r{{[0-9]+}}, r{{[0-9]+}}
+; ARM32: movlt [[R]], #1
+; ARM32: mov [[R2:r[4-7]]], [[R]]
+; ARM32: bl use_value
+; ARM32: cmp [[R2]], #0
+; ARM32: movne [[RES1]], [[RES0]]
+; ARM32: mov r0, [[RES1]]
 
 
 ; Cmp/multi-select folding.
@@ -158,6 +223,21 @@ entry:
 ; CHECK: cmovge
 ; CHECK: add
 ; CHECK: add
+; ARM32-LABEL: fold_cmp_select_multi
+; ARM32-DAG: mov [[T0:r[0-9]+]], #0
+; ARM32-DAG: cmp r0, r1
+; ARM32: movlt [[T0]], #1
+; ARM32-DAG: mov [[T1:r[0-9]+]], r1
+; ARM32-DAG: cmp [[T0]], #0
+; ARM32: [[T1]], r0
+; ARM32-DAG: mov [[T2:r[0-9]+]], r0
+; ARM32-DAG: cmp [[T0]], #0
+; ARM32: [[T2]], r1
+; ARM32: cmp [[T0]], #0
+; ARM32: movne
+; ARM32: add
+; ARM32: add
+; ARM32: bx lr
 
 
 ; Cmp/multi-select non-folding because of live-out.
@@ -184,7 +264,22 @@ next:
 ; CHECK: cmove
 ; CHECK: add
 ; CHECK: add
-
+; ARM32-LABEL: no_fold_cmp_select_multi_liveout
+; ARM32-LABEL: fold_cmp_select_multi
+; ARM32-DAG: mov [[T0:r[0-9]+]], #0
+; ARM32-DAG: cmp r0, r1
+; ARM32: movlt [[T0]], #1
+; ARM32-DAG: mov [[T1:r[0-9]+]], r1
+; ARM32-DAG: cmp [[T0]], #0
+; ARM32: [[T1]], r0
+; ARM32-DAG: mov [[T2:r[0-9]+]], r0
+; ARM32-DAG: cmp [[T0]], #0
+; ARM32: [[T2]], r1
+; ARM32: cmp [[T0]], #0
+; ARM32: movne
+; ARM32: add
+; ARM32: add
+; ARM32: bx lr
 
 ; Cmp/multi-select non-folding because of extra non-whitelisted uses.
 define i32 @no_fold_cmp_select_multi_non_whitelist(i32 %arg1, i32 %arg2) {
@@ -212,3 +307,20 @@ entry:
 ; CHECK: add
 ; CHECK: add
 ; CHECK: add
+; ARM32-LABEL: no_fold_cmp_select_multi_non_whitelist
+; ARM32-DAG: mov [[T0:r[0-9]+]], #0
+; ARM32-DAG: cmp r0, r1
+; ARM32: movlt [[T0]], #1
+; ARM32-DAG: mov [[T1:r[0-9]+]], r1
+; ARM32-DAG: cmp [[T0]], #0
+; ARM32: [[T1]], r0
+; ARM32-DAG: mov [[T2:r[0-9]+]], r0
+; ARM32-DAG: cmp [[T0]], #0
+; ARM32: [[T2]], r1
+; ARM32: cmp [[T0]], #0
+; ARM32: movne
+; ARM32: and {{.*}}, [[T0]], #1
+; ARM32: add
+; ARM32: add
+; ARM32: add
+; ARM32: bx lr