diff options
Diffstat (limited to 'lib/Target/PowerPC')
| -rw-r--r-- | lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp | 4 | ||||
| -rw-r--r-- | lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h | 5 | ||||
| -rw-r--r-- | lib/Target/PowerPC/PPCISelLowering.cpp | 35 | ||||
| -rw-r--r-- | lib/Target/PowerPC/PPCInstrInfo.cpp | 86 | ||||
| -rw-r--r-- | lib/Target/PowerPC/PPCInstrInfo.h | 2 | ||||
| -rw-r--r-- | lib/Target/PowerPC/PPCMIPeephole.cpp | 2 | ||||
| -rw-r--r-- | lib/Target/PowerPC/PPCPreEmitPeephole.cpp | 2 |
7 files changed, 104 insertions, 32 deletions
diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp index 2a1de244da923..728e7757fd28f 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp +++ b/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp @@ -18,6 +18,7 @@ #include "llvm/MC/MCMachObjectWriter.h" #include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSymbolELF.h" #include "llvm/MC/MCValue.h" #include "llvm/Support/ErrorHandling.h" @@ -231,9 +232,10 @@ namespace { } // end anonymous namespace MCAsmBackend *llvm::createPPCAsmBackend(const Target &T, + const MCSubtargetInfo &STI, const MCRegisterInfo &MRI, - const Triple &TT, StringRef CPU, const MCTargetOptions &Options) { + const Triple &TT = STI.getTargetTriple(); if (TT.isOSDarwin()) return new DarwinPPCAsmBackend(T); diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h b/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h index 80a74c09a598a..d47b9a6e452ca 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h +++ b/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h @@ -29,6 +29,7 @@ class MCContext; class MCInstrInfo; class MCObjectWriter; class MCRegisterInfo; +class MCSubtargetInfo; class MCTargetOptions; class Target; class Triple; @@ -43,8 +44,8 @@ MCCodeEmitter *createPPCMCCodeEmitter(const MCInstrInfo &MCII, const MCRegisterInfo &MRI, MCContext &Ctx); -MCAsmBackend *createPPCAsmBackend(const Target &T, const MCRegisterInfo &MRI, - const Triple &TT, StringRef CPU, +MCAsmBackend *createPPCAsmBackend(const Target &T, const MCSubtargetInfo &STI, + const MCRegisterInfo &MRI, const MCTargetOptions &Options); /// Construct an PPC ELF object writer. diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index cea59de3e8a9d..f9de65fcb1df5 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -4397,13 +4397,18 @@ hasSameArgumentList(const Function *CallerFn, ImmutableCallSite CS) { static bool areCallingConvEligibleForTCO_64SVR4(CallingConv::ID CallerCC, CallingConv::ID CalleeCC) { - // Tail or Sibling call optimization (TCO/SCO) needs callee and caller to - // have the same calling convention. - if (CallerCC != CalleeCC) + // Tail calls are possible with fastcc and ccc. + auto isTailCallableCC = [] (CallingConv::ID CC){ + return CC == CallingConv::C || CC == CallingConv::Fast; + }; + if (!isTailCallableCC(CallerCC) || !isTailCallableCC(CalleeCC)) return false; - // Tail or Sibling calls can be done with fastcc/ccc. - return (CallerCC == CallingConv::Fast || CallerCC == CallingConv::C); + // We can safely tail call both fastcc and ccc callees from a c calling + // convention caller. If the caller is fastcc, we may have less stack space + // than a non-fastcc caller with the same signature so disable tail-calls in + // that case. + return CallerCC == CallingConv::C || CallerCC == CalleeCC; } bool @@ -4434,10 +4439,28 @@ PPCTargetLowering::IsEligibleForTailCallOptimization_64SVR4( // Callee contains any byval parameter is not supported, too. // Note: This is a quick work around, because in some cases, e.g. // caller's stack size > callee's stack size, we are still able to apply - // sibling call optimization. See: https://reviews.llvm.org/D23441#513574 + // sibling call optimization. For example, gcc is able to do SCO for caller1 + // in the following example, but not for caller2. + // struct test { + // long int a; + // char ary[56]; + // } gTest; + // __attribute__((noinline)) int callee(struct test v, struct test *b) { + // b->a = v.a; + // return 0; + // } + // void caller1(struct test a, struct test c, struct test *b) { + // callee(gTest, b); } + // void caller2(struct test *b) { callee(gTest, b); } if (any_of(Outs, [](const ISD::OutputArg& OA) { return OA.Flags.isByVal(); })) return false; + // If callee and caller use different calling conventions, we cannot pass + // parameters on stack since offsets for the parameter area may be different. + if (Caller.getCallingConv() != CalleeCC && + needStackSlotPassParameters(Subtarget, Outs)) + return false; + // No TCO/SCO on indirect call because Caller have to restore its TOC if (!isFunctionGlobalAddress(Callee) && !isa<ExternalSymbolSDNode>(Callee)) diff --git a/lib/Target/PowerPC/PPCInstrInfo.cpp b/lib/Target/PowerPC/PPCInstrInfo.cpp index ffb5cc8757f25..fb16700a5e177 100644 --- a/lib/Target/PowerPC/PPCInstrInfo.cpp +++ b/lib/Target/PowerPC/PPCInstrInfo.cpp @@ -2433,7 +2433,7 @@ bool PPCInstrInfo::convertToImmediateForm(MachineInstr &MI, int64_t MB = MI.getOperand(3).getImm(); APInt InVal(Opc == PPC::RLDICL ? 64 : 32, SExtImm, true); InVal = InVal.rotl(SH); - uint64_t Mask = (1LU << (63 - MB + 1)) - 1; + uint64_t Mask = (1LLU << (63 - MB + 1)) - 1; InVal &= Mask; // Can't replace negative values with an LI as that will sign-extend // and not clear the left bits. If we're setting the CR bit, we will use @@ -2457,8 +2457,8 @@ bool PPCInstrInfo::convertToImmediateForm(MachineInstr &MI, int64_t ME = MI.getOperand(4).getImm(); APInt InVal(32, SExtImm, true); InVal = InVal.rotl(SH); - // Set the bits ( MB + 32 ) to ( ME + 32 ). - uint64_t Mask = ((1 << (32 - MB)) - 1) & ~((1 << (31 - ME)) - 1); + // Set the bits ( MB + 32 ) to ( ME + 32 ). + uint64_t Mask = ((1LLU << (32 - MB)) - 1) & ~((1LLU << (31 - ME)) - 1); InVal &= Mask; // Can't replace negative values with an LI as that will sign-extend // and not clear the left bits. If we're setting the CR bit, we will use @@ -2527,6 +2527,7 @@ bool PPCInstrInfo::instrHasImmForm(const MachineInstr &MI, III.ConstantOpNo = 2; III.ImmWidth = 16; III.ImmMustBeMultipleOf = 1; + III.TruncateImmTo = 0; switch (Opc) { default: return false; case PPC::ADD4: @@ -2600,10 +2601,6 @@ bool PPCInstrInfo::instrHasImmForm(const MachineInstr &MI, case PPC::RLWNM8: case PPC::RLWNMo: case PPC::RLWNM8o: - case PPC::RLDCL: - case PPC::RLDCLo: - case PPC::RLDCR: - case PPC::RLDCRo: case PPC::SLW: case PPC::SLW8: case PPC::SLWo: @@ -2614,29 +2611,26 @@ bool PPCInstrInfo::instrHasImmForm(const MachineInstr &MI, case PPC::SRW8o: case PPC::SRAW: case PPC::SRAWo: - case PPC::SLD: - case PPC::SLDo: - case PPC::SRD: - case PPC::SRDo: - case PPC::SRAD: - case PPC::SRADo: III.SignedImm = false; III.ZeroIsSpecialOrig = 0; III.ZeroIsSpecialNew = 0; III.IsCommutative = false; // This isn't actually true, but the instructions ignore any of the // upper bits, so any immediate loaded with an LI is acceptable. + // This does not apply to shift right algebraic because a value + // out of range will produce a -1/0. III.ImmWidth = 16; + if (Opc == PPC::RLWNM || Opc == PPC::RLWNM8 || + Opc == PPC::RLWNMo || Opc == PPC::RLWNM8o) + III.TruncateImmTo = 5; + else + III.TruncateImmTo = 6; switch(Opc) { default: llvm_unreachable("Unknown opcode"); case PPC::RLWNM: III.ImmOpcode = PPC::RLWINM; break; case PPC::RLWNM8: III.ImmOpcode = PPC::RLWINM8; break; case PPC::RLWNMo: III.ImmOpcode = PPC::RLWINMo; break; case PPC::RLWNM8o: III.ImmOpcode = PPC::RLWINM8o; break; - case PPC::RLDCL: III.ImmOpcode = PPC::RLDICL; break; - case PPC::RLDCLo: III.ImmOpcode = PPC::RLDICLo; break; - case PPC::RLDCR: III.ImmOpcode = PPC::RLDICR; break; - case PPC::RLDCRo: III.ImmOpcode = PPC::RLDICRo; break; case PPC::SLW: III.ImmOpcode = PPC::RLWINM; break; case PPC::SLW8: III.ImmOpcode = PPC::RLWINM8; break; case PPC::SLWo: III.ImmOpcode = PPC::RLWINMo; break; @@ -2645,14 +2639,62 @@ bool PPCInstrInfo::instrHasImmForm(const MachineInstr &MI, case PPC::SRW8: III.ImmOpcode = PPC::RLWINM8; break; case PPC::SRWo: III.ImmOpcode = PPC::RLWINMo; break; case PPC::SRW8o: III.ImmOpcode = PPC::RLWINM8o; break; - case PPC::SRAW: III.ImmOpcode = PPC::SRAWI; break; - case PPC::SRAWo: III.ImmOpcode = PPC::SRAWIo; break; + case PPC::SRAW: + III.ImmWidth = 5; + III.TruncateImmTo = 0; + III.ImmOpcode = PPC::SRAWI; + break; + case PPC::SRAWo: + III.ImmWidth = 5; + III.TruncateImmTo = 0; + III.ImmOpcode = PPC::SRAWIo; + break; + } + break; + case PPC::RLDCL: + case PPC::RLDCLo: + case PPC::RLDCR: + case PPC::RLDCRo: + case PPC::SLD: + case PPC::SLDo: + case PPC::SRD: + case PPC::SRDo: + case PPC::SRAD: + case PPC::SRADo: + III.SignedImm = false; + III.ZeroIsSpecialOrig = 0; + III.ZeroIsSpecialNew = 0; + III.IsCommutative = false; + // This isn't actually true, but the instructions ignore any of the + // upper bits, so any immediate loaded with an LI is acceptable. + // This does not apply to shift right algebraic because a value + // out of range will produce a -1/0. + III.ImmWidth = 16; + if (Opc == PPC::RLDCL || Opc == PPC::RLDCLo || + Opc == PPC::RLDCR || Opc == PPC::RLDCRo) + III.TruncateImmTo = 6; + else + III.TruncateImmTo = 7; + switch(Opc) { + default: llvm_unreachable("Unknown opcode"); + case PPC::RLDCL: III.ImmOpcode = PPC::RLDICL; break; + case PPC::RLDCLo: III.ImmOpcode = PPC::RLDICLo; break; + case PPC::RLDCR: III.ImmOpcode = PPC::RLDICR; break; + case PPC::RLDCRo: III.ImmOpcode = PPC::RLDICRo; break; case PPC::SLD: III.ImmOpcode = PPC::RLDICR; break; case PPC::SLDo: III.ImmOpcode = PPC::RLDICRo; break; case PPC::SRD: III.ImmOpcode = PPC::RLDICL; break; case PPC::SRDo: III.ImmOpcode = PPC::RLDICLo; break; - case PPC::SRAD: III.ImmOpcode = PPC::SRADI; break; - case PPC::SRADo: III.ImmOpcode = PPC::SRADIo; break; + case PPC::SRAD: + III.ImmWidth = 6; + III.TruncateImmTo = 0; + III.ImmOpcode = PPC::SRADI; + break; + case PPC::SRADo: + III.ImmWidth = 6; + III.TruncateImmTo = 0; + III.ImmOpcode = PPC::SRADIo; + break; } break; // Loads and stores: @@ -2866,6 +2908,8 @@ bool PPCInstrInfo::transformToImmForm(MachineInstr &MI, const ImmInstrInfo &III, return false; if (Imm % III.ImmMustBeMultipleOf) return false; + if (III.TruncateImmTo) + Imm &= ((1 << III.TruncateImmTo) - 1); if (III.SignedImm) { APInt ActualValue(64, Imm, true); if (!ActualValue.isSignedIntN(III.ImmWidth)) diff --git a/lib/Target/PowerPC/PPCInstrInfo.h b/lib/Target/PowerPC/PPCInstrInfo.h index 4271c50127a1d..8bfb8bc880979 100644 --- a/lib/Target/PowerPC/PPCInstrInfo.h +++ b/lib/Target/PowerPC/PPCInstrInfo.h @@ -97,6 +97,8 @@ struct ImmInstrInfo { uint64_t ImmOpcode : 16; // The size of the immediate. uint64_t ImmWidth : 5; + // The immediate should be truncated to N bits. + uint64_t TruncateImmTo : 5; }; // Information required to convert an instruction to just a materialized diff --git a/lib/Target/PowerPC/PPCMIPeephole.cpp b/lib/Target/PowerPC/PPCMIPeephole.cpp index 474661aaaee86..a4c7a030389b1 100644 --- a/lib/Target/PowerPC/PPCMIPeephole.cpp +++ b/lib/Target/PowerPC/PPCMIPeephole.cpp @@ -55,7 +55,7 @@ FixedPointRegToImm("ppc-reg-to-imm-fixed-point", cl::Hidden, cl::init(true), "convert reg-reg instructions to reg-imm")); static cl::opt<bool> -ConvertRegReg("ppc-convert-rr-to-ri", cl::Hidden, cl::init(false), +ConvertRegReg("ppc-convert-rr-to-ri", cl::Hidden, cl::init(true), cl::desc("Convert eligible reg+reg instructions to reg+imm")); static cl::opt<bool> diff --git a/lib/Target/PowerPC/PPCPreEmitPeephole.cpp b/lib/Target/PowerPC/PPCPreEmitPeephole.cpp index 9501f0f89b81b..d524c354ed35e 100644 --- a/lib/Target/PowerPC/PPCPreEmitPeephole.cpp +++ b/lib/Target/PowerPC/PPCPreEmitPeephole.cpp @@ -35,7 +35,7 @@ STATISTIC(NumRemovedInPreEmit, "Number of instructions deleted in pre-emit peephole"); static cl::opt<bool> -RunPreEmitPeephole("ppc-late-peephole", cl::Hidden, cl::init(false), +RunPreEmitPeephole("ppc-late-peephole", cl::Hidden, cl::init(true), cl::desc("Run pre-emit peephole optimizations.")); namespace { |
