Index: lib/Target/Mips/MipsCallingConv.td =================================================================== --- lib/Target/Mips/MipsCallingConv.td +++ lib/Target/Mips/MipsCallingConv.td @@ -13,7 +13,7 @@ class CCIfSubtarget : CCIf" - "(State.getMachineFunction().getSubtarget()).", + "(State.getMachineFunction().getSubtarget()).", F), A>; @@ -51,6 +51,19 @@ // Mips O32 Calling Convention //===----------------------------------------------------------------------===// +def CC_MipsO32 : CallingConv<[ + // Promote i8/i16 arguments to i32. + CCIfType<[i1, i8, i16], CCPromoteToType>, + + // Integer values get stored in stack slots that are 4 bytes in + // size and 4-byte aligned. + CCIfType<[i32, f32], CCAssignToStack<4, 4>>, + + // Integer values get stored in stack slots that are 8 bytes in + // size and 8-byte aligned. + CCIfType<[f64], CCAssignToStack<8, 8>> +]>; + // Only the return rules are defined here for O32. The rules for argument // passing are defined in MipsISelLowering.cpp. def RetCC_MipsO32 : CallingConv<[ Index: lib/Target/Mips/MipsFastISel.cpp =================================================================== --- lib/Target/Mips/MipsFastISel.cpp +++ lib/Target/Mips/MipsFastISel.cpp @@ -68,6 +68,8 @@ // Convenience variables to avoid some queries. LLVMContext *Context; + bool fastLowerCall(CallLoweringInfo &CLI) override; + bool TargetSupported; bool UnsupportedFPMode; // To allow fast-isel to proceed and just not handle // floating point but not reject doing fast-isel in other @@ -87,17 +89,21 @@ bool selectIntExt(const Instruction *I); // Utility helper routines. - bool isTypeLegal(Type *Ty, MVT &VT); bool isLoadTypeLegal(Type *Ty, MVT &VT); bool computeAddress(const Value *Obj, Address &Addr); + bool computeCallAddress(const Value *V, Address &Addr); + // Emit helper routines. bool emitCmp(unsigned DestReg, const CmpInst *CI); bool emitLoad(MVT VT, unsigned &ResultReg, Address &Addr, unsigned Alignment = 0); + bool emitStore(MVT VT, unsigned SrcReg, Address Addr, + MachineMemOperand *MMO = nullptr); bool emitStore(MVT VT, unsigned SrcReg, Address &Addr, unsigned Alignment = 0); + unsigned emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, bool isZExt); bool emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, unsigned DestReg, bool IsZExt); @@ -140,9 +146,15 @@ return 0; } + // Call handling routines. +private: + CCAssignFn *CCAssignFnForCall(CallingConv::ID CC) const; + bool processCallArgs(CallLoweringInfo &CLI, SmallVectorImpl &ArgVTs, + unsigned &NumBytes); + bool finishCall(CallLoweringInfo &CLI, MVT RetVT, unsigned NumBytes); + public: // Backend specific FastISel code. - explicit MipsFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo) : FastISel(funcInfo, libInfo), @@ -166,6 +178,44 @@ }; } // end anonymous namespace. +#include "MipsGenCallingConv.inc" + +static bool CC_Mips16RetHelper(unsigned ValNo, MVT ValVT, + MVT LocVT, CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, CCState &State) +__attribute__((unused)); + + +static bool CC_MipsN(unsigned ValNo, MVT ValVT, + MVT LocVT, CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, CCState &State) +__attribute__((unused)); + +static bool CC_MipsN_VarArg(unsigned ValNo, MVT ValVT, + MVT LocVT, CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, CCState &State) +__attribute__((unused)); + +static bool CC_Mips_FastCC(unsigned ValNo, MVT ValVT, + MVT LocVT, CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, CCState &State) +__attribute__((unused)); + +static bool RetCC_F128(unsigned ValNo, MVT ValVT, + MVT LocVT, CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, CCState &State) +__attribute__((unused)); + +static bool RetCC_Mips(unsigned ValNo, MVT ValVT, + MVT LocVT, CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, CCState &State) +__attribute__((unused)); + + +CCAssignFn *MipsFastISel::CCAssignFnForCall(CallingConv::ID CC) const { + return CC_MipsO32; +} + unsigned MipsFastISel::materializeInt(const Constant *C, MVT VT) { if (VT != MVT::i32 && VT != MVT::i16 && VT != MVT::i8 && VT != MVT::i1) return 0; @@ -284,6 +334,19 @@ return Addr.getReg() != 0; } +bool MipsFastISel::computeCallAddress(const Value *V, Address &Addr) { + const GlobalValue *GV = dyn_cast(V); + if (GV && isa(GV) && dyn_cast(GV)->isIntrinsic()) + return false; + if (!GV) + return false; + if (const GlobalValue *GV = dyn_cast(V)) { + Addr.setGlobalValue(GV); + return true; + } + return false; +} + bool MipsFastISel::isTypeLegal(Type *Ty, MVT &VT) { EVT evt = TLI.getValueType(Ty, true); // Only handle simple types. @@ -694,6 +757,253 @@ return true; } // +bool MipsFastISel::processCallArgs(CallLoweringInfo &CLI, + SmallVectorImpl &OutVTs, + unsigned &NumBytes) { + // for now we don't handle any arguments + CallingConv::ID CC = CLI.CallConv; + SmallVector ArgLocs; + CCState CCInfo(CC, false, *FuncInfo.MF, ArgLocs, *Context); + CCInfo.AnalyzeCallOperands(OutVTs, CLI.OutFlags, CCAssignFnForCall(CC)); + // Get a count of how many bytes are to be pushed on the stack. + NumBytes = CCInfo.getNextStackOffset(); + // this is the minimum argument area, used for A0-A3 if needed + if (NumBytes < 16) + NumBytes = 16; + + emitInst(Mips::ADJCALLSTACKDOWN).addImm(16); + // Process the args. + MVT firstMVT; + for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { + CCValAssign &VA = ArgLocs[i]; + const Value *ArgVal = CLI.OutVals[VA.getValNo()]; + MVT ArgVT = OutVTs[VA.getValNo()]; + + if (i == 0) { + firstMVT = ArgVT; + if (ArgVT == MVT::f32) { + VA.convertToReg(Mips::F12); + } else if (ArgVT == MVT::f64) { + VA.convertToReg(Mips::D6); + } + } else if (i == 1) { + if ((firstMVT == MVT::f32) || (firstMVT == MVT::f64)) { + if (ArgVT == MVT::f32) { + VA.convertToReg(Mips::F14); + } else if (ArgVT == MVT::f64) { + VA.convertToReg(Mips::D7); + } + } + } + if (((ArgVT == MVT::i32) || (ArgVT == MVT::f32)) && VA.isMemLoc()) { + switch (VA.getLocMemOffset()) { + case 0: + VA.convertToReg(Mips::A0); + break; + case 4: + VA.convertToReg(Mips::A1); + break; + case 8: + VA.convertToReg(Mips::A2); + break; + case 12: + VA.convertToReg(Mips::A3); + break; + default: + break; + } + } + unsigned ArgReg = getRegForValue(ArgVal); + if (!ArgReg) + return false; + + // Handle arg promotion: SExt, ZExt, AExt. + switch (VA.getLocInfo()) { + case CCValAssign::Full: + break; + case CCValAssign::SExt: { + MVT DestVT = VA.getLocVT(); + MVT SrcVT = ArgVT; + ArgReg = emitIntExt(SrcVT, ArgReg, DestVT, /*isZExt=*/false); + if (!ArgReg) + return false; + break; + } + case CCValAssign::AExt: + // Intentional fall-through. + case CCValAssign::ZExt: { + MVT DestVT = VA.getLocVT(); + MVT SrcVT = ArgVT; + ArgReg = emitIntExt(SrcVT, ArgReg, DestVT, /*isZExt=*/true); + if (!ArgReg) + return false; + break; + } + default: + llvm_unreachable("Unknown arg promotion!"); + } + + // Now copy/store arg to correct locations. + if (VA.isRegLoc() && !VA.needsCustom()) { + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, + TII.get(TargetOpcode::COPY), VA.getLocReg()).addReg(ArgReg); + CLI.OutRegs.push_back(VA.getLocReg()); + } else if (VA.needsCustom()) { + // FIXME: Handle custom args. + return false; + } else { + // + // FIXME: This path will currently return false. It was copied + // from the AARch64 port and should be essentially fine for Mips too + // but the finish work on it will be enabled in a follow on patch. + // + assert(VA.isMemLoc() && "Assuming store on stack."); + // Don't emit stores for undef values. + if (isa(ArgVal)) + continue; + + // Need to store on the stack. + unsigned ArgSize = (ArgVT.getSizeInBits() + 7) / 8; + + unsigned BEAlign = 0; + if (ArgSize < 8 && !Subtarget->isLittle()) + BEAlign = 8 - ArgSize; + + Address Addr; + Addr.setKind(Address::RegBase); + Addr.setReg(Mips::SP); + Addr.setOffset(VA.getLocMemOffset() + BEAlign); + + unsigned Alignment = DL.getABITypeAlignment(ArgVal->getType()); + MachineMemOperand *MMO = FuncInfo.MF->getMachineMemOperand( + MachinePointerInfo::getStack(Addr.getOffset()), + MachineMemOperand::MOStore, ArgVT.getStoreSize(), Alignment); + (void)(MMO); + // if (!emitStore(ArgVT, ArgReg, Addr, MMO)) + return false; // can't store on the stack yet. + } + } + + if (NumBytes < 16) + NumBytes = 16; + return true; +} + +bool MipsFastISel::finishCall(CallLoweringInfo &CLI, MVT RetVT, + unsigned NumBytes) { + CallingConv::ID CC = CLI.CallConv; + emitInst(Mips::ADJCALLSTACKUP).addImm(16); + if (RetVT != MVT::isVoid) { + SmallVector RVLocs; + CCState CCInfo(CC, false, *FuncInfo.MF, RVLocs, *Context); + CCInfo.AnalyzeCallResult(RetVT, RetCC_Mips); + + // Only handle a single return value. + if (RVLocs.size() != 1) + return false; + // Copy all of the result registers out of their specified physreg. + MVT CopyVT = RVLocs[0].getValVT(); + // Special handling for extended integers. + if (RetVT == MVT::i1 || RetVT == MVT::i8 || RetVT == MVT::i16) + CopyVT = MVT::i32; + + unsigned ResultReg = createResultReg(TLI.getRegClassFor(CopyVT)); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, + TII.get(TargetOpcode::COPY), + ResultReg).addReg(RVLocs[0].getLocReg()); + CLI.InRegs.push_back(RVLocs[0].getLocReg()); + + CLI.ResultReg = ResultReg; + CLI.NumResultRegs = 1; + } + return true; +} + +bool MipsFastISel::fastLowerCall(CallLoweringInfo &CLI) { + CallingConv::ID CC = CLI.CallConv; + bool IsTailCall = CLI.IsTailCall; + bool IsVarArg = CLI.IsVarArg; + const Value *Callee = CLI.Callee; + // const char *SymName = CLI.SymName; + + // Allow SelectionDAG isel to handle tail calls. + if (IsTailCall) + return false; + + // Let SDISel handle vararg functions. + if (IsVarArg) + return false; + + // FIXME: Only handle *simple* calls for now. + MVT RetVT; + if (CLI.RetTy->isVoidTy()) + RetVT = MVT::isVoid; + else if (!isTypeLegal(CLI.RetTy, RetVT)) + return false; + + for (auto Flag : CLI.OutFlags) + if (Flag.isInReg() || Flag.isSRet() || Flag.isNest() || Flag.isByVal()) + return false; + + // Set up the argument vectors. + SmallVector OutVTs; + OutVTs.reserve(CLI.OutVals.size()); + + for (auto *Val : CLI.OutVals) { + MVT VT; + if (!isTypeLegal(Val->getType(), VT) && + !(VT == MVT::i1 || VT == MVT::i8 || VT == MVT::i16)) + return false; + + // We don't handle vector parameters yet. + if (VT.isVector() || VT.getSizeInBits() > 64) + return false; + + OutVTs.push_back(VT); + } + + Address Addr; + if (!computeCallAddress(Callee, Addr)) + return false; + + // Handle the arguments now that we've gotten them. + unsigned NumBytes; + if (!processCallArgs(CLI, OutVTs, NumBytes)) + return false; + + // Issue the call. + // emitInst(Mips::ADDu, Mips::GP).addReg(MFI->getGlobalBaseReg()).addReg( + // Mips::ZERO); + unsigned DestAddress = materializeGV(Addr.getGlobalValue(), MVT::i32); + emitInst(TargetOpcode::COPY, Mips::T9).addReg(DestAddress); + MachineInstrBuilder MIB = + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Mips::JALR), + Mips::RA).addReg(Mips::T9); + // Mips::RA).addReg(DestAddress) + + // Add implicit physical register uses to the call. + for (auto Reg : CLI.OutRegs) + MIB.addReg(Reg, RegState::Implicit); + + // Add a register mask with the call-preserved registers. + // Proper defs for return values will be added by setPhysRegsDeadExcept(). + MIB.addRegMask(TRI.getCallPreservedMask(CC)); + + CLI.Call = MIB; + + // Add implicit physical register uses to the call. + for (auto Reg : CLI.OutRegs) + MIB.addReg(Reg, RegState::Implicit); + + // Add a register mask with the call-preserved registers. Proper + // defs for return values will be added by setPhysRegsDeadExcept(). + MIB.addRegMask(TRI.getCallPreservedMask(CC)); + + CLI.Call = MIB; + // Finish off the call including any return values. + return finishCall(CLI, RetVT, NumBytes); +} + bool MipsFastISel::selectRet(const Instruction *I) { const ReturnInst *Ret = cast(I); @@ -812,6 +1122,7 @@ break; case MVT::i16: emitInst(Mips::ANDi, DestReg).addReg(SrcReg).addImm(0xffff); + break; } return true; } @@ -822,6 +1133,13 @@ return emitIntZExt(SrcVT, SrcReg, DestVT, DestReg); return emitIntSExt(SrcVT, SrcReg, DestVT, DestReg); } + +unsigned MipsFastISel::emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, + bool isZExt) { + unsigned DestReg = createResultReg(&Mips::GPR32RegClass); + return emitIntExt(SrcVT, SrcReg, DestVT, DestReg, isZExt); +} + bool MipsFastISel::fastSelectInstruction(const Instruction *I) { if (!TargetSupported) return false; Index: lib/Target/Mips/MipsISelLowering.h =================================================================== --- lib/Target/Mips/MipsISelLowering.h +++ lib/Target/Mips/MipsISelLowering.h @@ -601,6 +601,53 @@ MachineBasicBlock *emitSEL_D(MachineInstr *MI, MachineBasicBlock *BB) const; }; + + class MipsCCState : public CCState { + private: + /// Identify lowered values that originated from f128 arguments and record + /// this for use by RetCC_MipsN. + void + PreAnalyzeCallResultForF128(const SmallVectorImpl &Ins, + const TargetLowering::CallLoweringInfo &CLI); + + /// Identify lowered values that originated from f128 arguments and record + /// this for use by RetCC_MipsN. + void PreAnalyzeReturnForF128(const SmallVectorImpl &Outs); + + /// Records whether the value has been lowered from an f128. + SmallVector OriginalArgWasF128; + + public: + MipsCCState(CallingConv::ID CC, bool isVarArg, MachineFunction &MF, + SmallVectorImpl &locs, LLVMContext &C) + : CCState(CC, isVarArg, MF, locs, C) {} + + void AnalyzeCallResult(const SmallVectorImpl &Ins, + CCAssignFn Fn, + const TargetLowering::CallLoweringInfo &CLI) { + PreAnalyzeCallResultForF128(Ins, CLI); + CCState::AnalyzeCallResult(Ins, Fn); + OriginalArgWasF128.clear(); + } + + void AnalyzeReturn(const SmallVectorImpl &Outs, + CCAssignFn Fn) { + PreAnalyzeReturnForF128(Outs); + CCState::AnalyzeReturn(Outs, Fn); + OriginalArgWasF128.clear(); + } + + bool CheckReturn(const SmallVectorImpl &ArgsFlags, + CCAssignFn Fn) { + PreAnalyzeReturnForF128(ArgsFlags); + bool Return = CCState::CheckReturn(ArgsFlags, Fn); + OriginalArgWasF128.clear(); + return Return; + } + + bool WasOriginalArgF128(unsigned ValNo) { return OriginalArgWasF128[ValNo]; } + }; + /// Create MipsTargetLowering objects. const MipsTargetLowering * createMips16TargetLowering(const MipsTargetMachine &TM, @@ -615,4 +662,5 @@ } } + #endif Index: lib/Target/Mips/MipsISelLowering.cpp =================================================================== --- lib/Target/Mips/MipsISelLowering.cpp +++ lib/Target/Mips/MipsISelLowering.cpp @@ -73,63 +73,24 @@ static bool originalTypeIsF128(const Type *Ty, const SDNode *CallNode); -namespace { -class MipsCCState : public CCState { -private: - /// Identify lowered values that originated from f128 arguments and record - /// this for use by RetCC_MipsN. - void - PreAnalyzeCallResultForF128(const SmallVectorImpl &Ins, - const TargetLowering::CallLoweringInfo &CLI) { - for (unsigned i = 0; i < Ins.size(); ++i) - OriginalArgWasF128.push_back( - originalTypeIsF128(CLI.RetTy, CLI.Callee.getNode())); - } - - /// Identify lowered values that originated from f128 arguments and record - /// this for use by RetCC_MipsN. - void PreAnalyzeReturnForF128(const SmallVectorImpl &Outs) { - const MachineFunction &MF = getMachineFunction(); - for (unsigned i = 0; i < Outs.size(); ++i) - OriginalArgWasF128.push_back( - originalTypeIsF128(MF.getFunction()->getReturnType(), nullptr)); - } - - /// Records whether the value has been lowered from an f128. - SmallVector OriginalArgWasF128; - -public: - MipsCCState(CallingConv::ID CC, bool isVarArg, MachineFunction &MF, - SmallVectorImpl &locs, LLVMContext &C) - : CCState(CC, isVarArg, MF, locs, C) {} - - void AnalyzeCallResult(const SmallVectorImpl &Ins, - CCAssignFn Fn, - const TargetLowering::CallLoweringInfo &CLI) { - PreAnalyzeCallResultForF128(Ins, CLI); - CCState::AnalyzeCallResult(Ins, Fn); - OriginalArgWasF128.clear(); - } - void AnalyzeReturn(const SmallVectorImpl &Outs, - CCAssignFn Fn) { - PreAnalyzeReturnForF128(Outs); - CCState::AnalyzeReturn(Outs, Fn); - OriginalArgWasF128.clear(); - } - - bool CheckReturn(const SmallVectorImpl &ArgsFlags, - CCAssignFn Fn) { - PreAnalyzeReturnForF128(ArgsFlags); - bool Return = CCState::CheckReturn(ArgsFlags, Fn); - OriginalArgWasF128.clear(); - return Return; - } +void llvm::MipsCCState::PreAnalyzeCallResultForF128(const SmallVectorImpl &Ins, + const TargetLowering::CallLoweringInfo &CLI) { + for (unsigned i = 0; i < Ins.size(); ++i) + OriginalArgWasF128.push_back( + originalTypeIsF128(CLI.RetTy, CLI.Callee.getNode())); +} - bool WasOriginalArgF128(unsigned ValNo) { return OriginalArgWasF128[ValNo]; } -}; +/// Identify lowered values that originated from f128 arguments and record +/// this for use by RetCC_MipsN. +void llvm::MipsCCState::PreAnalyzeReturnForF128(const SmallVectorImpl &Outs) { + const MachineFunction &MF = getMachineFunction(); + for (unsigned i = 0; i < Outs.size(); ++i) + OriginalArgWasF128.push_back( + originalTypeIsF128(MF.getFunction()->getReturnType(), nullptr)); } + // If I is a shifted mask, set the size (Size) and the first bit of the // mask (Pos), and return true. // For example, if I is 0x003ff800, (Pos, Size) = (11, 11). Index: test/CodeGen/Mips/Fast-ISel/callabi.ll =================================================================== --- /dev/null +++ test/CodeGen/Mips/Fast-ISel/callabi.ll @@ -0,0 +1,477 @@ +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32r2 \ +; RUN: < %s | FileCheck %s +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32 \ +; RUN: < %s | FileCheck %s +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32r2 \ +; RUN: < %s | FileCheck %s -check-prefix=mips32r2 +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32 \ +; RUN: < %s | FileCheck %s -check-prefix=mips32 +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32r2 \ +; RUN: < %s | FileCheck %s -check-prefix=CHECK2 +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32 \ +; RUN: < %s | FileCheck %s -check-prefix=CHECK2 + + +@c1 = global i8 -45, align 1 +@uc1 = global i8 27, align 1 +@s1 = global i16 -1789, align 2 +@us1 = global i16 1256, align 2 + +; Function Attrs: nounwind +define void @cxi() #0 { +entry: +; CHECK-LABEL: cxi + call void @xi(i32 10) +; CHECK-DAG: addiu $4, $zero, 10 +; CHECK-DAG: lw $25, %got(xi)(${{[0-9]+}}) +; CHECK: jalr $25 + + ret void +} + +declare void @xi(i32) #1 + +; Function Attrs: nounwind +define void @cxii() #0 { +entry: +; CHECK-LABEL: cxii + call void @xii(i32 746, i32 892) +; CHECK-DAG: addiu $4, $zero, 746 +; CHECK-DAG: addiu $5, $zero, 892 +; CHECK-DAG: lw $25, %got(xii)(${{[0-9]+}}) +; CHECK: jalr $25 + + ret void +} + +declare void @xii(i32, i32) #1 + +; Function Attrs: nounwind +define void @cxiii() #0 { +entry: +; CHECK-LABEL: cxiii + call void @xiii(i32 88, i32 44, i32 11) +; CHECK-DAG: addiu $4, $zero, 88 +; CHECK-DAG: addiu $5, $zero, 44 +; CHECK-DAG: addiu $6, $zero, 11 +; CHECK-DAG: lw $25, %got(xiii)(${{[0-9]+}}) +; CHECK: jalr $25 + ret void +} + +declare void @xiii(i32, i32, i32) #1 + +; Function Attrs: nounwind +define void @cxiiii() #0 { +entry: +; CHECK-LABEL: cxiiii + call void @xiiii(i32 167, i32 320, i32 97, i32 14) +; CHECK-DAG: addiu $4, $zero, 167 +; CHECK-DAG: addiu $5, $zero, 320 +; CHECK-DAG: addiu $6, $zero, 97 +; CHECK-DAG: addiu $7, $zero, 14 +; CHECK-DAG: lw $25, %got(xiiii)(${{[0-9]+}}) +; CHECK: jalr $25 + + ret void +} + +declare void @xiiii(i32, i32, i32, i32) #1 + +; Function Attrs: nounwind +define void @cxiiiiconv() #0 { +entry: +; CHECK-LABEL: cxiiiiconv +; mips32r2-LABEL: cxiiiiconv +; mips32-LABEL: cxiiiiconv + %0 = load i8* @c1, align 1 + %conv = sext i8 %0 to i32 + %1 = load i8* @uc1, align 1 + %conv1 = zext i8 %1 to i32 + %2 = load i16* @s1, align 2 + %conv2 = sext i16 %2 to i32 + %3 = load i16* @us1, align 2 + %conv3 = zext i16 %3 to i32 + call void @xiiii(i32 %conv, i32 %conv1, i32 %conv2, i32 %conv3) +; CHECK: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; mips32r2: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; mips32: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; mips32r2-DAG: lw $[[REG_C1_ADDR:[0-9]+]], %got(c1)($[[REG_GP]]) +; mips32r2-DAG: lbu $[[REG_C1:[0-9]+]], 0($[[REG_C1_ADDR]]) +; mips32r2-DAG seb $3, $[[REG_C1]] +; mips32-DAG: lw $[[REG_C1_ADDR:[0-9]+]], %got(c1)($[[REG_GP]]) +; mips32-DAG: lbu $[[REG_C1:[0-9]+]], 0($[[REG_C1_ADDR]]) +; mips32-DAG: sll $[[REG_C1_1:[0-9]+]], $[[REG_C1]], 24 +; mips32-DAG: sra $4, $[[REG_C1_1]], 24 +; CHECK-DAG: lw $[[REG_UC1_ADDR:[0-9]+]], %got(uc1)($[[REG_GP]]) +; CHECK-DAG: lbu $[[REG_UC1:[0-9]+]], 0($[[REG_UC1_ADDR]]) +; FIXME andi is superfulous +; CHECK-DAG: andi $5, $[[REG_UC1]], 255 +; mips32r2-DAG: lw $[[REG_S1_ADDR:[0-9]+]], %got(s1)($[[REG_GP]]) +; mips32r2-DAG: lhu $[[REG_S1:[0-9]+]], 0($[[REG_S1_ADDR]]) +; mips32r2-DAG: seh $6, $[[REG_S1]] +; mips32-DAG: lw $[[REG_S1_ADDR:[0-9]+]], %got(s1)($[[REG_GP]]) +; mips32-DAG: lhu $[[REG_S1:[0-9]+]], 0($[[REG_S1_ADDR]]) +; mips32-DAG: sll $[[REG_S1_1:[0-9]+]], $[[REG_S1]], 16 +; mips32-DAG: sra $6, $[[REG_S1_1]], 16 +; CHECK-DAG: lw $[[REG_US1_ADDR:[0-9]+]], %got(us1)($[[REG_GP]]) +; CHECK-DAG: lhu $[[REG_US1:[0-9]+]], 0($[[REG_US1_ADDR]]) +; FIXME andi is superfulous +; CHECK-DAG: andi $7, $[[REG_US1]], 65535 +; mips32r2: jalr $25 +; mips32r2: jalr $25 +; CHECK: jalr $25 + ret void +} + +; Function Attrs: nounwind +define void @cxf() #0 { +entry: +; CHECK-LABEL: cxf + call void @xf(float 0x40BBC85560000000) +; CHECK: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; CHECK: lui $[[REG_FPCONST_1:[0-9]+]], 17886 +; CHECK: ori $[[REG_FPCONST:[0-9]+]], $[[REG_FPCONST_1]], 17067 +; CHECK: mtc1 $[[REG_FPCONST]], $f12 +; CHECK: lw $25, %got(xf)($[[REG_GP]]) +; CHECK: jalr $25 + ret void +} + +declare void @xf(float) #1 + +; Function Attrs: nounwind +define void @cxff() #0 { +entry: +; CHECK-LABEL: cxff + call void @xff(float 0x3FF74A6CA0000000, float 0x401A2C0840000000) +; CHECK: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; CHECK-DAG: lui $[[REG_FPCONST_1:[0-9]+]], 16314 +; CHECK-DAG: ori $[[REG_FPCONST:[0-9]+]], $[[REG_FPCONST_1]], 21349 +; CHECK-DAG: mtc1 $[[REG_FPCONST]], $f12 +; CHECK-DAG: lui $[[REG_FPCONST_2:[0-9]+]], 16593 +; CHECK-DAG: ori $[[REG_FPCONST_3:[0-9]+]], $[[REG_FPCONST_2]], 24642 +; CHECK-DAG: mtc1 $[[REG_FPCONST_3]], $f14 +; CHECK: lw $25, %got(xff)($[[REG_GP]]) +; CHECK: jalr $25 + ret void +} + +declare void @xff(float, float) #1 + +; Function Attrs: nounwind +define void @cxfi() #0 { +entry: +; CHECK-LABEL: cxfi + call void @xfi(float 0x4013906240000000, i32 102) +; CHECK: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; CHECK-DAG: lui $[[REG_FPCONST_1:[0-9]+]], 16540 +; CHECK-DAG: ori $[[REG_FPCONST:[0-9]+]], $[[REG_FPCONST_1]], 33554 +; CHECK-DAG: mtc1 $[[REG_FPCONST]], $f12 +; CHECK-DAG: addiu $5, $zero, 102 +; CHECK: lw $25, %got(xfi)($[[REG_GP]]) +; CHECK: jalr $25 + + ret void +} + +declare void @xfi(float, i32) #1 + +; Function Attrs: nounwind +define void @cxfii() #0 { +entry: +; CHECK-LABEL: cxfii + call void @xfii(float 0x405EC7EE00000000, i32 9993, i32 10922) +; CHECK: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; CHECK-DAG: lui $[[REG_FPCONST_1:[0-9]+]], 17142 +; CHECK-DAG: ori $[[REG_FPCONST:[0-9]+]], $[[REG_FPCONST_1]], 16240 +; CHECK-DAG: mtc1 $[[REG_FPCONST]], $f12 +; CHECK-DAG: addiu $5, $zero, 9993 +; CHECK-DAG: addiu $6, $zero, 10922 +; CHECK: lw $25, %got(xfii)($[[REG_GP]]) +; CHECK: jalr $25 + ret void +} + +declare void @xfii(float, i32, i32) #1 + +; Function Attrs: nounwind +define void @cxfiii() #0 { +entry: +; CHECK-LABEL: cxfiii + call void @xfiii(float 0x405C072B20000000, i32 3948, i32 89011, i32 111222) +; CHECK: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; CHECK-DAG: lui $[[REG_FPCONST_1:[0-9]+]], 17120 +; CHECK-DAG: ori $[[REG_FPCONST:[0-9]+]], $[[REG_FPCONST_1]], 14681 +; CHECK-DAG: mtc1 $[[REG_FPCONST]], $f12 +; CHECK-DAG: addiu $5, $zero, 3948 +; CHECK-DAG: lui $[[REG_I_1:[0-9]+]], 1 +; CHECK-DAG: ori $6, $[[REG_I_1]], 23475 +; CHECK-DAG: lui $[[REG_I_2:[0-9]+]], 1 +; CHECK-DAG: ori $7, $[[REG_I_2]], 45686 +; CHECK: lw $25, %got(xfiii)($[[REG_GP]]) +; CHECK: jalr $25 + ret void +} + +declare void @xfiii(float, i32, i32, i32) #1 + +; Function Attrs: nounwind +define void @cxd() #0 { +entry: +; mips32r2-LABEL: cxd: +; mips32-LABEL: cxd: + call void @xd(double 5.994560e+02) +; mips32: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; mips32-DAG: lui $[[REG_FPCONST_1:[0-9]+]], 16514 +; mips32-DAG: ori $[[REG_FPCONST_2:[0-9]+]], $[[REG_FPCONST_1]], 48037 +; mips32-DAG: lui $[[REG_FPCONST_3:[0-9]+]], 58195 +; mips32-DAG: ori $[[REG_FPCONST_4:[0-9]+]], $[[REG_FPCONST_3]], 63439 +; mips32-DAG: mtc1 $[[REG_FPCONST_4]], $f12 +; mips32-DAG: mtc1 $[[REG_FPCONST_2]], $f13 +; mips32-DAG: lw $25, %got(xd)($[[REG_GP]]) +; mips32: jalr $25 +; mips32r2: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; mips32r2-DAG: lui $[[REG_FPCONST_1:[0-9]+]], 16514 +; mips32r2-DAG: ori $[[REG_FPCONST_2:[0-9]+]], $[[REG_FPCONST_1]], 48037 +; mips32r2-DAG: lui $[[REG_FPCONST_3:[0-9]+]], 58195 +; mips32r2-DAG: ori $[[REG_FPCONST_4:[0-9]+]], $[[REG_FPCONST_3]], 63439 +; mips32r2-DAG: mtc1 $[[REG_FPCONST_4]], $f12 +; mips32r2-DAG: mthc1 $[[REG_FPCONST_2]], $f12 +; mips32r2-DAG: lw $25, %got(xd)($[[REG_GP]]) +; mips32r2 : jalr $25 + ret void +} + +declare void @xd(double) #1 + +; Function Attrs: nounwind +define void @cxdd() #0 { +; mips32r2-LABEL: cxdd: +; mips32-LABEL: cxdd: +entry: + call void @xdd(double 1.234980e+03, double 0x40F5B331F7CED917) +; mips32: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; mips32-DAG: lui $[[REG_FPCONST_1:[0-9]+]], 16531 +; mips32-DAG: ori $[[REG_FPCONST_2:[0-9]+]], $[[REG_FPCONST_1]], 19435 +; mips32-DAG: lui $[[REG_FPCONST_3:[0-9]+]], 34078 +; mips32-DAG: ori $[[REG_FPCONST_4:[0-9]+]], $[[REG_FPCONST_3]], 47186 +; mips32-DAG: mtc1 $[[REG_FPCONST_4]], $f12 +; mips32-DAG: mtc1 $[[REG_FPCONST_2]], $f13 +; mips32-DAG: lui $[[REG_FPCONST_1:[0-9]+]], 16629 +; mips32-DAG: ori $[[REG_FPCONST_2:[0-9]+]], $[[REG_FPCONST_1]], 45873 +; mips32-DAG: lui $[[REG_FPCONST_3:[0-9]+]], 63438 +; mips32-DAG: ori $[[REG_FPCONST_4:[0-9]+]], $[[REG_FPCONST_3]], 55575 +; mips32-DAG: mtc1 $[[REG_FPCONST_4]], $f14 +; mips32-DAG: mtc1 $[[REG_FPCONST_2]], $f15 +; mips32-DAG: lw $25, %got(xdd)($[[REG_GP]]) +; mips32: jalr $25 +; mips32r2: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; mips32r2-DAG: lui $[[REG_FPCONST_1:[0-9]+]], 16531 +; mips32r2-DAG: ori $[[REG_FPCONST_2:[0-9]+]], $[[REG_FPCONST_1]], 19435 +; mips32r2-DAG: lui $[[REG_FPCONST_3:[0-9]+]], 34078 +; mips32r2-DAG: ori $[[REG_FPCONST_4:[0-9]+]], $[[REG_FPCONST_3]], 47186 +; mips32r2-DAG: mtc1 $[[REG_FPCONST_4]], $f12 +; mips32r2-DAG: mthc1 $[[REG_FPCONST_2]], $f12 +; mips32r2-DAG: lui $[[REG_FPCONST_1:[0-9]+]], 16629 +; mips32r2-DAG: ori $[[REG_FPCONST_2:[0-9]+]], $[[REG_FPCONST_1]], 45873 +; mips32r2-DAG: lui $[[REG_FPCONST_3:[0-9]+]], 63438 +; mips32r2-DAG: ori $[[REG_FPCONST_4:[0-9]+]], $[[REG_FPCONST_3]], 55575 +; mips32r2-DAG: mtc1 $[[REG_FPCONST_4]], $f14 +; mips32r2-DAG: mthc1 $[[REG_FPCONST_2]], $f14 +; mips32r2-DAG: lw $25, %got(xdd)($[[REG_GP]]) +; mips32r2 : jalr $25 + ret void +} + +declare void @xdd(double, double) #1 + +; Function Attrs: nounwind +define void @cxif() #0 { +entry: +; CHECK-LABEL: cxif: + call void @xif(i32 345, float 0x407BCE5A20000000) +; CHECK-DAG: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; CHECK-DAG: addiu $4, $zero, 345 +; CHECK-DAG: lui $[[REGF_1:[0-9]+]], 17374 +; CHECK-DAG: ori $[[REGF_2:[0-9]+]], $[[REGF_1]], 29393 +; CHECK-DAG: mtc1 $[[REGF_2]], $f[[REGF_3:[0-9]+]] +; CHECK-DAG: mfc1 $5, $f[[REGF_3]] +; CHECK-DAG: lw $25, %got(xif)($[[REG_GP]]) +; CHECK: jalr $25 + + ret void +} + +declare void @xif(i32, float) #1 + +; Function Attrs: nounwind +define void @cxiff() #0 { +entry: +; CHECK-LABEL: cxiff: +; CHECK2-LABEL: cxiff: + call void @xiff(i32 12239, float 0x408EDB3340000000, float 0x4013FFE5C0000000) +; We need to do the two floating point parameters in a separate +; check because we can't control the ordering of parts of the sequence +;; +; CHECK: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; CHECK: addiu $4, $zero, 12239 +; CHECK2: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; CHECK2: addiu $4, $zero, 12239 +; CHECK: lui $[[REGF_1:[0-9]+]], 17526 +; CHECK: ori $[[REGF_2:[0-9]+]], $[[REGF_1]], 55706 +; CHECK: mtc1 $[[REGF_2]], $f[[REGF_3:[0-9]+]] +; CHECK: mfc1 $5, $f[[REGF_3]] +; CHECK2: lui $[[REGF2_1:[0-9]+]], 16543 +; CHECK2: ori $[[REGF2_2:[0-9]+]], $[[REGF2_1]], 65326 +; CHECK2: mtc1 $[[REGF2_2]], $f[[REGF2_3:[0-9]+]] +; CHECK2: mfc1 $6, $f[[REGF2_3]] +; CHECK: lw $25, %got(xiff)($[[REG_GP]]) +; CHECK2: lw $25, %got(xiff)($[[REG_GP]]) +; CHECK: jalr $25 +; CHECK2: jalr $25 + ret void +} + +declare void @xiff(i32, float, float) #1 + +; Function Attrs: nounwind +define void @cxifi() #0 { +entry: +; CHECK: cxifi: + call void @xifi(i32 887, float 0x402277CEE0000000, i32 888) +; CHECK-DAG: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; CHECK-DAG: addiu $4, $zero, 887 +; CHECK-DAG: lui $[[REGF_1:[0-9]+]], 16659 +; CHECK-DAG: ori $[[REGF_2:[0-9]+]], $[[REGF_1]], 48759 +; CHECK-DAG: mtc1 $[[REGF_2]], $f[[REGF_3:[0-9]+]] +; CHECK-DAG: mfc1 $5, $f[[REGF_3]] +; CHECk-DAG: addiu $6, $zero, 888 +; CHECK-DAG: lw $25, %got(xifi)($[[REG_GP]]) +; CHECK: jalr $25 + + ret void +} + +declare void @xifi(i32, float, i32) #1 + +; Function Attrs: nounwind +define void @cxifif() #0 { +entry: +; CHECK: cxifif: +; CHECK2: cxifif: + call void @xifif(i32 67774, float 0x408EE0FBE0000000, i32 9991, float 0x40B15C8CC0000000) +; CHECK-DAG: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; CHECK-DAG: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; CHECK-DAG: lui $[[REGI:[0-9]+]], 1 +; CHECK-DAG: ori $4, $[[REGI]], 2238 +; CHECK-DAG: lui $[[REGF_1:[0-9]+]], 17527 +; CHECK-DAG: ori $[[REGF_2:[0-9]+]], $[[REGF_1]], 2015 +; CHECK-DAG: mtc1 $[[REGF_2]], $f[[REGF_3:[0-9]+]] +; CHECK-DAG: mfc1 $5, $f[[REGF_3]] +; CHECk-DAG: addiu $6, $zero, 888 +; CHECK2: lui $[[REGF2_1:[0-9]+]], 17802 +; CHECK2: ori $[[REGF2_2:[0-9]+]], $[[REGF2_1]], 58470 +; CHECK2: mtc1 $[[REGF2_2]], $f[[REGF2_3:[0-9]+]] +; CHECK2: mfc1 $7, $f[[REGF2_3]] +; CHECK: lw $25, %got(xifif)($[[REG_GP]]) +; CHECK2: lw $25, %got(xifif)($[[REG_GP]]) +; CHECK2: jalr $25 +; CHECK: jalr $25 + + ret void +} + +declare void @xifif(i32, float, i32, float) #1 + +; Function Attrs: nounwind +define void @cxiffi() #0 { +entry: +; CHECK-label: cxiffi: +; CHECK2-label: cxiffi: + call void @xiffi(i32 45, float 0x3FF6666660000000, float 0x408F333340000000, i32 234) +; CHECK-DAG: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; CHECK-DAG: addiu $4, $zero, 45 +; CHECK2-DAG: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; CHECK2-DAG: addiu $4, $zero, 45 +; CHECK-DAG: lui $[[REGF_1:[0-9]+]], 16307 +; CHECK-DAG: ori $[[REGF_2:[0-9]+]], $[[REGF_1]], 13107 +; CHECK-DAG: mtc1 $[[REGF_2]], $f[[REGF_3:[0-9]+]] +; CHECK-DAG: mfc1 $5, $f[[REGF_3]] +; CHECK2: lui $[[REGF2_1:[0-9]+]], 17529 +; CHECK2: ori $[[REGF2_2:[0-9]+]], $[[REGF2_1]], 39322 +; CHECK2: mtc1 $[[REGF2_2]], $f[[REGF2_3:[0-9]+]] +; CHECK2: mfc1 $6, $f[[REGF2_3]] +; CHECK-DAG: lw $25, %got(xiffi)($[[REG_GP]]) +; CHECK-DAG: addiu $7, $zero, 234 +; CHECK2-DAG: lw $25, %got(xiffi)($[[REG_GP]]) +; CHECK: jalr $25 +; CHECK2: jalr $25 + + ret void +} + +declare void @xiffi(i32, float, float, i32) #1 + +; Function Attrs: nounwind +define void @cxifii() #0 { +entry: +; CHECK-DAG: cxifii: + call void @xifii(i32 12239, float 0x408EDB3340000000, i32 998877, i32 1234) +; CHECK-DAG: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; CHECK-DAG: addiu $4, $zero, 12239 +; CHECK-DAG: lui $[[REGF_1:[0-9]+]], 17526 +; CHECK-DAG: ori $[[REGF_2:[0-9]+]], $[[REGF_1]], 55706 +; CHECK-DAG: mtc1 $[[REGF_2]], $f[[REGF_3:[0-9]+]] +; CHECK-DAG: mfc1 $5, $f[[REGF_3]] +; CHECK-DAG: lui $[[REGI2:[0-9]+]], 15 +; CHECK-DAG: ori $6, $[[REGI2]], 15837 +; CHECk-DAG: addiu $7, $zero, 1234 +; CHECK-DAG: lw $25, %got(xifii)($[[REG_GP]]) +; CHECK: jalr $25 + ret void +} + +declare void @xifii(i32, float, i32, i32) #1 + +; FIXME: this function will not pass yet. +; Function Attrs: nounwind +; define void @cxfid() #0 { +;entry: +; call void @xfid(float 0x4013B851E0000000, i32 811123, double 0x40934BFF487FCB92) +; ret void +;} + +declare void @xfid(float, i32, double) #1 + +; Function Attrs: nounwind +define void @g() #0 { +entry: + call void @cxi() + call void @cxii() + call void @cxiii() + call void @cxiiii() + call void @cxiiiiconv() + call void @cxf() + call void @cxff() + call void @cxd() + call void @cxfi() + call void @cxfii() + call void @cxfiii() + call void @cxdd() + call void @cxif() + call void @cxiff() + call void @cxifi() + call void @cxifii() + call void @cxifif() + call void @cxiffi() + ret void +} + + +attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } + +!llvm.ident = !{!0} + +!0 = metadata !{metadata !"clang version 3.6.0 (gitosis@dmz-portal.mips.com:clang 43992fe7b17de5553ac06d323cb80cc6723a9ae3) (gitosis@dmz-portal.mips.com:llvm.git 0834e6839eb170197c81bb02e916258d1527e312)"} Index: test/CodeGen/Mips/Fast-ISel/icmpa.ll =================================================================== --- test/CodeGen/Mips/Fast-ISel/icmpa.ll +++ test/CodeGen/Mips/Fast-ISel/icmpa.ll @@ -208,3 +208,4 @@ store i32 %conv, i32* @b1, align 4 ret void } +