diff options
author | Vasileios Kalintiris <Vasileios.Kalintiris@imgtec.com> | 2015-04-27 13:28:05 +0000 |
---|---|---|
committer | Vasileios Kalintiris <Vasileios.Kalintiris@imgtec.com> | 2015-04-27 13:28:05 +0000 |
commit | 7a6b18783f771d1cf721f87a11ddf65da0491ed4 (patch) | |
tree | 53e42656302a1cad0feb8c4a2cb03bf02f9489e5 /llvm/lib/Target | |
parent | b19cf2082f1d6803d50252b40b099ed2a02b14df (diff) | |
download | bcm5719-llvm-7a6b18783f771d1cf721f87a11ddf65da0491ed4.tar.gz bcm5719-llvm-7a6b18783f771d1cf721f87a11ddf65da0491ed4.zip |
Reapply "[mips][FastISel] Implement shift ops for Mips fast-isel.""
This reapplies r235194, which was reverted in r235495 because it was causing a
failure in our out-of-tree buildbots for MIPS. With the sign-extension patch
in r235718, this patch doesn't cause any problem any more.
llvm-svn: 235878
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r-- | llvm/lib/Target/Mips/MipsFastISel.cpp | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/llvm/lib/Target/Mips/MipsFastISel.cpp b/llvm/lib/Target/Mips/MipsFastISel.cpp index 265f6de06cb..ab44d33cecf 100644 --- a/llvm/lib/Target/Mips/MipsFastISel.cpp +++ b/llvm/lib/Target/Mips/MipsFastISel.cpp @@ -100,6 +100,7 @@ private: bool selectRet(const Instruction *I); bool selectTrunc(const Instruction *I); bool selectIntExt(const Instruction *I); + bool selectShift(const Instruction *I); // Utility helper routines. bool isTypeLegal(Type *Ty, MVT &VT); @@ -1413,6 +1414,81 @@ unsigned MipsFastISel::emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, return Success ? DestReg : 0; } +bool MipsFastISel::selectShift(const Instruction *I) { + MVT RetVT; + + if (!isTypeSupported(I->getType(), RetVT)) + return false; + + unsigned ResultReg = createResultReg(&Mips::GPR32RegClass); + if (!ResultReg) + return false; + + unsigned Opcode = I->getOpcode(); + const Value *Op0 = I->getOperand(0); + unsigned Op0Reg = getRegForValue(Op0); + if (!Op0Reg) + return false; + + // If AShr or LShr, then we need to make sure the operand0 is sign extended. + if (Opcode == Instruction::AShr || Opcode == Instruction::LShr) { + unsigned TempReg = createResultReg(&Mips::GPR32RegClass); + if (!TempReg) + return false; + + MVT Op0MVT = TLI.getValueType(Op0->getType(), true).getSimpleVT(); + bool IsZExt = Opcode == Instruction::LShr; + if (!emitIntExt(Op0MVT, Op0Reg, MVT::i32, TempReg, IsZExt)) + return false; + + Op0Reg = TempReg; + } + + if (const auto *C = dyn_cast<ConstantInt>(I->getOperand(1))) { + uint64_t ShiftVal = C->getZExtValue(); + + switch (Opcode) { + default: + llvm_unreachable("Unexpected instruction."); + case Instruction::Shl: + Opcode = Mips::SLL; + break; + case Instruction::AShr: + Opcode = Mips::SRA; + break; + case Instruction::LShr: + Opcode = Mips::SRL; + break; + } + + emitInst(Opcode, ResultReg).addReg(Op0Reg).addImm(ShiftVal); + updateValueMap(I, ResultReg); + return true; + } + + unsigned Op1Reg = getRegForValue(I->getOperand(1)); + if (!Op1Reg) + return false; + + switch (Opcode) { + default: + llvm_unreachable("Unexpected instruction."); + case Instruction::Shl: + Opcode = Mips::SLLV; + break; + case Instruction::AShr: + Opcode = Mips::SRAV; + break; + case Instruction::LShr: + Opcode = Mips::SRLV; + break; + } + + emitInst(Opcode, ResultReg).addReg(Op0Reg).addReg(Op1Reg); + updateValueMap(I, ResultReg); + return true; +} + bool MipsFastISel::fastSelectInstruction(const Instruction *I) { if (!TargetSupported) return false; @@ -1423,6 +1499,10 @@ bool MipsFastISel::fastSelectInstruction(const Instruction *I) { return selectLoad(I); case Instruction::Store: return selectStore(I); + case Instruction::Shl: + case Instruction::LShr: + case Instruction::AShr: + return selectShift(I); case Instruction::And: case Instruction::Or: case Instruction::Xor: |