summaryrefslogtreecommitdiff
path: root/lib/Target/PowerPC/PPCFastISel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/PowerPC/PPCFastISel.cpp')
-rw-r--r--lib/Target/PowerPC/PPCFastISel.cpp71
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.