Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Unified Diff: src/IceTargetLoweringMIPS32.cpp

Issue 1416493002: Implements simple returns and call args for Mips. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Corrections to patch set 3 per stichnot review Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/IceTargetLoweringMIPS32.h ('k') | tests_lit/llvm2ice_tests/int-arg.ll » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/IceTargetLoweringMIPS32.cpp
diff --git a/src/IceTargetLoweringMIPS32.cpp b/src/IceTargetLoweringMIPS32.cpp
index 7cc65cf09a53432791e3f78bef59352ffc0d2ae0..a7e579e0e96b0c50b1508b0f6b969d8764fb4dcf 100644
--- a/src/IceTargetLoweringMIPS32.cpp
+++ b/src/IceTargetLoweringMIPS32.cpp
@@ -24,6 +24,7 @@
#include "IceInstMIPS32.h"
#include "IceLiveness.h"
#include "IceOperand.h"
+#include "IcePhiLoweringImpl.h"
#include "IceRegistersMIPS32.h"
#include "IceTargetLoweringMIPS32.def"
#include "IceUtils.h"
@@ -31,21 +32,41 @@
namespace Ice {
+using llvm::isInt;
+
+namespace {
+
+// The maximum number of arguments to pass in GPR registers.
+constexpr uint32_t MIPS32_MAX_GPR_ARG = 4;
+
+} // end of anonymous namespace
+
TargetMIPS32::TargetMIPS32(Cfg *Func) : TargetLowering(Func) {
// TODO: Don't initialize IntegerRegisters and friends every time. Instead,
// initialize in some sort of static initializer for the class.
+
llvm::SmallBitVector IntegerRegisters(RegMIPS32::Reg_NUM);
- llvm::SmallBitVector FloatRegisters(RegMIPS32::Reg_NUM);
+ llvm::SmallBitVector I64PairRegisters(RegMIPS32::Reg_NUM);
+ llvm::SmallBitVector Float32Registers(RegMIPS32::Reg_NUM);
+ llvm::SmallBitVector Float64Registers(RegMIPS32::Reg_NUM);
llvm::SmallBitVector VectorRegisters(RegMIPS32::Reg_NUM);
llvm::SmallBitVector InvalidRegisters(RegMIPS32::Reg_NUM);
ScratchRegs.resize(RegMIPS32::Reg_NUM);
#define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \
- isFP) \
+ isI64Pair, isFP32, isFP64, isVec128, alias_init) \
IntegerRegisters[RegMIPS32::val] = isInt; \
- FloatRegisters[RegMIPS32::val] = isFP; \
- VectorRegisters[RegMIPS32::val] = isFP; \
+ I64PairRegisters[RegMIPS32::val] = isI64Pair; \
+ Float32Registers[RegMIPS32::val] = isFP32; \
+ Float64Registers[RegMIPS32::val] = isFP64; \
+ VectorRegisters[RegMIPS32::val] = isVec128; \
+ RegisterAliases[RegMIPS32::val].resize(RegMIPS32::Reg_NUM); \
+ for (SizeT RegAlias : alias_init) { \
+ assert(!RegisterAliases[RegMIPS32::val][RegAlias] && \
+ "Duplicate alias for " #val); \
+ RegisterAliases[RegMIPS32::val].set(RegAlias); \
+ } \
RegisterAliases[RegMIPS32::val].resize(RegMIPS32::Reg_NUM); \
- RegisterAliases[RegMIPS32::val].set(RegMIPS32::val); \
+ assert(RegisterAliases[RegMIPS32::val][RegMIPS32::val]); \
ScratchRegs[RegMIPS32::val] = scratch;
REGMIPS32_TABLE;
#undef X
@@ -55,8 +76,8 @@ TargetMIPS32::TargetMIPS32(Cfg *Func) : TargetLowering(Func) {
TypeToRegisterSet[IceType_i16] = IntegerRegisters;
TypeToRegisterSet[IceType_i32] = IntegerRegisters;
TypeToRegisterSet[IceType_i64] = IntegerRegisters;
- TypeToRegisterSet[IceType_f32] = FloatRegisters;
- TypeToRegisterSet[IceType_f64] = FloatRegisters;
+ TypeToRegisterSet[IceType_f32] = Float32Registers;
+ TypeToRegisterSet[IceType_f64] = Float64Registers;
TypeToRegisterSet[IceType_v4i1] = VectorRegisters;
TypeToRegisterSet[IceType_v8i1] = VectorRegisters;
TypeToRegisterSet[IceType_v16i1] = VectorRegisters;
@@ -213,7 +234,7 @@ IceString TargetMIPS32::getRegName(SizeT RegNum, Type Ty) const {
(void)Ty;
static const char *RegNames[] = {
#define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \
- isFP) \
+ isI64Pair, isFP32, isFP64, isVec128, alias_init) \
name,
REGMIPS32_TABLE
#undef X
@@ -248,39 +269,215 @@ void TargetMIPS32::emitJumpTable(const Cfg *Func,
UnimplementedError(Func->getContext()->getFlags());
}
+/// Provide a trivial wrapper to legalize() for this common usage.
+Variable *TargetMIPS32::legalizeToReg(Operand *From, int32_t RegNum) {
+ return llvm::cast<Variable>(legalize(From, Legal_Reg, RegNum));
+}
+
+/// Legalize undef values to concrete values.
+Operand *TargetMIPS32::legalizeUndef(Operand *From, int32_t RegNum) {
+ (void)RegNum;
+ Type Ty = From->getType();
+ if (llvm::isa<ConstantUndef>(From)) {
+ // Lower undefs to zero. Another option is to lower undefs to an
+ // uninitialized register; however, using an uninitialized register
+ // results in less predictable code.
+ //
+ // If in the future the implementation is changed to lower undef
+ // values to uninitialized registers, a FakeDef will be needed:
+ // Context.insert(InstFakeDef::create(Func, Reg));
+ // This is in order to ensure that the live range of Reg is not
+ // overestimated. If the constant being lowered is a 64 bit value,
+ // then the result should be split and the lo and hi components will
+ // need to go in uninitialized registers.
+ if (isVectorType(Ty))
+ UnimplementedError(Func->getContext()->getFlags());
+ return Ctx->getConstantZero(Ty);
+ }
+ return From;
+}
+
+Variable *TargetMIPS32::makeReg(Type Type, int32_t RegNum) {
+ // There aren't any 64-bit integer registers for Mips32.
+ assert(Type != IceType_i64);
+ Variable *Reg = Func->makeVariable(Type);
+ if (RegNum == Variable::NoRegister)
+ Reg->setMustHaveReg();
+ else
+ Reg->setRegNum(RegNum);
+ return Reg;
+}
+
void TargetMIPS32::emitVariable(const Variable *Var) const {
if (!BuildDefs::dump())
return;
Ostream &Str = Ctx->getStrEmit();
- (void)Var;
- (void)Str;
+ const Type FrameSPTy = IceType_i32;
+ if (Var->hasReg()) {
+ Str << '$' << getRegName(Var->getRegNum(), Var->getType());
+ return;
+ } else {
+ int32_t Offset = Var->getStackOffset();
+ Str << Offset;
+ Str << "(" << getRegName(getFrameOrStackReg(), FrameSPTy);
+ Str << ")";
+ }
UnimplementedError(Func->getContext()->getFlags());
}
void TargetMIPS32::lowerArguments() {
VarList &Args = Func->getArgs();
- if (Args.size() > 0)
- UnimplementedError(Func->getContext()->getFlags());
+ // We are only handling integer registers for now. The Mips o32 ABI is
+ // somewhat complex but will be implemented in its totality through follow
+ // on patches.
+ //
+ unsigned NumGPRRegsUsed = 0;
+ // For each register argument, replace Arg in the argument list with the
+ // home register. Then generate an instruction in the prolog to copy the
+ // home register to the assigned location of Arg.
+ Context.init(Func->getEntryNode());
+ Context.setInsertPoint(Context.getCur());
+ for (SizeT I = 0, E = Args.size(); I < E; ++I) {
+ Variable *Arg = Args[I];
+ Type Ty = Arg->getType();
+ // TODO(rkotler): handle float/vector types.
+ if (isVectorType(Ty)) {
+ UnimplementedError(Func->getContext()->getFlags());
+ continue;
+ }
+ if (isFloatingType(Ty)) {
+ UnimplementedError(Func->getContext()->getFlags());
+ continue;
+ }
+ if (Ty == IceType_i64) {
+ if (NumGPRRegsUsed >= MIPS32_MAX_GPR_ARG)
+ continue;
+ int32_t RegLo = RegMIPS32::Reg_A0 + NumGPRRegsUsed;
+ int32_t RegHi = RegLo + 1;
+ ++NumGPRRegsUsed;
+ // Always start i64 registers at an even register, so this may end
+ // up padding away a register.
+ if (RegLo % 2 != 0) {
+ ++RegLo;
+ ++NumGPRRegsUsed;
+ }
+ // If this leaves us without room to consume another register,
+ // leave any previously speculatively consumed registers as consumed.
+ if (NumGPRRegsUsed >= MIPS32_MAX_GPR_ARG)
+ continue;
+ // RegHi = RegMIPS32::Reg_A0 + NumGPRRegsUsed;
+ ++NumGPRRegsUsed;
+ Variable *RegisterArg = Func->makeVariable(Ty);
+ auto *RegisterArg64On32 = llvm::cast<Variable64On32>(RegisterArg);
+ if (BuildDefs::dump())
+ RegisterArg64On32->setName(Func, "home_reg:" + Arg->getName(Func));
+ RegisterArg64On32->initHiLo(Func);
+ RegisterArg64On32->setIsArg();
+ RegisterArg64On32->getLo()->setRegNum(RegLo);
+ RegisterArg64On32->getHi()->setRegNum(RegHi);
+ Arg->setIsArg(false);
+ Args[I] = RegisterArg64On32;
+ Context.insert(InstAssign::create(Func, Arg, RegisterArg));
+ continue;
+ } else {
+ assert(Ty == IceType_i32);
+ if (NumGPRRegsUsed >= MIPS32_MAX_GPR_ARG)
+ continue;
+ int32_t RegNum = RegMIPS32::Reg_A0 + NumGPRRegsUsed;
+ ++NumGPRRegsUsed;
+ Variable *RegisterArg = Func->makeVariable(Ty);
+ if (BuildDefs::dump()) {
+ RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func));
+ }
+ RegisterArg->setRegNum(RegNum);
+ RegisterArg->setIsArg();
+ Arg->setIsArg(false);
+ Args[I] = RegisterArg;
+ Context.insert(InstAssign::create(Func, Arg, RegisterArg));
+ }
+ }
}
Type TargetMIPS32::stackSlotType() { return IceType_i32; }
void TargetMIPS32::addProlog(CfgNode *Node) {
(void)Node;
+ return;
UnimplementedError(Func->getContext()->getFlags());
}
void TargetMIPS32::addEpilog(CfgNode *Node) {
(void)Node;
+ return;
UnimplementedError(Func->getContext()->getFlags());
}
+Operand *TargetMIPS32::loOperand(Operand *Operand) {
+ assert(Operand->getType() == IceType_i64);
+ if (auto *Var64On32 = llvm::dyn_cast<Variable64On32>(Operand))
+ return Var64On32->getLo();
+ if (auto *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) {
+ return Ctx->getConstantInt32(static_cast<uint32_t>(Const->getValue()));
+ }
+ if (auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(Operand)) {
+ // Conservatively disallow memory operands with side-effects (pre/post
+ // increment) in case of duplication.
+ assert(Mem->getAddrMode() == OperandMIPS32Mem::Offset);
+ return OperandMIPS32Mem::create(Func, IceType_i32, Mem->getBase(),
+ Mem->getOffset(), Mem->getAddrMode());
+ }
+ llvm_unreachable("Unsupported operand type");
+ return nullptr;
+}
+
+Operand *TargetMIPS32::hiOperand(Operand *Operand) {
+ assert(Operand->getType() == IceType_i64);
+ if (Operand->getType() != IceType_i64)
+ return Operand;
+ if (auto *Var64On32 = llvm::dyn_cast<Variable64On32>(Operand))
+ return Var64On32->getHi();
+ if (auto *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) {
+ return Ctx->getConstantInt32(
+ static_cast<uint32_t>(Const->getValue() >> 32));
+ }
+ if (auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(Operand)) {
+ // Conservatively disallow memory operands with side-effects
+ // in case of duplication.
+ assert(Mem->getAddrMode() == OperandMIPS32Mem::Offset);
+ const Type SplitType = IceType_i32;
+ Variable *Base = Mem->getBase();
+ ConstantInteger32 *Offset = Mem->getOffset();
+ assert(!Utils::WouldOverflowAdd(Offset->getValue(), 4));
+ int32_t NextOffsetVal = Offset->getValue() + 4;
+ constexpr bool SignExt = false;
+ if (!OperandMIPS32Mem::canHoldOffset(SplitType, SignExt, NextOffsetVal)) {
+ // We have to make a temp variable and add 4 to either Base or Offset.
+ // If we add 4 to Offset, this will convert a non-RegReg addressing
+ // mode into a RegReg addressing mode. Since NaCl sandboxing disallows
+ // RegReg addressing modes, prefer adding to base and replacing instead.
+ // Thus we leave the old offset alone.
+ Constant *Four = Ctx->getConstantInt32(4);
+ Variable *NewBase = Func->makeVariable(Base->getType());
+ lowerArithmetic(InstArithmetic::create(Func, InstArithmetic::Add, NewBase,
+ Base, Four));
+ Base = NewBase;
+ } else {
+ Offset =
+ llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(NextOffsetVal));
+ }
+ return OperandMIPS32Mem::create(Func, SplitType, Base, Offset,
+ Mem->getAddrMode());
+ }
+ llvm_unreachable("Unsupported operand type");
+ return nullptr;
+}
+
llvm::SmallBitVector TargetMIPS32::getRegisterSet(RegSetMask Include,
RegSetMask Exclude) const {
llvm::SmallBitVector Registers(RegMIPS32::Reg_NUM);
#define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \
- isFP) \
+ isI64Pair, isFP32, isFP64, isVec128, alias_init) \
if (scratch && (Include & RegSet_CallerSave)) \
Registers[RegMIPS32::val] = true; \
if (preserved && (Include & RegSet_CalleeSave)) \
@@ -318,70 +515,117 @@ void TargetMIPS32::lowerAlloca(const InstAlloca *Inst) {
}
void TargetMIPS32::lowerArithmetic(const InstArithmetic *Inst) {
- switch (Inst->getOp()) {
- case InstArithmetic::_num:
- UnimplementedError(Func->getContext()->getFlags());
- break;
- case InstArithmetic::Add:
- UnimplementedError(Func->getContext()->getFlags());
- break;
- case InstArithmetic::And:
- UnimplementedError(Func->getContext()->getFlags());
- break;
- case InstArithmetic::Or:
- UnimplementedError(Func->getContext()->getFlags());
- break;
- case InstArithmetic::Xor:
+ Variable *Dest = Inst->getDest();
+ Operand *Src0 = legalizeUndef(Inst->getSrc(0));
+ Operand *Src1 = legalizeUndef(Inst->getSrc(1));
+ (void)Src0;
+ (void)Src1;
+ if (Dest->getType() == IceType_i64) {
UnimplementedError(Func->getContext()->getFlags());
- break;
- case InstArithmetic::Sub:
- UnimplementedError(Func->getContext()->getFlags());
- break;
- case InstArithmetic::Mul:
- UnimplementedError(Func->getContext()->getFlags());
- break;
- case InstArithmetic::Shl:
- UnimplementedError(Func->getContext()->getFlags());
- break;
- case InstArithmetic::Lshr:
- UnimplementedError(Func->getContext()->getFlags());
- break;
- case InstArithmetic::Ashr:
- UnimplementedError(Func->getContext()->getFlags());
- break;
- case InstArithmetic::Udiv:
- UnimplementedError(Func->getContext()->getFlags());
- break;
- case InstArithmetic::Sdiv:
- UnimplementedError(Func->getContext()->getFlags());
- break;
- case InstArithmetic::Urem:
+ } else if (isVectorType(Dest->getType())) {
UnimplementedError(Func->getContext()->getFlags());
- break;
- case InstArithmetic::Srem:
- UnimplementedError(Func->getContext()->getFlags());
- break;
- case InstArithmetic::Fadd:
- UnimplementedError(Func->getContext()->getFlags());
- break;
- case InstArithmetic::Fsub:
- UnimplementedError(Func->getContext()->getFlags());
- break;
- case InstArithmetic::Fmul:
- UnimplementedError(Func->getContext()->getFlags());
- break;
- case InstArithmetic::Fdiv:
- UnimplementedError(Func->getContext()->getFlags());
- break;
- case InstArithmetic::Frem:
- UnimplementedError(Func->getContext()->getFlags());
- break;
+ } else { // Dest->getType() is non-i64 scalar
+ switch (Inst->getOp()) {
+ case InstArithmetic::_num:
+ UnimplementedError(Func->getContext()->getFlags());
+ break;
+ case InstArithmetic::Add:
+ UnimplementedError(Func->getContext()->getFlags());
+ // Variable *T = makeReg(Dest->getType());
+ // _add(T, Src0, Src1);
+ // _mov(Dest, T);
+ return;
+ case InstArithmetic::And:
+ UnimplementedError(Func->getContext()->getFlags());
+ break;
+ case InstArithmetic::Or:
+ UnimplementedError(Func->getContext()->getFlags());
+ break;
+ case InstArithmetic::Xor:
+ UnimplementedError(Func->getContext()->getFlags());
+ break;
+ case InstArithmetic::Sub:
+ UnimplementedError(Func->getContext()->getFlags());
+ break;
+ case InstArithmetic::Mul:
+ UnimplementedError(Func->getContext()->getFlags());
+ break;
+ case InstArithmetic::Shl:
+ UnimplementedError(Func->getContext()->getFlags());
+ break;
+ case InstArithmetic::Lshr:
+ UnimplementedError(Func->getContext()->getFlags());
+ break;
+ case InstArithmetic::Ashr:
+ UnimplementedError(Func->getContext()->getFlags());
+ break;
+ case InstArithmetic::Udiv:
+ UnimplementedError(Func->getContext()->getFlags());
+ break;
+ case InstArithmetic::Sdiv:
+ UnimplementedError(Func->getContext()->getFlags());
+ break;
+ case InstArithmetic::Urem:
+ UnimplementedError(Func->getContext()->getFlags());
+ break;
+ case InstArithmetic::Srem:
+ UnimplementedError(Func->getContext()->getFlags());
+ break;
+ case InstArithmetic::Fadd:
+ UnimplementedError(Func->getContext()->getFlags());
+ break;
+ case InstArithmetic::Fsub:
+ UnimplementedError(Func->getContext()->getFlags());
+ break;
+ case InstArithmetic::Fmul:
+ UnimplementedError(Func->getContext()->getFlags());
+ break;
+ case InstArithmetic::Fdiv:
+ UnimplementedError(Func->getContext()->getFlags());
+ break;
+ case InstArithmetic::Frem:
+ UnimplementedError(Func->getContext()->getFlags());
+ break;
+ }
}
}
void TargetMIPS32::lowerAssign(const InstAssign *Inst) {
- (void)Inst;
- UnimplementedError(Func->getContext()->getFlags());
+ Variable *Dest = Inst->getDest();
+ Operand *Src0 = Inst->getSrc(0);
+ assert(Dest->getType() == Src0->getType());
+ if (Dest->getType() == IceType_i64) {
+ Src0 = legalizeUndef(Src0);
+ Operand *Src0Lo = legalize(loOperand(Src0), Legal_Reg);
+ Operand *Src0Hi = legalize(hiOperand(Src0), Legal_Reg);
+ Variable *DestLo = llvm::cast<Variable>(loOperand(Dest));
+ Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest));
+ // Variable *T_Lo = nullptr, *T_Hi = nullptr;
+ Variable *T_Lo = makeReg(IceType_i32);
+ Variable *T_Hi = makeReg(IceType_i32);
+ _mov(T_Lo, Src0Lo);
+ _mov(DestLo, T_Lo);
+ _mov(T_Hi, Src0Hi);
+ _mov(DestHi, T_Hi);
+ } else {
+ Operand *SrcR;
+ if (Dest->hasReg()) {
+ // If Dest already has a physical register, then legalize the Src operand
+ // into a Variable with the same register assignment. This especially
+ // helps allow the use of Flex operands.
+ SrcR = legalize(Src0, Legal_Reg, Dest->getRegNum());
+ } else {
+ // Dest could be a stack operand. Since we could potentially need
+ // to do a Store (and store can only have Register operands),
+ // legalize this to a register.
+ SrcR = legalize(Src0, Legal_Reg);
+ }
+ if (isVectorType(Dest->getType())) {
+ UnimplementedError(Func->getContext()->getFlags());
+ } else {
+ _mov(Dest, SrcR);
+ }
+ }
}
void TargetMIPS32::lowerBr(const InstBr *Inst) {
@@ -608,8 +852,32 @@ void TargetMIPS32::lowerPhi(const InstPhi * /*Inst*/) {
void TargetMIPS32::lowerRet(const InstRet *Inst) {
Variable *Reg = nullptr;
- if (Inst->hasRetValue())
- UnimplementedError(Func->getContext()->getFlags());
+ if (Inst->hasRetValue()) {
+ Operand *Src0 = Inst->getRetValue();
+ switch (Src0->getType()) {
+ case IceType_i1:
+ case IceType_i8:
+ case IceType_i16:
+ case IceType_i32: {
+ // Reg = legalizeToReg(Src0, RegMIPS32::Reg_V0);
+ Operand *Src0F = legalize(Src0, Legal_Reg);
+ Reg = makeReg(Src0F->getType(), RegMIPS32::Reg_V0);
+ _mov(Reg, Src0F);
+ break;
+ }
+ case IceType_i64: {
+ Src0 = legalizeUndef(Src0);
+ Variable *R0 = legalizeToReg(loOperand(Src0), RegMIPS32::Reg_V0);
+ Variable *R1 = legalizeToReg(hiOperand(Src0), RegMIPS32::Reg_V1);
+ Reg = R0;
+ Context.insert(InstFakeUse::create(Func, R1));
+ break;
+ }
+
+ default:
+ UnimplementedError(Func->getContext()->getFlags());
+ }
+ }
_ret(getPhysicalRegister(RegMIPS32::Reg_RA), Reg);
}
@@ -640,7 +908,7 @@ void TargetMIPS32::lowerUnreachable(const InstUnreachable * /*Inst*/) {
// integrity of liveness analysis. Undef values are also turned into zeroes,
// since loOperand() and hiOperand() don't expect Undef input.
void TargetMIPS32::prelowerPhis() {
- UnimplementedError(Func->getContext()->getFlags());
+ PhiLowering::prelowerPhis32Bit<TargetMIPS32>(this, Context.getNode(), Func);
}
void TargetMIPS32::postLower() {
@@ -705,7 +973,86 @@ void TargetDataMIPS32::lowerJumpTables() {
UnimplementedError(Ctx->getFlags());
}
+// Helper for legalize() to emit the right code to lower an operand to a
+// register of the appropriate type.
+Variable *TargetMIPS32::copyToReg(Operand *Src, int32_t RegNum) {
+ Type Ty = Src->getType();
+ Variable *Reg = makeReg(Ty, RegNum);
+ if (isVectorType(Ty) || isFloatingType(Ty)) {
+ UnimplementedError(Ctx->getFlags());
+ } else {
+ // Mov's Src operand can really only be the flexible second operand type
+ // or a register. Users should guarantee that.
+ _mov(Reg, Src);
+ }
+ return Reg;
+}
+
+Operand *TargetMIPS32::legalize(Operand *From, LegalMask Allowed,
+ int32_t RegNum) {
+ Type Ty = From->getType();
+ // Assert that a physical register is allowed. To date, all calls
+ // to legalize() allow a physical register. Legal_Flex converts
+ // registers to the right type OperandMIPS32FlexReg as needed.
+ assert(Allowed & Legal_Reg);
+ // Go through the various types of operands:
+ // OperandMIPS32Mem, OperandMIPS32Flex, Constant, and Variable.
+ // Given the above assertion, if type of operand is not legal
+ // (e.g., OperandMIPS32Mem and !Legal_Mem), we can always copy
+ // to a register.
+ if (auto C = llvm::dyn_cast<ConstantRelocatable>(From)) {
+ (void)C;
+ return From;
+ } else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(From)) {
+ uint32_t Value = static_cast<uint32_t>(C32->getValue());
+ // Check if the immediate will fit in a Flexible second operand,
+ // if a Flexible second operand is allowed. We need to know the exact
+ // value, so that rules out relocatable constants.
+ // Also try the inverse and use MVN if possible.
+ // Do a movw/movt to a register.
+ Variable *Reg;
+ if (RegNum == Variable::NoRegister)
+ Reg = makeReg(Ty, RegNum);
+ else
+ Reg = getPhysicalRegister(RegNum);
+ if (isInt<16>(int32_t(Value))) {
+ _addiu(Reg, getPhysicalRegister(RegMIPS32::Reg_ZERO, Ty), Value);
+ } else {
+ uint32_t UpperBits = (Value >> 16) & 0xFFFF;
+ (void)UpperBits;
+ uint32_t LowerBits = Value & 0xFFFF;
+ Variable *TReg = makeReg(Ty, RegNum);
+ _lui(TReg, UpperBits);
+ _ori(Reg, TReg, LowerBits);
+ }
+ return Reg;
+ }
+ if (auto Var = llvm::dyn_cast<Variable>(From)) {
+ // Check if the variable is guaranteed a physical register. This
+ // can happen either when the variable is pre-colored or when it is
+ // assigned infinite weight.
+ bool MustHaveRegister = (Var->hasReg() || Var->mustHaveReg());
+ // We need a new physical register for the operand if:
+ // Mem is not allowed and Var isn't guaranteed a physical
+ // register, or
+ // RegNum is required and Var->getRegNum() doesn't match.
+ if ((!(Allowed & Legal_Mem) && !MustHaveRegister) ||
+ (RegNum != Variable::NoRegister && RegNum != Var->getRegNum())) {
+ From = copyToReg(From, RegNum);
+ }
+ return From;
+ }
+ return From;
+}
+
TargetHeaderMIPS32::TargetHeaderMIPS32(GlobalContext *Ctx)
: TargetHeaderLowering(Ctx) {}
+void TargetHeaderMIPS32::lower() {
+ OstreamLocker L(Ctx);
+ Ostream &Str = Ctx->getStrEmit();
+ Str << "\t.set\tnomicromips\n";
+ Str << "\t.set\tnomips16\n";
+}
+
} // end of namespace Ice
« no previous file with comments | « src/IceTargetLoweringMIPS32.h ('k') | tests_lit/llvm2ice_tests/int-arg.ll » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698