Index: src/IceTargetLoweringMIPS32.cpp |
diff --git a/src/IceTargetLoweringMIPS32.cpp b/src/IceTargetLoweringMIPS32.cpp |
index c4b602463f20af75a03df68d14f4f43a92998fa5..942429998f749ef259c1fb5966d1d09392f182c5 100644 |
--- a/src/IceTargetLoweringMIPS32.cpp |
+++ b/src/IceTargetLoweringMIPS32.cpp |
@@ -1485,12 +1485,19 @@ void TargetMIPS32::PostLoweringLegalizer::legalizeMov(InstMIPS32Mov *MovInstr) { |
} |
} else { |
// Dest is FPR and SrcR is GPR. Use mtc1. |
- if (typeWidthInBytes(SrcR->getType()) == 8) { |
- // Split it into two mtc1 instructions |
- Variable *SrcGPRHi = Target->makeReg( |
- IceType_i32, RegMIPS32::get64PairFirstRegNum(SRegNum)); |
- Variable *SrcGPRLo = Target->makeReg( |
- IceType_i32, RegMIPS32::get64PairSecondRegNum(SRegNum)); |
+ if (typeWidthInBytes(Dest->getType()) == 8) { |
+ Variable *SrcGPRHi, *SrcGPRLo; |
+ // SrcR could be $zero which is i32 |
+ if (SRegNum == RegMIPS32::Reg_ZERO) { |
+ SrcGPRHi = Target->makeReg(IceType_i32, SRegNum); |
+ SrcGPRLo = SrcGPRHi; |
+ } else { |
+ // Split it into two mtc1 instructions |
+ SrcGPRHi = Target->makeReg( |
+ IceType_i32, RegMIPS32::get64PairFirstRegNum(SRegNum)); |
+ SrcGPRLo = Target->makeReg( |
+ IceType_i32, RegMIPS32::get64PairSecondRegNum(SRegNum)); |
+ } |
Variable *DstFPRHi = Target->makeReg( |
IceType_f32, RegMIPS32::get64PairFirstRegNum(DRegNum)); |
Variable *DstFPRLo = Target->makeReg( |
@@ -3421,9 +3428,104 @@ void TargetDataMIPS32::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(jaydeep.patil): 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."); |
+ const uint32_t IntValue = Utils::bitCopy<uint32_t>(Value); |
+ return static_cast<uint64_t>(IntValue); |
+ } |
+}; |
+const char ConstantPoolEmitterTraits<float>::AsmTag[] = ".word"; |
+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 Utils::bitCopy<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) { |
+ if (!BuildDefs::dump()) |
+ return; |
+ using Traits = ConstantPoolEmitterTraits<T>; |
+ Str << Const->getLabelName(); |
+ T Value = Const->getValue(); |
+ Str << ":\n\t" << Traits::AsmTag << "\t0x"; |
+ 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 == 4 ? 2 : 3) << "\n"; |
+ if (getFlags().getReorderPooledConstants()) { |
+ // TODO(jaydeep.patil): add constant pooling. |
+ UnimplementedError(getFlags()); |
+ } |
+ for (Constant *C : Pool) { |
+ if (!C->getShouldBePooled()) { |
+ continue; |
+ } |
+ emitConstant<T>(Str, llvm::dyn_cast<typename Traits::ConstantType>(C)); |
+ } |
+} |
+} // end of anonymous namespace |
+ |
void TargetDataMIPS32::lowerConstants() { |
if (getFlags().getDisableTranslation()) |
return; |
+ switch (getFlags().getOutFileType()) { |
+ case FT_Elf: { |
+ ELFObjectWriter *Writer = Ctx->getObjectWriter(); |
+ Writer->writeConstantPool<ConstantFloat>(IceType_f32); |
+ Writer->writeConstantPool<ConstantDouble>(IceType_f64); |
+ } break; |
+ case FT_Asm: |
+ case FT_Iasm: { |
+ OstreamLocker _(Ctx); |
+ emitConstantPool<float>(Ctx); |
+ emitConstantPool<double>(Ctx); |
+ break; |
+ } |
+ } |
} |
void TargetDataMIPS32::lowerJumpTables() { |
@@ -3545,21 +3647,25 @@ Operand *TargetMIPS32::legalize(Operand *From, LegalMask Allowed, |
} |
return Reg; |
} else if (isScalarFloatingType(Ty)) { |
- // Load floats/doubles from literal pool. |
auto *CFrom = llvm::cast<Constant>(From); |
- assert(CFrom->getShouldBePooled()); |
- Constant *Offset = Ctx->getConstantSym(0, CFrom->getLabelName()); |
- Variable *TReg1 = makeReg(getPointerType()); |
- Variable *TReg2 = makeReg(Ty); |
- Context.insert<InstFakeDef>(TReg2); |
- _lui(TReg1, Offset, RO_Hi); |
- OperandMIPS32Mem *Addr = |
- OperandMIPS32Mem::create(Func, Ty, TReg1, Offset); |
- if (Ty == IceType_f32) |
- _lwc1(TReg2, Addr, RO_Lo); |
- else |
- _ldc1(TReg2, Addr, RO_Lo); |
- return copyToReg(TReg2, RegNum); |
+ Variable *TReg = makeReg(Ty); |
+ if (!CFrom->getShouldBePooled()) { |
+ // Float/Double constant 0 is not pooled. |
+ Context.insert<InstFakeDef>(TReg); |
+ _mov(TReg, getZero()); |
+ } else { |
+ // Load floats/doubles from literal pool. |
+ Constant *Offset = Ctx->getConstantSym(0, CFrom->getLabelName()); |
+ Variable *TReg1 = makeReg(getPointerType()); |
+ _lui(TReg1, Offset, RO_Hi); |
+ OperandMIPS32Mem *Addr = |
+ OperandMIPS32Mem::create(Func, Ty, TReg1, Offset); |
+ if (Ty == IceType_f32) |
+ _lwc1(TReg, Addr, RO_Lo); |
+ else |
+ _ldc1(TReg, Addr, RO_Lo); |
+ } |
+ return copyToReg(TReg, RegNum); |
} |
} |