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)
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 {
}
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);
}
#include "IceUtils.h"
#include "llvm/Support/MathExtras.h"
+#include <algorithm>
+
namespace Ice {
namespace {
}
}
+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)
private:
~TargetDataARM32() override = default;
- template <typename T> static void emitConstantPool(GlobalContext *Ctx);
};
class TargetHeaderARM32 final : public TargetHeaderLowering {
; 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.
; CHECK-LABEL: fold_cmp_br
; CHECK: cmp
; CHECK: jge
+; ARM32-LABEL: fold_cmp_br
+; ARM32: cmp
+; ARM32: beq
; Cmp/branch folding with intervening instructions.
; 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.
; 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.
; 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.
; 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.
; 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:
; 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) {
; 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.
; 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.
; 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) {
; 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