Index: src/IceTargetLoweringMIPS32.cpp |
diff --git a/src/IceTargetLoweringMIPS32.cpp b/src/IceTargetLoweringMIPS32.cpp |
index 331f1ed4c99b6a82b3c3682f1a40810004cf6baa..36520b44052b21bd40b48db75f1b633643dcce8f 100644 |
--- a/src/IceTargetLoweringMIPS32.cpp |
+++ b/src/IceTargetLoweringMIPS32.cpp |
@@ -219,13 +219,97 @@ uint32_t TargetMIPS32::getStackAlignment() const { |
void TargetMIPS32::genTargetHelperCallFor(Inst *Instr) { |
constexpr bool NoTailCall = false; |
constexpr bool IsTargetHelperCall = true; |
+ Variable *Dest = Instr->getDest(); |
+ const Type DestTy = Dest ? Dest->getType() : IceType_void; |
switch (Instr->getKind()) { |
default: |
return; |
+ case Inst::Select: { |
+ if (isVectorType(DestTy)) { |
+ Operand *SrcT = llvm::cast<InstSelect>(Instr)->getTrueOperand(); |
+ Operand *SrcF = llvm::cast<InstSelect>(Instr)->getFalseOperand(); |
+ Operand *Cond = llvm::cast<InstSelect>(Instr)->getCondition(); |
+ Variable *T = Func->makeVariable(DestTy); |
+ auto *Undef = ConstantUndef::create(Ctx, DestTy); |
+ Context.insert<InstAssign>(T, Undef); |
+ auto *VarVecOn32 = llvm::cast<VariableVecOn32>(T); |
+ VarVecOn32->initVecElement(Func); |
+ for (SizeT I = 0; I < typeNumElements(DestTy); ++I) { |
+ auto *Index = Ctx->getConstantInt32(I); |
+ auto *OpC = Func->makeVariable(typeElementType(Cond->getType())); |
+ Context.insert<InstExtractElement>(OpC, Cond, Index); |
+ auto *OpT = Func->makeVariable(typeElementType(DestTy)); |
+ Context.insert<InstExtractElement>(OpT, SrcT, Index); |
+ auto *OpF = Func->makeVariable(typeElementType(DestTy)); |
+ Context.insert<InstExtractElement>(OpF, SrcF, Index); |
+ auto *Dst = Func->makeVariable(typeElementType(DestTy)); |
+ Variable *DestT = Func->makeVariable(DestTy); |
+ Context.insert<InstSelect>(Dst, OpC, OpT, OpF); |
+ Context.insert<InstInsertElement>(DestT, T, Dst, Index); |
+ T = DestT; |
+ } |
+ Context.insert<InstAssign>(Dest, T); |
+ Instr->setDeleted(); |
+ } |
+ return; |
+ } |
+ case Inst::Fcmp: { |
+ if (isVectorType(DestTy)) { |
+ InstFcmp::FCond Cond = llvm::cast<InstFcmp>(Instr)->getCondition(); |
+ Operand *Src0 = Instr->getSrc(0); |
+ Operand *Src1 = Instr->getSrc(1); |
+ Variable *T = Func->makeVariable(IceType_v4f32); |
+ auto *Undef = ConstantUndef::create(Ctx, IceType_v4f32); |
+ Context.insert<InstAssign>(T, Undef); |
+ auto *VarVecOn32 = llvm::cast<VariableVecOn32>(T); |
+ VarVecOn32->initVecElement(Func); |
+ for (SizeT I = 0; I < typeNumElements(IceType_v4f32); ++I) { |
+ auto *Index = Ctx->getConstantInt32(I); |
+ auto *Op0 = Func->makeVariable(IceType_f32); |
+ Context.insert<InstExtractElement>(Op0, Src0, Index); |
+ auto *Op1 = Func->makeVariable(IceType_f32); |
+ Context.insert<InstExtractElement>(Op1, Src1, Index); |
+ auto *Dst = Func->makeVariable(IceType_f32); |
+ Variable *DestT = Func->makeVariable(IceType_v4f32); |
+ Context.insert<InstFcmp>(Cond, Dst, Op0, Op1); |
+ Context.insert<InstInsertElement>(DestT, T, Dst, Index); |
+ T = DestT; |
+ } |
+ Context.insert<InstAssign>(Dest, T); |
+ Instr->setDeleted(); |
+ } |
+ return; |
+ } |
+ case Inst::Icmp: { |
+ if (isVectorType(DestTy)) { |
+ InstIcmp::ICond Cond = llvm::cast<InstIcmp>(Instr)->getCondition(); |
+ Operand *Src0 = Instr->getSrc(0); |
+ Operand *Src1 = Instr->getSrc(1); |
+ const Type SrcType = Src0->getType(); |
+ Variable *T = Func->makeVariable(DestTy); |
+ auto *Undef = ConstantUndef::create(Ctx, DestTy); |
+ Context.insert<InstAssign>(T, Undef); |
+ auto *VarVecOn32 = llvm::cast<VariableVecOn32>(T); |
+ VarVecOn32->initVecElement(Func); |
+ for (SizeT I = 0; I < typeNumElements(SrcType); ++I) { |
+ auto *Index = Ctx->getConstantInt32(I); |
+ auto *Op0 = Func->makeVariable(typeElementType(SrcType)); |
+ Context.insert<InstExtractElement>(Op0, Src0, Index); |
+ auto *Op1 = Func->makeVariable(typeElementType(SrcType)); |
+ Context.insert<InstExtractElement>(Op1, Src1, Index); |
+ auto *Dst = Func->makeVariable(typeElementType(DestTy)); |
+ Variable *DestT = Func->makeVariable(DestTy); |
+ Context.insert<InstIcmp>(Cond, Dst, Op0, Op1); |
+ Context.insert<InstInsertElement>(DestT, T, Dst, Index); |
+ T = DestT; |
+ } |
+ Context.insert<InstAssign>(Dest, T); |
+ Instr->setDeleted(); |
+ } |
+ return; |
+ } |
case Inst::Arithmetic: { |
- Variable *Dest = Instr->getDest(); |
- const Type DestTy = Dest->getType(); |
const InstArithmetic::OpKind Op = |
llvm::cast<InstArithmetic>(Instr)->getOp(); |
if (isVectorType(DestTy)) { |
@@ -288,12 +372,32 @@ void TargetMIPS32::genTargetHelperCallFor(Inst *Instr) { |
llvm::report_fatal_error("Control flow should never have reached here."); |
} |
case Inst::Cast: { |
- Variable *Dest = Instr->getDest(); |
Operand *Src0 = Instr->getSrc(0); |
- const Type DestTy = Dest->getType(); |
const Type SrcTy = Src0->getType(); |
auto *CastInstr = llvm::cast<InstCast>(Instr); |
const InstCast::OpKind CastKind = CastInstr->getCastKind(); |
+ |
+ if (isVectorType(DestTy)) { |
+ Variable *T = Func->makeVariable(DestTy); |
+ auto *VarVecOn32 = llvm::cast<VariableVecOn32>(T); |
+ VarVecOn32->initVecElement(Func); |
+ auto *Undef = ConstantUndef::create(Ctx, DestTy); |
+ Context.insert<InstAssign>(T, Undef); |
+ for (SizeT I = 0; I < typeNumElements(DestTy); ++I) { |
+ auto *Index = Ctx->getConstantInt32(I); |
+ auto *Op = Func->makeVariable(typeElementType(SrcTy)); |
+ Context.insert<InstExtractElement>(Op, Src0, Index); |
+ auto *Dst = Func->makeVariable(typeElementType(DestTy)); |
+ Variable *DestT = Func->makeVariable(DestTy); |
+ Context.insert<InstCast>(CastKind, Dst, Op); |
+ Context.insert<InstInsertElement>(DestT, T, Dst, Index); |
+ T = DestT; |
+ } |
+ Context.insert<InstAssign>(Dest, T); |
+ Instr->setDeleted(); |
+ return; |
+ } |
+ |
switch (CastKind) { |
default: |
return; |
@@ -333,7 +437,7 @@ void TargetMIPS32::genTargetHelperCallFor(Inst *Instr) { |
} |
const bool SourceIs32 = SrcTy == IceType_i32; |
const bool SourceIsSigned = CastKind == InstCast::Sitofp; |
- const bool DestIsF32 = isFloat32Asserting32Or64(Dest->getType()); |
+ const bool DestIsF32 = isFloat32Asserting32Or64(DestTy); |
RuntimeHelper RTHFunc = RuntimeHelper::H_Num; |
if (SourceIsSigned) { |
if (SourceIs32) { |
@@ -397,7 +501,7 @@ void TargetMIPS32::genTargetHelperCallFor(Inst *Instr) { |
Context.insert(Call); |
// The PNaCl ABI disallows i8/i16 return types, so truncate the helper |
// call result to the appropriate type as necessary. |
- if (CallDest->getType() != Dest->getType()) |
+ if (CallDest->getType() != DestTy) |
Context.insert<InstCast>(InstCast::Trunc, Dest, CallDest); |
Instr->setDeleted(); |
return; |
@@ -431,10 +535,9 @@ void TargetMIPS32::genTargetHelperCallFor(Inst *Instr) { |
llvm::report_fatal_error("Control flow should never have reached here."); |
} |
case Inst::IntrinsicCall: { |
- Variable *Dest = Instr->getDest(); |
auto *IntrinsicCall = llvm::cast<InstIntrinsicCall>(Instr); |
Intrinsics::IntrinsicID ID = IntrinsicCall->getIntrinsicInfo().ID; |
- if (Dest && isVectorType(Dest->getType()) && ID == Intrinsics::Fabs) { |
+ if (isVectorType(DestTy) && ID == Intrinsics::Fabs) { |
Operand *Src0 = IntrinsicCall->getArg(0); |
GlobalString FabsFloat = Ctx->getGlobalString("llvm.fabs.f32"); |
Operand *CallTarget = Ctx->getConstantExternSym(FabsFloat); |
@@ -445,11 +548,12 @@ void TargetMIPS32::genTargetHelperCallFor(Inst *Instr) { |
Intrinsics::IntrinsicInfo Info = FullInfo->Info; |
Variable *T = Func->makeVariable(IceType_v4f32); |
- auto *VarVecOn32 = llvm::dyn_cast<VariableVecOn32>(T); |
+ auto *Undef = ConstantUndef::create(Ctx, IceType_v4f32); |
+ Context.insert<InstAssign>(T, Undef); |
+ auto *VarVecOn32 = llvm::cast<VariableVecOn32>(T); |
VarVecOn32->initVecElement(Func); |
- Context.insert<InstFakeDef>(T); |
- for (SizeT i = 0; i < VarVecOn32->ElementsPerContainer; ++i) { |
+ for (SizeT i = 0; i < typeNumElements(IceType_v4f32); ++i) { |
auto *Index = Ctx->getConstantInt32(i); |
auto *Op = Func->makeVariable(IceType_f32); |
Context.insert<InstExtractElement>(Op, Src0, Index); |
@@ -1079,23 +1183,13 @@ void TargetMIPS32::lowerArguments() { |
// v4f32 is returned through stack. $4 is setup by the caller and passed as |
// first argument implicitly. Callee then copies the return vector at $4. |
+ Variable *ImplicitRetVec = nullptr; |
if (isVectorFloatingType(Func->getReturnType())) { |
- Variable *ImplicitRetVec = Func->makeVariable(IceType_i32); |
+ ImplicitRetVec = Func->makeVariable(IceType_i32); |
ImplicitRetVec->setName(Func, "ImplicitRet_v4f32"); |
ImplicitRetVec->setIsArg(); |
Args.insert(Args.begin(), ImplicitRetVec); |
setImplicitRet(ImplicitRetVec); |
- Context.insert<InstFakeDef>(ImplicitRetVec); |
- for (CfgNode *Node : Func->getNodes()) { |
- for (Inst &Instr : Node->getInsts()) { |
- if (llvm::isa<InstRet>(&Instr)) { |
- Context.setInsertPoint(Instr); |
- Context.insert<InstFakeUse>(ImplicitRetVec); |
- break; |
- } |
- } |
- } |
- Context.setInsertPoint(Context.getCur()); |
} |
for (SizeT i = 0, E = Args.size(); i < E; ++i) { |
@@ -1149,6 +1243,19 @@ void TargetMIPS32::lowerArguments() { |
} |
Context.insert<InstAssign>(Arg, RegisterArg); |
} |
+ |
+ // Insert fake use of ImplicitRet_v4f32 to keep it live |
+ if (ImplicitRetVec) { |
+ for (CfgNode *Node : Func->getNodes()) { |
+ for (Inst &Instr : Node->getInsts()) { |
+ if (llvm::isa<InstRet>(&Instr)) { |
+ Context.setInsertPoint(Instr); |
+ Context.insert<InstFakeUse>(ImplicitRetVec); |
+ break; |
+ } |
+ } |
+ } |
+ } |
} |
Type TargetMIPS32::stackSlotType() { return IceType_i32; } |
@@ -2247,7 +2354,7 @@ void TargetMIPS32::lowerArithmetic(const InstArithmetic *Instr) { |
return; |
} |
if (isVectorType(Dest->getType())) { |
- UnimplementedLoweringError(this, Instr); |
+ llvm::report_fatal_error("Arithmetic: Destination type is vector"); |
return; |
} |
@@ -2395,6 +2502,20 @@ void TargetMIPS32::lowerAssign(const InstAssign *Instr) { |
return; |
} |
+ // Source type may not be same as destination |
+ if (isVectorType(Dest->getType())) { |
+ Operand *Src0 = legalizeUndef(Instr->getSrc(0)); |
+ auto *DstVec = llvm::dyn_cast<VariableVecOn32>(Dest); |
+ for (SizeT i = 0; i < DstVec->ContainersPerVector; ++i) { |
+ auto *DCont = DstVec->getContainers()[i]; |
+ auto *SCont = |
+ legalize(getOperandAtIndex(Src0, IceType_i32, i), Legal_Reg); |
+ auto *TReg = makeReg(IceType_i32); |
+ _mov(TReg, SCont); |
+ _mov(DCont, TReg); |
+ } |
+ return; |
+ } |
Operand *Src0 = Instr->getSrc(0); |
assert(Dest->getType() == Src0->getType()); |
if (Dest->getType() == IceType_i64) { |
@@ -2410,18 +2531,6 @@ void TargetMIPS32::lowerAssign(const InstAssign *Instr) { |
_mov(DestHi, T_Hi); |
return; |
} |
- if (isVectorType(Dest->getType())) { |
- auto *DstVec = llvm::dyn_cast<VariableVecOn32>(Dest); |
- for (SizeT i = 0; i < DstVec->ElementsPerContainer; ++i) { |
- auto *DCont = DstVec->getContainers()[i]; |
- auto *SCont = |
- legalize(getOperandAtIndex(Src0, IceType_i32, i), Legal_Reg); |
- auto *TReg = makeReg(IceType_i32); |
- _mov(TReg, SCont); |
- _mov(DCont, TReg); |
- } |
- return; |
- } |
Operand *SrcR; |
if (Dest->hasReg()) { |
// If Dest already has a physical register, then legalize the Src operand |
@@ -2830,7 +2939,7 @@ void TargetMIPS32::lowerCall(const InstCall *Instr) { |
ReturnReg = makeReg(Dest->getType(), RegMIPS32::Reg_V0); |
auto *RetVec = llvm::dyn_cast<VariableVecOn32>(ReturnReg); |
RetVec->initVecElement(Func); |
- for (SizeT i = 0; i < RetVec->ElementsPerContainer; ++i) { |
+ for (SizeT i = 0; i < RetVec->ContainersPerVector; ++i) { |
auto *Var = RetVec->getContainers()[i]; |
Var->setRegNum(RegNumT::fixme(RegMIPS32::Reg_V0 + i)); |
} |
@@ -2921,7 +3030,7 @@ void TargetMIPS32::lowerCall(const InstCall *Instr) { |
if (ReturnReg) { |
if (RetVecFloat) { |
auto *DestVecOn32 = llvm::cast<VariableVecOn32>(Dest); |
- for (SizeT i = 0; i < DestVecOn32->ElementsPerContainer; ++i) { |
+ for (SizeT i = 0; i < DestVecOn32->ContainersPerVector; ++i) { |
auto *Var = DestVecOn32->getContainers()[i]; |
OperandMIPS32Mem *Mem = OperandMIPS32Mem::create( |
Func, IceType_i32, RetVecFloat, |
@@ -2930,7 +3039,7 @@ void TargetMIPS32::lowerCall(const InstCall *Instr) { |
} |
} else if (auto *RetVec = llvm::dyn_cast<VariableVecOn32>(ReturnReg)) { |
auto *DestVecOn32 = llvm::cast<VariableVecOn32>(Dest); |
- for (SizeT i = 0; i < DestVecOn32->ElementsPerContainer; ++i) { |
+ for (SizeT i = 0; i < DestVecOn32->ContainersPerVector; ++i) { |
_mov(DestVecOn32->getContainers()[i], RetVec->getContainers()[i]); |
} |
} else if (ReturnRegHi) { |
@@ -2966,7 +3075,7 @@ void TargetMIPS32::lowerCast(const InstCast *Instr) { |
: (1 << (CHAR_BITS * typeWidthInBytes(Src0Ty))) - 1); |
if (isVectorType(DestTy)) { |
- UnimplementedLoweringError(this, Instr); |
+ llvm::report_fatal_error("Cast: Destination type is vector"); |
return; |
} |
switch (CastKind) { |
@@ -3129,6 +3238,11 @@ void TargetMIPS32::lowerCast(const InstCast *Instr) { |
lowerAssign(Assign); |
return; |
} |
+ if (isVectorType(DestTy) || isVectorType(Src0->getType())) { |
+ llvm::report_fatal_error( |
+ "Bitcast: vector type should have been prelowered."); |
+ return; |
+ } |
switch (DestTy) { |
case IceType_NUM: |
case IceType_void: |
@@ -3178,16 +3292,6 @@ void TargetMIPS32::lowerCast(const InstCast *Instr) { |
} |
break; |
} |
- case IceType_v8i1: |
- assert(Src0->getType() == IceType_i8); |
- llvm::report_fatal_error( |
- "v8i1 to i8 conversion should have been prelowered."); |
- break; |
- case IceType_v16i1: |
- assert(Src0->getType() == IceType_i16); |
- llvm::report_fatal_error( |
- "v16i1 to i16 conversion should have been prelowered."); |
- break; |
default: |
UnimplementedLoweringError(this, Instr); |
} |
@@ -3208,7 +3312,7 @@ void TargetMIPS32::lowerExtractElement(const InstExtractElement *Instr) { |
auto *Src0R = llvm::dyn_cast<VariableVecOn32>(Src0); |
// Number of elements in each container |
uint32_t ElemPerCont = |
- typeNumElements(Src0->getType()) / Src0R->ElementsPerContainer; |
+ typeNumElements(Src0->getType()) / Src0R->ContainersPerVector; |
auto *SrcE = Src0R->getContainers()[Index / ElemPerCont]; |
// Position of the element in the container |
uint32_t PosInCont = Index % ElemPerCont; |
@@ -3248,8 +3352,9 @@ void TargetMIPS32::lowerExtractElement(const InstExtractElement *Instr) { |
} |
} |
if (typeElementType(Src0R->getType()) == IceType_i1) { |
- _andi(TReg, TDest, 0x1); |
- _mov(Dest, TReg); |
+ Variable *TReg1 = makeReg(DestTy); |
+ _andi(TReg1, TDest, 0x1); |
+ _mov(Dest, TReg1); |
} else { |
_mov(Dest, TDest); |
} |
@@ -3261,7 +3366,7 @@ void TargetMIPS32::lowerExtractElement(const InstExtractElement *Instr) { |
void TargetMIPS32::lowerFcmp(const InstFcmp *Instr) { |
Variable *Dest = Instr->getDest(); |
if (isVectorType(Dest->getType())) { |
- UnimplementedLoweringError(this, Instr); |
+ llvm::report_fatal_error("Fcmp: Destination type is vector"); |
return; |
} |
@@ -3270,7 +3375,7 @@ void TargetMIPS32::lowerFcmp(const InstFcmp *Instr) { |
auto *Zero = getZero(); |
InstFcmp::FCond Cond = Instr->getCondition(); |
- auto *DestR = makeReg(Dest->getType()); |
+ auto *DestR = makeReg(IceType_i32); |
auto *Src0R = legalizeToReg(Src0); |
auto *Src1R = legalizeToReg(Src1); |
const Type Src0Ty = Src0->getType(); |
@@ -3608,7 +3713,7 @@ void TargetMIPS32::lowerIcmp(const InstIcmp *Instr) { |
} |
Variable *Dest = Instr->getDest(); |
if (isVectorType(Dest->getType())) { |
- UnimplementedLoweringError(this, Instr); |
+ llvm::report_fatal_error("Icmp: Destination type is vector"); |
return; |
} |
InstIcmp::ICond Cond = Instr->getCondition(); |
@@ -3714,14 +3819,13 @@ void TargetMIPS32::lowerInsertElement(const InstInsertElement *Instr) { |
if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src2)) { |
const uint32_t Index = Imm->getValue(); |
// Vector to insert in |
- auto *Src0 = Instr->getSrc(0); |
+ auto *Src0 = legalizeUndef(Instr->getSrc(0)); |
auto *Src0R = llvm::dyn_cast<VariableVecOn32>(Src0); |
// Number of elements in each container |
uint32_t ElemPerCont = |
- typeNumElements(Src0->getType()) / Src0R->ElementsPerContainer; |
+ typeNumElements(Src0->getType()) / Src0R->ContainersPerVector; |
// Source Element |
auto *SrcE = Src0R->getContainers()[Index / ElemPerCont]; |
- Context.insert<InstFakeDef>(SrcE); |
// Dest is a vector |
auto *VDest = llvm::dyn_cast<VariableVecOn32>(Dest); |
VDest->initVecElement(Func); |
@@ -3741,7 +3845,7 @@ void TargetMIPS32::lowerInsertElement(const InstInsertElement *Instr) { |
// Position of the element in the container |
uint32_t PosInCont = Index % ElemPerCont; |
// Load source vector in a temporary vector |
- for (SizeT i = 0; i < TVDest->ElementsPerContainer; ++i) { |
+ for (SizeT i = 0; i < TVDest->ContainersPerVector; ++i) { |
auto *DCont = TVDest->getContainers()[i]; |
// Do not define DstE as we are going to redefine it |
if (DCont == DstE) |
@@ -4292,7 +4396,6 @@ OperandMIPS32Mem *TargetMIPS32::formAddressingMode(Type Ty, Cfg *Func, |
} |
if (isVectorType(Ty)) { |
- UnimplementedError(getFlags()); |
return nullptr; |
} |
@@ -4435,7 +4538,7 @@ void TargetMIPS32::lowerRet(const InstRet *Instr) { |
Reg = getImplicitRet(); |
auto *RegT = legalizeToReg(Reg); |
// Return the vector through buffer in implicit argument a0 |
- for (SizeT i = 0; i < SrcVec->ElementsPerContainer; ++i) { |
+ for (SizeT i = 0; i < SrcVec->ContainersPerVector; ++i) { |
OperandMIPS32Mem *Mem = OperandMIPS32Mem::create( |
Func, IceType_f32, RegT, |
llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(i * 4))); |
@@ -4461,7 +4564,7 @@ void TargetMIPS32::lowerSelect(const InstSelect *Instr) { |
const Type DestTy = Dest->getType(); |
if (isVectorType(DestTy)) { |
- UnimplementedLoweringError(this, Instr); |
+ llvm::report_fatal_error("Select: Destination type is vector"); |
return; |
} |
@@ -4533,7 +4636,7 @@ void TargetMIPS32::lowerStore(const InstStore *Instr) { |
_sw(ValueLo, llvm::cast<OperandMIPS32Mem>(loOperand(NewAddr))); |
} else if (isVectorType(Value->getType())) { |
auto *DataVec = llvm::dyn_cast<VariableVecOn32>(Value); |
- for (SizeT i = 0; i < DataVec->ElementsPerContainer; ++i) { |
+ for (SizeT i = 0; i < DataVec->ContainersPerVector; ++i) { |
auto *DCont = legalizeToReg(DataVec->getContainers()[i]); |
auto *MCont = llvm::cast<OperandMIPS32Mem>( |
getOperandAtIndex(NewAddr, IceType_i32, i)); |