diff --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp --- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -253,6 +253,14 @@ None) == PPC::AM_DForm; } + /// SelectPCRelForm - Returns true if address N can be represented by + /// PC-Relative addressing mode. + bool SelectPCRelForm(SDNode *Parent, SDValue N, SDValue &Disp, + SDValue &Base) { + return PPCLowering->SelectOptimalAddrMode(Parent, N, Disp, Base, *CurDAG, + None) == PPC::AM_PCRel; + } + /// SelectXForm - Returns true if address N can be represented by the /// addressing mode of XForm instructions (an indexed [r+r] operation). bool SelectXForm(SDNode *Parent, SDValue N, SDValue &Disp, SDValue &Base) { diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.h b/llvm/lib/Target/PowerPC/PPCISelLowering.h --- a/llvm/lib/Target/PowerPC/PPCISelLowering.h +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.h @@ -704,6 +704,7 @@ AM_DSForm, AM_DQForm, AM_XForm, + AM_PCRel }; } // end namespace PPC diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -1458,6 +1458,7 @@ PPC::MOF_AddrIsSImm32 | PPC::MOF_Vector | PPC::MOF_SubtargetP9, PPC::MOF_AddrIsSImm32 | PPC::MOF_Vector256 | PPC::MOF_SubtargetP10, }; + AddrModesMap[PPC::AM_PCRel] = {PPC::MOF_PCRel | PPC::MOF_SubtargetP10}; } /// getMaxByValAlign - Helper for getByValTypeAlignment to determine @@ -16491,6 +16492,9 @@ for (auto FlagSet : AddrModesMap.at(PPC::AM_DQForm)) if ((Flags & FlagSet) == FlagSet) return PPC::AM_DQForm; + for (auto FlagSet : AddrModesMap.at(PPC::AM_PCRel)) + if ((Flags & FlagSet) == FlagSet) + return PPC::AM_PCRel; // If no other forms are selected, return an X-Form instructions can // always be matched. return PPC::AM_XForm; @@ -16584,6 +16588,19 @@ FlagSet |= PPC::MOF_NotAddNorCst; }; + // Check for Power10 specific flags + if (FlagSet & PPC::MOF_SubtargetP10) { + // Check if we have a PCRel node. If so, add the PCRel flag, return early. + if (N.getOpcode() == PPCISD::MAT_PCREL_ADDR || + isValidPCRelNode(N) || + isValidPCRelNode(N) || + isValidPCRelNode(N) || + isValidPCRelNode(N)) { + FlagSet |= PPC::MOF_PCRel; + return FlagSet; + } + } + // Mark this as something we don't want to handle here if it is atomic // or pre-increment instruction. if (const LSBaseSDNode *LSB = dyn_cast(Parent)) @@ -16786,6 +16803,10 @@ Base = N; break; } + case PPC::AM_PCRel: { + Disp = N; + break; + } case PPC::AM_None: break; default: { // By default, X-Form is always available to be selected. diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td @@ -1109,6 +1109,7 @@ def DQForm : ComplexPattern; def XForm : ComplexPattern; def ForceXForm : ComplexPattern; +def PCRelForm : ComplexPattern; //===----------------------------------------------------------------------===// // PowerPC Instruction Predicate Definitions. diff --git a/llvm/lib/Target/PowerPC/PPCInstrPrefix.td b/llvm/lib/Target/PowerPC/PPCInstrPrefix.td --- a/llvm/lib/Target/PowerPC/PPCInstrPrefix.td +++ b/llvm/lib/Target/PowerPC/PPCInstrPrefix.td @@ -1675,170 +1675,160 @@ } } -// TODO: We have an added complexity of 500 here. This is only a temporary -// solution to have tablegen consider these patterns first. The way we do -// addressing for PowerPC is complex depending on available D form, X form, or -// aligned D form loads/stores like DS and DQ forms. The prefixed -// instructions in this file also add additional PC Relative loads/stores -// and D form loads/stores with 34 bit immediates. It is very difficult to force -// instruction selection to consistently pick these first without the current -// added complexity. Once pc-relative implementation is complete, a set of -// follow-up patches will address this refactoring and the AddedComplexity will -// be removed. -let Predicates = [PCRelativeMemops], AddedComplexity = 500 in { +let Predicates = [PCRelativeMemops] in { // Load i32 - def : Pat<(i32 (zextloadi8 (PPCmatpcreladdr pcreladdr:$ga))), + def : Pat<(i32 (zextloadi8 (PPCmatpcreladdr PCRelForm:$ga))), (PLBZpc $ga, 0)>; - def : Pat<(i32 (extloadi8 (PPCmatpcreladdr pcreladdr:$ga))), + def : Pat<(i32 (extloadi8 (PPCmatpcreladdr PCRelForm:$ga))), (PLBZpc $ga, 0)>; - def : Pat<(i32 (sextloadi16 (PPCmatpcreladdr pcreladdr:$ga))), + def : Pat<(i32 (sextloadi16 (PPCmatpcreladdr PCRelForm:$ga))), (PLHApc $ga, 0)>; - def : Pat<(i32 (zextloadi16 (PPCmatpcreladdr pcreladdr:$ga))), + def : Pat<(i32 (zextloadi16 (PPCmatpcreladdr PCRelForm:$ga))), (PLHZpc $ga, 0)>; - def : Pat<(i32 (extloadi16 (PPCmatpcreladdr pcreladdr:$ga))), + def : Pat<(i32 (extloadi16 (PPCmatpcreladdr PCRelForm:$ga))), (PLHZpc $ga, 0)>; - def : Pat<(i32 (load (PPCmatpcreladdr pcreladdr:$ga))), (PLWZpc $ga, 0)>; + def : Pat<(i32 (load (PPCmatpcreladdr PCRelForm:$ga))), (PLWZpc $ga, 0)>; // Store i32 - def : Pat<(truncstorei8 i32:$RS, (PPCmatpcreladdr pcreladdr:$ga)), + def : Pat<(truncstorei8 i32:$RS, (PPCmatpcreladdr PCRelForm:$ga)), (PSTBpc $RS, $ga, 0)>; - def : Pat<(truncstorei16 i32:$RS, (PPCmatpcreladdr pcreladdr:$ga)), + def : Pat<(truncstorei16 i32:$RS, (PPCmatpcreladdr PCRelForm:$ga)), (PSTHpc $RS, $ga, 0)>; - def : Pat<(store i32:$RS, (PPCmatpcreladdr pcreladdr:$ga)), + def : Pat<(store i32:$RS, (PPCmatpcreladdr PCRelForm:$ga)), (PSTWpc $RS, $ga, 0)>; // Load i64 - def : Pat<(i64 (zextloadi8 (PPCmatpcreladdr pcreladdr:$ga))), + def : Pat<(i64 (zextloadi8 (PPCmatpcreladdr PCRelForm:$ga))), (PLBZ8pc $ga, 0)>; - def : Pat<(i64 (extloadi8 (PPCmatpcreladdr pcreladdr:$ga))), + def : Pat<(i64 (extloadi8 (PPCmatpcreladdr PCRelForm:$ga))), (PLBZ8pc $ga, 0)>; - def : Pat<(i64 (sextloadi16 (PPCmatpcreladdr pcreladdr:$ga))), + def : Pat<(i64 (sextloadi16 (PPCmatpcreladdr PCRelForm:$ga))), (PLHA8pc $ga, 0)>; - def : Pat<(i64 (zextloadi16 (PPCmatpcreladdr pcreladdr:$ga))), + def : Pat<(i64 (zextloadi16 (PPCmatpcreladdr PCRelForm:$ga))), (PLHZ8pc $ga, 0)>; - def : Pat<(i64 (extloadi16 (PPCmatpcreladdr pcreladdr:$ga))), + def : Pat<(i64 (extloadi16 (PPCmatpcreladdr PCRelForm:$ga))), (PLHZ8pc $ga, 0)>; - def : Pat<(i64 (zextloadi32 (PPCmatpcreladdr pcreladdr:$ga))), + def : Pat<(i64 (zextloadi32 (PPCmatpcreladdr PCRelForm:$ga))), (PLWZ8pc $ga, 0)>; - def : Pat<(i64 (sextloadi32 (PPCmatpcreladdr pcreladdr:$ga))), + def : Pat<(i64 (sextloadi32 (PPCmatpcreladdr PCRelForm:$ga))), (PLWA8pc $ga, 0)>; - def : Pat<(i64 (extloadi32 (PPCmatpcreladdr pcreladdr:$ga))), + def : Pat<(i64 (extloadi32 (PPCmatpcreladdr PCRelForm:$ga))), (PLWZ8pc $ga, 0)>; - def : Pat<(i64 (load (PPCmatpcreladdr pcreladdr:$ga))), (PLDpc $ga, 0)>; + def : Pat<(i64 (load (PPCmatpcreladdr PCRelForm:$ga))), (PLDpc $ga, 0)>; // Store i64 - def : Pat<(truncstorei8 i64:$RS, (PPCmatpcreladdr pcreladdr:$ga)), + def : Pat<(truncstorei8 i64:$RS, (PPCmatpcreladdr PCRelForm:$ga)), (PSTB8pc $RS, $ga, 0)>; - def : Pat<(truncstorei16 i64:$RS, (PPCmatpcreladdr pcreladdr:$ga)), + def : Pat<(truncstorei16 i64:$RS, (PPCmatpcreladdr PCRelForm:$ga)), (PSTH8pc $RS, $ga, 0)>; - def : Pat<(truncstorei32 i64:$RS, (PPCmatpcreladdr pcreladdr:$ga)), + def : Pat<(truncstorei32 i64:$RS, (PPCmatpcreladdr PCRelForm:$ga)), (PSTW8pc $RS, $ga, 0)>; - def : Pat<(store i64:$RS, (PPCmatpcreladdr pcreladdr:$ga)), + def : Pat<(store i64:$RS, (PPCmatpcreladdr PCRelForm:$ga)), (PSTDpc $RS, $ga, 0)>; // Load f32 - def : Pat<(f32 (load (PPCmatpcreladdr pcreladdr:$addr))), (PLFSpc $addr, 0)>; + def : Pat<(f32 (load (PPCmatpcreladdr PCRelForm:$addr))), (PLFSpc $addr, 0)>; // Store f32 - def : Pat<(store f32:$FRS, (PPCmatpcreladdr pcreladdr:$ga)), + def : Pat<(store f32:$FRS, (PPCmatpcreladdr PCRelForm:$ga)), (PSTFSpc $FRS, $ga, 0)>; // Load f64 - def : Pat<(f64 (extloadf32 (PPCmatpcreladdr pcreladdr:$addr))), + def : Pat<(f64 (extloadf32 (PPCmatpcreladdr PCRelForm:$addr))), (COPY_TO_REGCLASS (PLFSpc $addr, 0), VSFRC)>; - def : Pat<(f64 (load (PPCmatpcreladdr pcreladdr:$addr))), (PLFDpc $addr, 0)>; + def : Pat<(f64 (load (PPCmatpcreladdr PCRelForm:$addr))), (PLFDpc $addr, 0)>; // Store f64 - def : Pat<(store f64:$FRS, (PPCmatpcreladdr pcreladdr:$ga)), + def : Pat<(store f64:$FRS, (PPCmatpcreladdr PCRelForm:$ga)), (PSTFDpc $FRS, $ga, 0)>; // Load f128 - def : Pat<(f128 (load (PPCmatpcreladdr pcreladdr:$addr))), + def : Pat<(f128 (load (PPCmatpcreladdr PCRelForm:$addr))), (COPY_TO_REGCLASS (PLXVpc $addr, 0), VRRC)>; // Store f128 - def : Pat<(store f128:$XS, (PPCmatpcreladdr pcreladdr:$ga)), + def : Pat<(store f128:$XS, (PPCmatpcreladdr PCRelForm:$ga)), (PSTXVpc (COPY_TO_REGCLASS $XS, VSRC), $ga, 0)>; // Load v4i32 - def : Pat<(v4i32 (load (PPCmatpcreladdr pcreladdr:$addr))), (PLXVpc $addr, 0)>; + def : Pat<(v4i32 (load (PPCmatpcreladdr PCRelForm:$addr))), (PLXVpc $addr, 0)>; // Store v4i32 - def : Pat<(store v4i32:$XS, (PPCmatpcreladdr pcreladdr:$ga)), + def : Pat<(store v4i32:$XS, (PPCmatpcreladdr PCRelForm:$ga)), (PSTXVpc $XS, $ga, 0)>; // Load v2i64 - def : Pat<(v2i64 (load (PPCmatpcreladdr pcreladdr:$addr))), (PLXVpc $addr, 0)>; + def : Pat<(v2i64 (load (PPCmatpcreladdr PCRelForm:$addr))), (PLXVpc $addr, 0)>; // Store v2i64 - def : Pat<(store v2i64:$XS, (PPCmatpcreladdr pcreladdr:$ga)), + def : Pat<(store v2i64:$XS, (PPCmatpcreladdr PCRelForm:$ga)), (PSTXVpc $XS, $ga, 0)>; // Load v4f32 - def : Pat<(v4f32 (load (PPCmatpcreladdr pcreladdr:$addr))), (PLXVpc $addr, 0)>; + def : Pat<(v4f32 (load (PPCmatpcreladdr PCRelForm:$addr))), (PLXVpc $addr, 0)>; // Store v4f32 - def : Pat<(store v4f32:$XS, (PPCmatpcreladdr pcreladdr:$ga)), + def : Pat<(store v4f32:$XS, (PPCmatpcreladdr PCRelForm:$ga)), (PSTXVpc $XS, $ga, 0)>; // Load v2f64 - def : Pat<(v2f64 (load (PPCmatpcreladdr pcreladdr:$addr))), (PLXVpc $addr, 0)>; + def : Pat<(v2f64 (load (PPCmatpcreladdr PCRelForm:$addr))), (PLXVpc $addr, 0)>; // Store v2f64 - def : Pat<(store v2f64:$XS, (PPCmatpcreladdr pcreladdr:$ga)), + def : Pat<(store v2f64:$XS, (PPCmatpcreladdr PCRelForm:$ga)), (PSTXVpc $XS, $ga, 0)>; // Atomic Load - def : Pat<(atomic_load_8 (PPCmatpcreladdr pcreladdr:$ga)), + def : Pat<(atomic_load_8 (PPCmatpcreladdr PCRelForm:$ga)), (PLBZpc $ga, 0)>; - def : Pat<(atomic_load_16 (PPCmatpcreladdr pcreladdr:$ga)), + def : Pat<(atomic_load_16 (PPCmatpcreladdr PCRelForm:$ga)), (PLHZpc $ga, 0)>; - def : Pat<(atomic_load_32 (PPCmatpcreladdr pcreladdr:$ga)), + def : Pat<(atomic_load_32 (PPCmatpcreladdr PCRelForm:$ga)), (PLWZpc $ga, 0)>; - def : Pat<(atomic_load_64 (PPCmatpcreladdr pcreladdr:$ga)), + def : Pat<(atomic_load_64 (PPCmatpcreladdr PCRelForm:$ga)), (PLDpc $ga, 0)>; // Atomic Store - def : Pat<(atomic_store_8 (PPCmatpcreladdr pcreladdr:$ga), i32:$RS), + def : Pat<(atomic_store_8 (PPCmatpcreladdr PCRelForm:$ga), i32:$RS), (PSTBpc $RS, $ga, 0)>; - def : Pat<(atomic_store_16 (PPCmatpcreladdr pcreladdr:$ga), i32:$RS), + def : Pat<(atomic_store_16 (PPCmatpcreladdr PCRelForm:$ga), i32:$RS), (PSTHpc $RS, $ga, 0)>; - def : Pat<(atomic_store_32 (PPCmatpcreladdr pcreladdr:$ga), i32:$RS), + def : Pat<(atomic_store_32 (PPCmatpcreladdr PCRelForm:$ga), i32:$RS), (PSTWpc $RS, $ga, 0)>; - def : Pat<(atomic_store_8 (PPCmatpcreladdr pcreladdr:$ga), i64:$RS), + def : Pat<(atomic_store_8 (PPCmatpcreladdr PCRelForm:$ga), i64:$RS), (PSTB8pc $RS, $ga, 0)>; - def : Pat<(atomic_store_16 (PPCmatpcreladdr pcreladdr:$ga), i64:$RS), + def : Pat<(atomic_store_16 (PPCmatpcreladdr PCRelForm:$ga), i64:$RS), (PSTH8pc $RS, $ga, 0)>; - def : Pat<(atomic_store_32 (PPCmatpcreladdr pcreladdr:$ga), i64:$RS), + def : Pat<(atomic_store_32 (PPCmatpcreladdr PCRelForm:$ga), i64:$RS), (PSTW8pc $RS, $ga, 0)>; - def : Pat<(atomic_store_64 (PPCmatpcreladdr pcreladdr:$ga), i64:$RS), + def : Pat<(atomic_store_64 (PPCmatpcreladdr PCRelForm:$ga), i64:$RS), (PSTDpc $RS, $ga, 0)>; // Special Cases For PPCstore_scal_int_from_vsr def : Pat<(PPCstore_scal_int_from_vsr (f64 (PPCcv_fp_to_sint_in_vsr f64:$src)), - (PPCmatpcreladdr pcreladdr:$dst), 8), + (PPCmatpcreladdr PCRelForm:$dst), 8), (PSTXSDpc (XSCVDPSXDS f64:$src), $dst, 0)>; def : Pat<(PPCstore_scal_int_from_vsr (f64 (PPCcv_fp_to_sint_in_vsr f128:$src)), - (PPCmatpcreladdr pcreladdr:$dst), 8), + (PPCmatpcreladdr PCRelForm:$dst), 8), (PSTXSDpc (COPY_TO_REGCLASS (XSCVQPSDZ f128:$src), VFRC), $dst, 0)>; def : Pat<(PPCstore_scal_int_from_vsr (f64 (PPCcv_fp_to_uint_in_vsr f64:$src)), - (PPCmatpcreladdr pcreladdr:$dst), 8), + (PPCmatpcreladdr PCRelForm:$dst), 8), (PSTXSDpc (XSCVDPUXDS f64:$src), $dst, 0)>; def : Pat<(PPCstore_scal_int_from_vsr (f64 (PPCcv_fp_to_uint_in_vsr f128:$src)), - (PPCmatpcreladdr pcreladdr:$dst), 8), + (PPCmatpcreladdr PCRelForm:$dst), 8), (PSTXSDpc (COPY_TO_REGCLASS (XSCVQPUDZ f128:$src), VFRC), $dst, 0)>; // If the PPCmatpcreladdr node is not caught by any other pattern it should be // caught here and turned into a paddi instruction to materialize the address. - def : Pat<(PPCmatpcreladdr pcreladdr:$addr), (PADDI8pc 0, $addr)>; + def : Pat<(PPCmatpcreladdr PCRelForm:$addr), (PADDI8pc 0, $addr)>; // PPCtlsdynamatpcreladdr node is used for TLS dynamic models to materialize // tls global address with paddi instruction. - def : Pat<(PPCtlsdynamatpcreladdr pcreladdr:$addr), (PADDI8pc 0, $addr)>; + def : Pat<(PPCtlsdynamatpcreladdr PCRelForm:$addr), (PADDI8pc 0, $addr)>; // PPCtlslocalexecmataddr node is used for TLS local exec models to // materialize tls global address with paddi instruction. def : Pat<(PPCaddTls i64:$in, (PPCtlslocalexecmataddr tglobaltlsaddr:$addr)),