Commit b001cc4c by Sagar Thakur Committed by Jim Stichnoth

[Subzero][MIPS32] Implement bitcast operation for both 32-bit and 64-bit operands

R=stichnot@chromium.org Review URL: https://codereview.chromium.org/2404803002 . Patch from Sagar Thakur <sagar.thakur@imgtec.com>.
parent 46f4feaa
...@@ -283,13 +283,20 @@ InstMIPS32Call::InstMIPS32Call(Cfg *Func, Variable *Dest, Operand *CallTarget) ...@@ -283,13 +283,20 @@ InstMIPS32Call::InstMIPS32Call(Cfg *Func, Variable *Dest, Operand *CallTarget)
addSource(CallTarget); addSource(CallTarget);
} }
InstMIPS32Mov::InstMIPS32Mov(Cfg *Func, Variable *Dest, Operand *Src) InstMIPS32Mov::InstMIPS32Mov(Cfg *Func, Variable *Dest, Operand *Src,
Operand *Src2)
: InstMIPS32(Func, InstMIPS32::Mov, 2, Dest) { : InstMIPS32(Func, InstMIPS32::Mov, 2, Dest) {
auto *Dest64 = llvm::dyn_cast<Variable64On32>(Dest); auto *Dest64 = llvm::dyn_cast<Variable64On32>(Dest);
auto *Src64 = llvm::dyn_cast<Variable64On32>(Src); auto *Src64 = llvm::dyn_cast<Variable64On32>(Src);
assert(Dest64 == nullptr || Src64 == nullptr); assert(Dest64 == nullptr || Src64 == nullptr);
if (Dest->getType() == IceType_f64 && Src2 != nullptr) {
addSource(Src);
addSource(Src2);
return;
}
if (Dest64 != nullptr) { if (Dest64 != nullptr) {
// this-> is needed below because there is a parameter named Dest. // this-> is needed below because there is a parameter named Dest.
this->Dest = Dest64->getLo(); this->Dest = Dest64->getLo();
...@@ -588,110 +595,7 @@ void InstMIPS32Ret::dump(const Cfg *Func) const { ...@@ -588,110 +595,7 @@ void InstMIPS32Ret::dump(const Cfg *Func) const {
void InstMIPS32Mov::emit(const Cfg *Func) const { void InstMIPS32Mov::emit(const Cfg *Func) const {
if (!BuildDefs::dump()) if (!BuildDefs::dump())
return; return;
assert(!(isMultiDest() && isMultiSource()) && "Invalid mov type.");
if (isMultiDest()) {
emitMultiDestSingleSource(Func);
return;
}
if (isMultiSource()) {
emitSingleDestMultiSource(Func);
return;
}
emitSingleDestSingleSource(Func);
}
// TODO(jaydeep.patil) Handle all types of operands in mov
void InstMIPS32Mov::emitIAS(const Cfg *Func) const {
assert(!(isMultiDest() && isMultiSource()) && "Invalid mov type.");
if (isMultiDest()) {
llvm_unreachable("Not yet implemented");
}
if (isMultiSource()) {
llvm_unreachable("Not yet implemented");
}
Variable *Dest = getDest();
Operand *Src = getSrc(0);
auto *SrcV = llvm::dyn_cast<Variable>(Src);
assert(!llvm::isa<Constant>(Src));
const bool DestIsReg = Dest->hasReg();
const bool SrcIsReg = (SrcV && SrcV->hasReg());
// reg to reg
if (DestIsReg && SrcIsReg) {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->move(getDest(), getSrc(0));
return;
}
llvm_unreachable("Not yet implemented");
}
void InstMIPS32Mov::dump(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
assert(getSrcSize() == 1 || getSrcSize() == 2);
Ostream &Str = Func->getContext()->getStrDump();
Variable *Dest = getDest();
Variable *DestHi = getDestHi();
Dest->dump(Func);
if (DestHi) {
Str << ", ";
DestHi->dump(Func);
}
dumpOpcode(Str, " = mov", getDest()->getType());
Str << " ";
dumpSources(Func);
}
void InstMIPS32Mov::emitMultiDestSingleSource(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
Ostream &Str = Func->getContext()->getStrEmit();
Variable *DestLo = getDest();
Variable *DestHi = getDestHi();
auto *Src = llvm::cast<Variable>(getSrc(0));
assert(DestHi->hasReg());
assert(DestLo->hasReg());
assert(llvm::isa<Variable>(Src) && Src->hasReg());
// Str << "\t"
// << "vmov" << getPredicate() << "\t";
DestLo->emit(Func);
Str << ", ";
DestHi->emit(Func);
Str << ", ";
Src->emit(Func);
}
void InstMIPS32Mov::emitSingleDestMultiSource(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
Ostream &Str = Func->getContext()->getStrEmit();
Variable *Dest = getDest();
auto *SrcLo = llvm::cast<Variable>(getSrc(0));
auto *SrcHi = llvm::cast<Variable>(getSrc(1));
assert(SrcHi->hasReg());
assert(SrcLo->hasReg());
assert(Dest->hasReg());
assert(getSrcSize() == 2);
// Str << "\t"
// << "vmov" << getPredicate() << "\t";
Dest->emit(Func);
Str << ", ";
SrcLo->emit(Func);
Str << ", ";
SrcHi->emit(Func);
}
void InstMIPS32Mov::emitSingleDestSingleSource(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
Ostream &Str = Func->getContext()->getStrEmit(); Ostream &Str = Func->getContext()->getStrEmit();
Variable *Dest = getDest(); Variable *Dest = getDest();
Operand *Src = getSrc(0); Operand *Src = getSrc(0);
...@@ -752,6 +656,41 @@ void InstMIPS32Mov::emitSingleDestSingleSource(const Cfg *Func) const { ...@@ -752,6 +656,41 @@ void InstMIPS32Mov::emitSingleDestSingleSource(const Cfg *Func) const {
llvm::report_fatal_error("Invalid mov instruction. Dest or Src is memory."); llvm::report_fatal_error("Invalid mov instruction. Dest or Src is memory.");
} }
// TODO(jaydeep.patil) Handle all types of operands in mov
void InstMIPS32Mov::emitIAS(const Cfg *Func) const {
Variable *Dest = getDest();
Operand *Src = getSrc(0);
auto *SrcV = llvm::dyn_cast<Variable>(Src);
assert(!llvm::isa<Constant>(Src));
const bool DestIsReg = Dest->hasReg();
const bool SrcIsReg = (SrcV && SrcV->hasReg());
// reg to reg
if (DestIsReg && SrcIsReg) {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->move(getDest(), getSrc(0));
return;
}
llvm_unreachable("Not yet implemented");
}
void InstMIPS32Mov::dump(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
assert(getSrcSize() == 1 || getSrcSize() == 2);
Ostream &Str = Func->getContext()->getStrDump();
Variable *Dest = getDest();
Variable *DestHi = getDestHi();
Dest->dump(Func);
if (DestHi) {
Str << ", ";
DestHi->dump(Func);
}
dumpOpcode(Str, " = mov", getDest()->getType());
Str << " ";
dumpSources(Func);
}
template <> void InstMIPS32Abs_d::emitIAS(const Cfg *Func) const { template <> void InstMIPS32Abs_d::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>(); auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Asm->abs_d(getDest(), getSrc(0)); Asm->abs_d(getDest(), getSrc(0));
......
...@@ -1200,12 +1200,14 @@ class InstMIPS32Mov final : public InstMIPS32 { ...@@ -1200,12 +1200,14 @@ class InstMIPS32Mov final : public InstMIPS32 {
InstMIPS32Mov &operator=(const InstMIPS32Mov &) = delete; InstMIPS32Mov &operator=(const InstMIPS32Mov &) = delete;
public: public:
static InstMIPS32Mov *create(Cfg *Func, Variable *Dest, Operand *Src) { static InstMIPS32Mov *create(Cfg *Func, Variable *Dest, Operand *Src,
return new (Func->allocate<InstMIPS32Mov>()) InstMIPS32Mov(Func, Dest, Src); Operand *Src2) {
return new (Func->allocate<InstMIPS32Mov>())
InstMIPS32Mov(Func, Dest, Src, Src2);
} }
bool isRedundantAssign() const override { bool isRedundantAssign() const override {
return !isMultiDest() && !isMultiSource() && return checkForRedundantAssign(getDest(), getSrc(0));
checkForRedundantAssign(getDest(), getSrc(0));
} }
// bool isSimpleAssign() const override { return true; } // bool isSimpleAssign() const override { return true; }
void emit(const Cfg *Func) const override; void emit(const Cfg *Func) const override;
...@@ -1213,17 +1215,10 @@ public: ...@@ -1213,17 +1215,10 @@ public:
void dump(const Cfg *Func) const override; void dump(const Cfg *Func) const override;
static bool classof(const Inst *Inst) { return isClassof(Inst, Mov); } static bool classof(const Inst *Inst) { return isClassof(Inst, Mov); }
bool isMultiDest() const { return DestHi != nullptr; }
bool isMultiSource() const {
assert(getSrcSize() == 1 || getSrcSize() == 2);
return getSrcSize() == 2;
}
Variable *getDestHi() const { return DestHi; } Variable *getDestHi() const { return DestHi; }
private: private:
InstMIPS32Mov(Cfg *Func, Variable *Dest, Operand *Src); InstMIPS32Mov(Cfg *Func, Variable *Dest, Operand *Src, Operand *Src2);
void emitMultiDestSingleSource(const Cfg *Func) const; void emitMultiDestSingleSource(const Cfg *Func) const;
void emitSingleDestMultiSource(const Cfg *Func) const; void emitSingleDestMultiSource(const Cfg *Func) const;
......
...@@ -1546,9 +1546,6 @@ void TargetMIPS32::PostLoweringLegalizer::legalizeMov(InstMIPS32Mov *MovInstr) { ...@@ -1546,9 +1546,6 @@ void TargetMIPS32::PostLoweringLegalizer::legalizeMov(InstMIPS32Mov *MovInstr) {
(void)SrcTy; (void)SrcTy;
assert(SrcTy != IceType_i64); assert(SrcTy != IceType_i64);
if (MovInstr->isMultiDest() || MovInstr->isMultiSource())
return;
bool Legalized = false; bool Legalized = false;
auto *SrcR = llvm::cast<Variable>(Src); auto *SrcR = llvm::cast<Variable>(Src);
if (Dest->hasReg() && SrcR->hasReg()) { if (Dest->hasReg() && SrcR->hasReg()) {
...@@ -1562,16 +1559,26 @@ void TargetMIPS32::PostLoweringLegalizer::legalizeMov(InstMIPS32Mov *MovInstr) { ...@@ -1562,16 +1559,26 @@ void TargetMIPS32::PostLoweringLegalizer::legalizeMov(InstMIPS32Mov *MovInstr) {
if (IsDstGPR != IsSrcGPR) { if (IsDstGPR != IsSrcGPR) {
if (IsDstGPR) { if (IsDstGPR) {
// Dest is GPR and SrcR is FPR. Use mfc1. // Dest is GPR and SrcR is FPR. Use mfc1.
if (typeWidthInBytes(Dest->getType()) == 8) { int32_t TypeWidth = typeWidthInBytes(DestTy);
if (MovInstr->getDestHi() != nullptr)
TypeWidth += typeWidthInBytes(MovInstr->getDestHi()->getType());
if (TypeWidth == 8) {
// Split it into two mfc1 instructions // Split it into two mfc1 instructions
Variable *SrcGPRHi = Target->makeReg( Variable *SrcGPRHi = Target->makeReg(
IceType_f32, RegMIPS32::get64PairFirstRegNum(SRegNum)); IceType_f32, RegMIPS32::get64PairFirstRegNum(SRegNum));
Variable *SrcGPRLo = Target->makeReg( Variable *SrcGPRLo = Target->makeReg(
IceType_f32, RegMIPS32::get64PairSecondRegNum(SRegNum)); IceType_f32, RegMIPS32::get64PairSecondRegNum(SRegNum));
Variable *DstFPRHi = Target->makeReg( Variable *DstFPRHi, *DstFPRLo;
IceType_i32, RegMIPS32::get64PairFirstRegNum(DRegNum)); if (MovInstr->getDestHi() != nullptr && Dest != nullptr) {
Variable *DstFPRLo = Target->makeReg( DstFPRHi = Target->makeReg(IceType_i32,
IceType_i32, RegMIPS32::get64PairSecondRegNum(DRegNum)); MovInstr->getDestHi()->getRegNum());
DstFPRLo = Target->makeReg(IceType_i32, Dest->getRegNum());
} else {
DstFPRHi = Target->makeReg(
IceType_i32, RegMIPS32::get64PairFirstRegNum(DRegNum));
DstFPRLo = Target->makeReg(
IceType_i32, RegMIPS32::get64PairSecondRegNum(DRegNum));
}
Target->_mov(DstFPRHi, SrcGPRLo); Target->_mov(DstFPRHi, SrcGPRLo);
Target->_mov(DstFPRLo, SrcGPRHi); Target->_mov(DstFPRLo, SrcGPRHi);
Legalized = true; Legalized = true;
...@@ -1591,10 +1598,19 @@ void TargetMIPS32::PostLoweringLegalizer::legalizeMov(InstMIPS32Mov *MovInstr) { ...@@ -1591,10 +1598,19 @@ void TargetMIPS32::PostLoweringLegalizer::legalizeMov(InstMIPS32Mov *MovInstr) {
SrcGPRLo = SrcGPRHi; SrcGPRLo = SrcGPRHi;
} else { } else {
// Split it into two mtc1 instructions // Split it into two mtc1 instructions
SrcGPRHi = Target->makeReg( if (MovInstr->getSrcSize() == 2) {
IceType_i32, RegMIPS32::get64PairFirstRegNum(SRegNum)); const auto FirstReg =
SrcGPRLo = Target->makeReg( (llvm::cast<Variable>(MovInstr->getSrc(0)))->getRegNum();
IceType_i32, RegMIPS32::get64PairSecondRegNum(SRegNum)); const auto SecondReg =
(llvm::cast<Variable>(MovInstr->getSrc(1)))->getRegNum();
SrcGPRHi = Target->makeReg(IceType_i32, FirstReg);
SrcGPRLo = Target->makeReg(IceType_i32, SecondReg);
} else {
SrcGPRHi = Target->makeReg(
IceType_i32, RegMIPS32::get64PairFirstRegNum(SRegNum));
SrcGPRLo = Target->makeReg(
IceType_i32, RegMIPS32::get64PairSecondRegNum(SRegNum));
}
} }
Variable *DstFPRHi = Target->makeReg( Variable *DstFPRHi = Target->makeReg(
IceType_f32, RegMIPS32::get64PairFirstRegNum(DRegNum)); IceType_f32, RegMIPS32::get64PairFirstRegNum(DRegNum));
...@@ -1624,7 +1640,12 @@ void TargetMIPS32::PostLoweringLegalizer::legalizeMov(InstMIPS32Mov *MovInstr) { ...@@ -1624,7 +1640,12 @@ void TargetMIPS32::PostLoweringLegalizer::legalizeMov(InstMIPS32Mov *MovInstr) {
auto *SrcR = llvm::cast<Variable>(Src); auto *SrcR = llvm::cast<Variable>(Src);
assert(SrcR->hasReg()); assert(SrcR->hasReg());
assert(!SrcR->isRematerializable()); assert(!SrcR->isRematerializable());
const int32_t Offset = Dest->getStackOffset(); int32_t Offset = 0;
if (MovInstr->getDestHi() != nullptr)
Offset = MovInstr->getDestHi()->getStackOffset();
else
Offset = Dest->getStackOffset();
// This is a _mov(Mem(), Variable), i.e., a store. // This is a _mov(Mem(), Variable), i.e., a store.
auto *Base = Target->getPhysicalRegister(Target->getFrameOrStackReg()); auto *Base = Target->getPhysicalRegister(Target->getFrameOrStackReg());
...@@ -1638,10 +1659,10 @@ void TargetMIPS32::PostLoweringLegalizer::legalizeMov(InstMIPS32Mov *MovInstr) { ...@@ -1638,10 +1659,10 @@ void TargetMIPS32::PostLoweringLegalizer::legalizeMov(InstMIPS32Mov *MovInstr) {
// instead of swc1. // instead of swc1.
const RegNumT RegNum = SrcR->getRegNum(); const RegNumT RegNum = SrcR->getRegNum();
const bool IsSrcGPReg = RegMIPS32::isGPRReg(SrcR->getRegNum()); const bool IsSrcGPReg = RegMIPS32::isGPRReg(SrcR->getRegNum());
if (SrcTy == IceType_f32 && IsSrcGPReg == true) { if (SrcTy == IceType_f32 && IsSrcGPReg) {
Variable *SrcGPR = Target->makeReg(IceType_i32, RegNum); Variable *SrcGPR = Target->makeReg(IceType_i32, RegNum);
Target->_sw(SrcGPR, Addr); Target->_sw(SrcGPR, Addr);
} else if (SrcTy == IceType_f64 && IsSrcGPReg == true) { } else if (SrcTy == IceType_f64 && IsSrcGPReg) {
Variable *SrcGPRHi = Variable *SrcGPRHi =
Target->makeReg(IceType_i32, RegMIPS32::get64PairFirstRegNum(RegNum)); Target->makeReg(IceType_i32, RegMIPS32::get64PairFirstRegNum(RegNum));
Variable *SrcGPRLo = Target->makeReg( Variable *SrcGPRLo = Target->makeReg(
...@@ -1652,6 +1673,19 @@ void TargetMIPS32::PostLoweringLegalizer::legalizeMov(InstMIPS32Mov *MovInstr) { ...@@ -1652,6 +1673,19 @@ void TargetMIPS32::PostLoweringLegalizer::legalizeMov(InstMIPS32Mov *MovInstr) {
Target->Ctx->getConstantInt32(Offset + 4))); Target->Ctx->getConstantInt32(Offset + 4)));
Target->_sw(SrcGPRLo, Addr); Target->_sw(SrcGPRLo, Addr);
Target->_sw(SrcGPRHi, AddrHi); Target->_sw(SrcGPRHi, AddrHi);
} else if (DestTy == IceType_f64 && IsSrcGPReg) {
const auto FirstReg =
(llvm::cast<Variable>(MovInstr->getSrc(0)))->getRegNum();
const auto SecondReg =
(llvm::cast<Variable>(MovInstr->getSrc(1)))->getRegNum();
Variable *SrcGPRHi = Target->makeReg(IceType_i32, SecondReg);
Variable *SrcGPRLo = Target->makeReg(IceType_i32, FirstReg);
OperandMIPS32Mem *AddrHi = OperandMIPS32Mem::create(
Target->Func, DestTy, Base,
llvm::cast<ConstantInteger32>(
Target->Ctx->getConstantInt32(Offset + 4)));
Target->_sw(SrcGPRLo, Addr);
Target->_sw(SrcGPRHi, AddrHi);
} else { } else {
Target->_sw(SrcR, Addr); Target->_sw(SrcR, Addr);
} }
...@@ -3112,6 +3146,38 @@ void TargetMIPS32::lowerCast(const InstCast *Instr) { ...@@ -3112,6 +3146,38 @@ void TargetMIPS32::lowerCast(const InstCast *Instr) {
llvm::report_fatal_error( llvm::report_fatal_error(
"i16 to v16i1 conversion should have been prelowered."); "i16 to v16i1 conversion should have been prelowered.");
break; break;
case IceType_i32:
case IceType_f32: {
Variable *Src0R = legalizeToReg(Src0);
_mov(Dest, Src0R);
break;
}
case IceType_i64: {
assert(Src0->getType() == IceType_f64);
Variable *Src0R = legalizeToReg(Src0);
auto *Dest64 = llvm::cast<Variable64On32>(Dest);
_mov(Dest64, Src0R);
break;
}
case IceType_f64: {
assert(Src0->getType() == IceType_i64);
const uint32_t Mask = 0xFFFFFFFF;
if (auto *C64 = llvm::dyn_cast<ConstantInteger64>(Src0)) {
Variable *RegHi, *RegLo;
const uint64_t Value = C64->getValue();
uint64_t Upper32Bits = (Value >> INT32_BITS) & Mask;
uint64_t Lower32Bits = Value & Mask;
RegLo = legalizeToReg(Ctx->getConstantInt32(Lower32Bits));
RegHi = legalizeToReg(Ctx->getConstantInt32(Upper32Bits));
_mov(Dest, RegHi, RegLo);
} else {
auto *Var64On32 = llvm::cast<Variable64On32>(Src0);
auto *RegLo = legalizeToReg(loOperand(Var64On32));
auto *RegHi = legalizeToReg(hiOperand(Var64On32));
_mov(Dest, RegHi, RegLo);
}
break;
}
case IceType_v8i1: case IceType_v8i1:
assert(Src0->getType() == IceType_i8); assert(Src0->getType() == IceType_i8);
llvm::report_fatal_error( llvm::report_fatal_error(
......
...@@ -341,15 +341,15 @@ public: ...@@ -341,15 +341,15 @@ public:
Context.insert<InstMIPS32Mflo>(Dest, Src); Context.insert<InstMIPS32Mflo>(Dest, Src);
} }
void _mov(Variable *Dest, Operand *Src0) { void _mov(Variable *Dest, Operand *Src0, Operand *Src1 = nullptr) {
assert(Dest != nullptr); assert(Dest != nullptr);
// Variable* Src0_ = llvm::dyn_cast<Variable>(Src0); // Variable* Src0_ = llvm::dyn_cast<Variable>(Src0);
if (llvm::isa<ConstantRelocatable>(Src0)) { if (llvm::isa<ConstantRelocatable>(Src0)) {
Context.insert<InstMIPS32La>(Dest, Src0); Context.insert<InstMIPS32La>(Dest, Src0);
} else { } else {
auto *Instr = Context.insert<InstMIPS32Mov>(Dest, Src0); auto *Instr = Context.insert<InstMIPS32Mov>(Dest, Src0, Src1);
if (Instr->isMultiDest()) { if (Instr->getDestHi() != nullptr) {
// If Instr is multi-dest, then Dest must be a Variable64On32. We add a // If DestHi is available, then Dest must be a Variable64On32. We add a
// fake-def for Instr.DestHi here. // fake-def for Instr.DestHi here.
assert(llvm::isa<Variable64On32>(Dest)); assert(llvm::isa<Variable64On32>(Dest));
Context.insert<InstFakeDef>(Instr->getDestHi()); Context.insert<InstFakeDef>(Instr->getDestHi());
......
...@@ -13,6 +13,20 @@ ...@@ -13,6 +13,20 @@
; RUN: | %if --need=target_ARM32 --command FileCheck %s \ ; RUN: | %if --need=target_ARM32 --command FileCheck %s \
; RUN: --check-prefix=ARM32 ; RUN: --check-prefix=ARM32
; RUN: %if --need=target_MIPS32 --need=allow_dump \
; RUN: --command %p2i --filetype=asm \
; RUN: --target mips32 -i %s --args -O2 \
; RUN: | %if --need=target_MIPS32 --need=allow_dump \
; RUN: --command FileCheck %s \
; RUN: --check-prefix=MIPS32 --check-prefix=MIPS32-O2
; RUN: %if --need=target_MIPS32 --need=allow_dump \
; RUN: --command %p2i --filetype=asm \
; RUN: --target mips32 -i %s --args -Om1 \
; RUN: | %if --need=target_MIPS32 --need=allow_dump \
; RUN: --command FileCheck %s \
; RUN: --check-prefix=MIPS32 --check-prefix=MIPS32-OM1
define internal i32 @cast_f2i(float %f) { define internal i32 @cast_f2i(float %f) {
entry: entry:
%v0 = bitcast float %f to i32 %v0 = bitcast float %f to i32
...@@ -22,6 +36,10 @@ entry: ...@@ -22,6 +36,10 @@ entry:
; CHECK: movd eax ; CHECK: movd eax
; ARM32-LABEL: cast_f2i ; ARM32-LABEL: cast_f2i
; ARM32: vmov r{{[0-9]+}}, s{{[0-9]+}} ; ARM32: vmov r{{[0-9]+}}, s{{[0-9]+}}
; MIPS32-LABEL: cast_f2i
; MIPS32-O2: mfc1 $v0, $f{{[0-9]+}}
; MIPS32-OM1: swc1
; MIPS32-OM1: lw
define internal float @cast_i2f(i32 %i) { define internal float @cast_i2f(i32 %i) {
entry: entry:
...@@ -32,6 +50,10 @@ entry: ...@@ -32,6 +50,10 @@ entry:
; CHECK: fld DWORD PTR ; CHECK: fld DWORD PTR
; ARM32-LABEL: cast_i2f ; ARM32-LABEL: cast_i2f
; ARM32: vmov s{{[0-9]+}}, r{{[0-9]+}} ; ARM32: vmov s{{[0-9]+}}, r{{[0-9]+}}
; MIPS32-LABEL: cast_i2f
; MIPS32-O2: mtc1 $a0, $f{{[0-9]+}}
; MIPS32-OM1: sw
; MIPS32-OM1: lwc1
define internal i64 @cast_d2ll(double %d) { define internal i64 @cast_d2ll(double %d) {
entry: entry:
...@@ -42,6 +64,12 @@ entry: ...@@ -42,6 +64,12 @@ entry:
; CHECK: mov edx ; CHECK: mov edx
; ARM32-LABEL: cast_d2ll ; ARM32-LABEL: cast_d2ll
; ARM32: vmov r{{[0-9]+}}, r{{[0-9]+}}, d{{[0-9]+}} ; ARM32: vmov r{{[0-9]+}}, r{{[0-9]+}}, d{{[0-9]+}}
; MIPS32-LABEL: cast_d2ll
; MIPS32-O2: mfc1 $v1, $f{{[0-9]+}}
; MIPS32-O2: mfc1 $v0, $f{{[0-9]+}}
; MIPS32-OM1: sdc1
; MIPS32-OM1: lw
; MIPS32-OM1: lw
define internal i64 @cast_d2ll_const() { define internal i64 @cast_d2ll_const() {
entry: entry:
...@@ -56,6 +84,14 @@ entry: ...@@ -56,6 +84,14 @@ entry:
; ARM32-DAG: movt [[ADDR]], #{{.*_MOVT_}} ; ARM32-DAG: movt [[ADDR]], #{{.*_MOVT_}}
; ARM32-DAG: vldr [[DREG:d[0-9]+]], {{\[}}[[ADDR]]{{\]}} ; ARM32-DAG: vldr [[DREG:d[0-9]+]], {{\[}}[[ADDR]]{{\]}}
; ARM32: vmov r{{[0-9]+}}, r{{[0-9]+}}, [[DREG]] ; ARM32: vmov r{{[0-9]+}}, r{{[0-9]+}}, [[DREG]]
; MIPS32-LABEL: cast_d2ll_const
; MIPS32: lui {{.*}}, %hi(.L$double$0012345678901234)
; MIPS32: ldc1 {{.*}}, %lo(.L$double$0012345678901234)({{.*}})
; MIPS32-O2: mfc1 $v1, $f{{[0-9]+}}
; MIPS32-O2: mfc1 $v0, $f{{[0-9]+}}
; MIPS32-OM1: sdc1
; MIPS32-OM1: lw
; MIPS32-OM1: lw
define internal double @cast_ll2d(i64 %ll) { define internal double @cast_ll2d(i64 %ll) {
entry: entry:
...@@ -66,6 +102,12 @@ entry: ...@@ -66,6 +102,12 @@ entry:
; CHECK: fld QWORD PTR ; CHECK: fld QWORD PTR
; ARM32-LABEL: cast_ll2d ; ARM32-LABEL: cast_ll2d
; ARM32: vmov d{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}} ; ARM32: vmov d{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}
; MIPS32-LABEL: cast_ll2d
; MIPS32-O2: mtc1 $a0, $f{{[0-9]+}}
; MIPS32-O2: mtc1 $a1, $f{{[0-9]+}}
; MIPS32-OM1: sw
; MIPS32-OM1: sw
; MIPS32-OM1: ldc1
define internal double @cast_ll2d_const() { define internal double @cast_ll2d_const() {
entry: entry:
...@@ -81,3 +123,12 @@ entry: ...@@ -81,3 +123,12 @@ entry:
; ARM32-DAG: movt [[REG0:r[0-9]+]], #29646 ; ARM32-DAG: movt [[REG0:r[0-9]+]], #29646
; ARM32-DAG: movw [[REG1:r[0-9]+]], #2874 ; ARM32-DAG: movw [[REG1:r[0-9]+]], #2874
; ARM32: vmov d{{[0-9]+}}, [[REG0]], [[REG1]] ; ARM32: vmov d{{[0-9]+}}, [[REG0]], [[REG1]]
; MIPS32-LABEL: cast_ll2d_const
; MIPS32: lui {{.*}}, 29646
; MIPS32: ori {{.*}}, {{.*}}, 12274
; MIPS32: addiu {{.*}}, $zero, 2874
; MIPS32-O2: mtc1 {{.*}}, $f{{[0-9]+}}
; MIPS32-O2: mtc1 {{.*}}, $f{{[0-9]+}}
; MIPS32-OM1: sw
; MIPS32-OM1: sw
; MIPS32-OM1: ldc1
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