diff options
Diffstat (limited to 'lib/Target/PowerPC/PPCFastISel.cpp')
-rw-r--r-- | lib/Target/PowerPC/PPCFastISel.cpp | 71 |
1 files changed, 44 insertions, 27 deletions
diff --git a/lib/Target/PowerPC/PPCFastISel.cpp b/lib/Target/PowerPC/PPCFastISel.cpp index 16dcd468c91d6..7e92042d2f969 100644 --- a/lib/Target/PowerPC/PPCFastISel.cpp +++ b/lib/Target/PowerPC/PPCFastISel.cpp @@ -16,6 +16,7 @@ #include "PPC.h" #include "MCTargetDesc/PPCPredicates.h" #include "PPCCallingConv.h" +#include "PPCCCState.h" #include "PPCISelLowering.h" #include "PPCMachineFunctionInfo.h" #include "PPCSubtarget.h" @@ -158,7 +159,7 @@ class PPCFastISel final : public FastISel { unsigned FP64LoadOpc = PPC::LFD); bool PPCEmitStore(MVT VT, unsigned SrcReg, Address &Addr); bool PPCComputeAddress(const Value *Obj, Address &Addr); - void PPCSimplifyAddress(Address &Addr, MVT VT, bool &UseOffset, + void PPCSimplifyAddress(Address &Addr, bool &UseOffset, unsigned &IndexReg); bool PPCEmitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, unsigned DestReg, bool IsZExt); @@ -185,7 +186,7 @@ class PPCFastISel final : public FastISel { unsigned &NumBytes, bool IsVarArg); bool finishCall(MVT RetVT, CallLoweringInfo &CLI, unsigned &NumBytes); - CCAssignFn *usePPC32CCs(unsigned Flag); + LLVM_ATTRIBUTE_UNUSED CCAssignFn *usePPC32CCs(unsigned Flag); private: #include "PPCGenFastISel.inc" @@ -196,7 +197,7 @@ class PPCFastISel final : public FastISel { #include "PPCGenCallingConv.inc" -// Function whose sole purpose is to kill compiler warnings +// Function whose sole purpose is to kill compiler warnings // stemming from unused functions included from PPCGenCallingConv.inc. CCAssignFn *PPCFastISel::usePPC32CCs(unsigned Flag) { if (Flag == 1) @@ -213,13 +214,29 @@ static Optional<PPC::Predicate> getComparePred(CmpInst::Predicate Pred) { switch (Pred) { // These are not representable with any single compare. case CmpInst::FCMP_FALSE: + case CmpInst::FCMP_TRUE: + // Major concern about the following 6 cases is NaN result. The comparison + // result consists of 4 bits, indicating lt, eq, gt and un (unordered), + // only one of which will be set. The result is generated by fcmpu + // instruction. However, bc instruction only inspects one of the first 3 + // bits, so when un is set, bc instruction may jump to to an undesired + // place. + // + // More specifically, if we expect an unordered comparison and un is set, we + // expect to always go to true branch; in such case UEQ, UGT and ULT still + // give false, which are undesired; but UNE, UGE, ULE happen to give true, + // since they are tested by inspecting !eq, !lt, !gt, respectively. + // + // Similarly, for ordered comparison, when un is set, we always expect the + // result to be false. In such case OGT, OLT and OEQ is good, since they are + // actually testing GT, LT, and EQ respectively, which are false. OGE, OLE + // and ONE are tested through !lt, !gt and !eq, and these are true. case CmpInst::FCMP_UEQ: case CmpInst::FCMP_UGT: - case CmpInst::FCMP_UGE: case CmpInst::FCMP_ULT: - case CmpInst::FCMP_ULE: - case CmpInst::FCMP_UNE: - case CmpInst::FCMP_TRUE: + case CmpInst::FCMP_OGE: + case CmpInst::FCMP_OLE: + case CmpInst::FCMP_ONE: default: return Optional<PPC::Predicate>(); @@ -232,7 +249,7 @@ static Optional<PPC::Predicate> getComparePred(CmpInst::Predicate Pred) { case CmpInst::ICMP_SGT: return PPC::PRED_GT; - case CmpInst::FCMP_OGE: + case CmpInst::FCMP_UGE: case CmpInst::ICMP_UGE: case CmpInst::ICMP_SGE: return PPC::PRED_GE; @@ -242,12 +259,12 @@ static Optional<PPC::Predicate> getComparePred(CmpInst::Predicate Pred) { case CmpInst::ICMP_SLT: return PPC::PRED_LT; - case CmpInst::FCMP_OLE: + case CmpInst::FCMP_ULE: case CmpInst::ICMP_ULE: case CmpInst::ICMP_SLE: return PPC::PRED_LE; - case CmpInst::FCMP_ONE: + case CmpInst::FCMP_UNE: case CmpInst::ICMP_NE: return PPC::PRED_NE; @@ -412,7 +429,7 @@ bool PPCFastISel::PPCComputeAddress(const Value *Obj, Address &Addr) { // Fix up some addresses that can't be used directly. For example, if // an offset won't fit in an instruction field, we may need to move it // into an index register. -void PPCFastISel::PPCSimplifyAddress(Address &Addr, MVT VT, bool &UseOffset, +void PPCFastISel::PPCSimplifyAddress(Address &Addr, bool &UseOffset, unsigned &IndexReg) { // Check whether the offset fits in the instruction field. @@ -431,8 +448,7 @@ void PPCFastISel::PPCSimplifyAddress(Address &Addr, MVT VT, bool &UseOffset, } if (!UseOffset) { - IntegerType *OffsetTy = ((VT == MVT::i32) ? Type::getInt32Ty(*Context) - : Type::getInt64Ty(*Context)); + IntegerType *OffsetTy = Type::getInt64Ty(*Context); const ConstantInt *Offset = ConstantInt::getSigned(OffsetTy, (int64_t)(Addr.Offset)); IndexReg = PPCMaterializeInt(Offset, MVT::i64); @@ -501,7 +517,7 @@ bool PPCFastISel::PPCEmitLoad(MVT VT, unsigned &ResultReg, Address &Addr, // If necessary, materialize the offset into a register and use // the indexed form. Also handle stack pointers with special needs. unsigned IndexReg = 0; - PPCSimplifyAddress(Addr, VT, UseOffset, IndexReg); + PPCSimplifyAddress(Addr, UseOffset, IndexReg); // If this is a potential VSX load with an offset of 0, a VSX indexed load can // be used. @@ -637,7 +653,7 @@ bool PPCFastISel::PPCEmitStore(MVT VT, unsigned SrcReg, Address &Addr) { // If necessary, materialize the offset into a register and use // the indexed form. Also handle stack pointers with special needs. unsigned IndexReg = 0; - PPCSimplifyAddress(Addr, VT, UseOffset, IndexReg); + PPCSimplifyAddress(Addr, UseOffset, IndexReg); // If this is a potential VSX store with an offset of 0, a VSX indexed store // can be used. @@ -1068,10 +1084,10 @@ unsigned PPCFastISel::PPCMoveToIntReg(const Instruction *I, MVT VT, if (!PPCEmitStore(MVT::f64, SrcReg, Addr)) return 0; - // Reload it into a GPR. If we want an i32, modify the address - // to have a 4-byte offset so we load from the right place. + // Reload it into a GPR. If we want an i32 on big endian, modify the + // address to have a 4-byte offset so we load from the right place. if (VT == MVT::i32) - Addr.Offset = 4; + Addr.Offset = (PPCSubTarget->isLittleEndian()) ? 0 : 4; // Look at the currently assigned register for this instruction // to determine the required register class. @@ -1115,14 +1131,13 @@ bool PPCFastISel::SelectFPToI(const Instruction *I, bool IsSigned) { return false; // Convert f32 to f64 if necessary. This is just a meaningless copy - // to get the register class right. COPY_TO_REGCLASS is needed since - // a COPY from F4RC to F8RC is converted to a F4RC-F4RC copy downstream. + // to get the register class right. const TargetRegisterClass *InRC = MRI.getRegClass(SrcReg); if (InRC == &PPC::F4RCRegClass) { unsigned TmpReg = createResultReg(&PPC::F8RCRegClass); BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, - TII.get(TargetOpcode::COPY_TO_REGCLASS), TmpReg) - .addReg(SrcReg).addImm(PPC::F8RCRegClassID); + TII.get(TargetOpcode::COPY), TmpReg) + .addReg(SrcReg); SrcReg = TmpReg; } @@ -1583,6 +1598,9 @@ bool PPCFastISel::SelectRet(const Instruction *I) { if (!FuncInfo.CanLowerReturn) return false; + if (TLI.supportSplitCSR(FuncInfo.MF)) + return false; + const ReturnInst *Ret = cast<ReturnInst>(I); const Function &F = *I->getParent()->getParent(); @@ -2071,7 +2089,6 @@ unsigned PPCFastISel::PPCMaterialize64BitInt(int64_t Imm, return TmpReg3; } - // Materialize an integer constant into a register, and return // the register number (or zero if we failed to handle it). unsigned PPCFastISel::PPCMaterializeInt(const ConstantInt *CI, MVT VT, @@ -2085,12 +2102,12 @@ unsigned PPCFastISel::PPCMaterializeInt(const ConstantInt *CI, MVT VT, return ImmReg; } - if (VT != MVT::i64 && VT != MVT::i32 && VT != MVT::i16 && - VT != MVT::i8 && VT != MVT::i1) + if (VT != MVT::i64 && VT != MVT::i32 && VT != MVT::i16 && VT != MVT::i8 && + VT != MVT::i1) return 0; - const TargetRegisterClass *RC = ((VT == MVT::i64) ? &PPC::G8RCRegClass : - &PPC::GPRCRegClass); + const TargetRegisterClass *RC = + ((VT == MVT::i64) ? &PPC::G8RCRegClass : &PPC::GPRCRegClass); int64_t Imm = UseSExt ? CI->getSExtValue() : CI->getZExtValue(); // If the constant is in range, use a load-immediate. |