diff --git a/lib/Target/Hexagon/HexagonFrameLowering.cpp b/lib/Target/Hexagon/HexagonFrameLowering.cpp index 3c08eaabe18..95b98160194 100644 --- a/lib/Target/Hexagon/HexagonFrameLowering.cpp +++ b/lib/Target/Hexagon/HexagonFrameLowering.cpp @@ -860,16 +860,6 @@ static const char *getSpillFunctionFor(unsigned MaxReg, SpillKind SpillType, return 0; } -/// Adds all callee-saved registers up to MaxReg to the instruction. -static void addCalleeSaveRegistersAsImpOperand(MachineInstr *Inst, - unsigned MaxReg, bool IsDef) { - // Add the callee-saved registers as implicit uses. - for (unsigned R = Hexagon::R16; R <= MaxReg; ++R) { - MachineOperand ImpUse = MachineOperand::CreateReg(R, IsDef, true); - Inst->addOperand(ImpUse); - } -} - int HexagonFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI, unsigned &FrameReg) const { @@ -989,7 +979,7 @@ bool HexagonFrameLowering::insertCSRSpillsInBlock(MachineBasicBlock &MBB, BuildMI(MBB, MI, DL, HII.get(SpillOpc)) .addExternalSymbol(SpillFun); // Add callee-saved registers as use. - addCalleeSaveRegistersAsImpOperand(SaveRegsCall, MaxReg, false); + addCalleeSaveRegistersAsImpOperand(SaveRegsCall, CSI, false, true); // Add live in registers. for (unsigned I = 0; I < CSI.size(); ++I) MBB.addLiveIn(CSI[I].getReg()); @@ -1050,7 +1040,7 @@ bool HexagonFrameLowering::insertCSRRestoresInBlock(MachineBasicBlock &MBB, // Transfer the function live-out registers. DeallocCall->copyImplicitOps(MF, *It); } - addCalleeSaveRegistersAsImpOperand(DeallocCall, MaxR, true); + addCalleeSaveRegistersAsImpOperand(DeallocCall, CSI, true, false); return true; } @@ -1130,10 +1120,12 @@ static bool needToReserveScavengingSpillSlots(MachineFunction &MF, return false; }; - // Check for an unused caller-saved register. + // Check for an unused caller-saved register. Callee-saved registers + // have become pristine by now. for (const MCPhysReg *P = HRI.getCallerSavedRegs(&MF); *P; ++P) if (!IsUsed(*P)) return false; + // All caller-saved registers are used. return true; } @@ -1647,39 +1639,39 @@ bool HexagonFrameLowering::expandSpillMacros(MachineFunction &MF, switch (Opc) { case TargetOpcode::COPY: - Changed = expandCopy(B, I, MRI, HII, NewRegs); + Changed |= expandCopy(B, I, MRI, HII, NewRegs); break; case Hexagon::STriw_pred: case Hexagon::STriw_mod: - Changed = expandStoreInt(B, I, MRI, HII, NewRegs); + Changed |= expandStoreInt(B, I, MRI, HII, NewRegs); break; case Hexagon::LDriw_pred: case Hexagon::LDriw_mod: - Changed = expandLoadInt(B, I, MRI, HII, NewRegs); + Changed |= expandLoadInt(B, I, MRI, HII, NewRegs); break; case Hexagon::STriq_pred_V6: case Hexagon::STriq_pred_V6_128B: - Changed = expandStoreVecPred(B, I, MRI, HII, NewRegs); + Changed |= expandStoreVecPred(B, I, MRI, HII, NewRegs); break; case Hexagon::LDriq_pred_V6: case Hexagon::LDriq_pred_V6_128B: - Changed = expandLoadVecPred(B, I, MRI, HII, NewRegs); + Changed |= expandLoadVecPred(B, I, MRI, HII, NewRegs); break; case Hexagon::LDrivv_pseudo_V6: case Hexagon::LDrivv_pseudo_V6_128B: - Changed = expandLoadVec2(B, I, MRI, HII, NewRegs); + Changed |= expandLoadVec2(B, I, MRI, HII, NewRegs); break; case Hexagon::STrivv_pseudo_V6: case Hexagon::STrivv_pseudo_V6_128B: - Changed = expandStoreVec2(B, I, MRI, HII, NewRegs); + Changed |= expandStoreVec2(B, I, MRI, HII, NewRegs); break; case Hexagon::STriv_pseudo_V6: case Hexagon::STriv_pseudo_V6_128B: - Changed = expandStoreVec(B, I, MRI, HII, NewRegs); + Changed |= expandStoreVec(B, I, MRI, HII, NewRegs); break; case Hexagon::LDriv_pseudo_V6: case Hexagon::LDriv_pseudo_V6_128B: - Changed = expandLoadVec(B, I, MRI, HII, NewRegs); + Changed |= expandLoadVec(B, I, MRI, HII, NewRegs); break; } } @@ -2171,6 +2163,16 @@ const MachineInstr *HexagonFrameLowering::getAlignaInstr( } +/// Adds all callee-saved registers as implicit uses or defs to the +/// instruction. +void HexagonFrameLowering::addCalleeSaveRegistersAsImpOperand(MachineInstr *MI, + const CSIVect &CSI, bool IsDef, bool IsKill) const { + // Add the callee-saved registers as implicit uses. + for (auto &R : CSI) + MI->addOperand(MachineOperand::CreateReg(R.getReg(), IsDef, true, IsKill)); +} + + /// Determine whether the callee-saved register saves and restores should /// be generated via inline code. If this function returns "true", inline /// code will be generated. If this function returns "false", additional diff --git a/lib/Target/Hexagon/HexagonFrameLowering.h b/lib/Target/Hexagon/HexagonFrameLowering.h index 1f578f30c77..3c3f03915d9 100644 --- a/lib/Target/Hexagon/HexagonFrameLowering.h +++ b/lib/Target/Hexagon/HexagonFrameLowering.h @@ -136,6 +136,8 @@ private: void findShrunkPrologEpilog(MachineFunction &MF, MachineBasicBlock *&PrologB, MachineBasicBlock *&EpilogB) const; + void addCalleeSaveRegistersAsImpOperand(MachineInstr *MI, const CSIVect &CSI, + bool IsDef, bool IsKill) const; bool shouldInlineCSR(llvm::MachineFunction &MF, const CSIVect &CSI) const; bool useSpillFunction(MachineFunction &MF, const CSIVect &CSI) const; bool useRestoreFunction(MachineFunction &MF, const CSIVect &CSI) const; diff --git a/lib/Target/Hexagon/HexagonInstrInfoV3.td b/lib/Target/Hexagon/HexagonInstrInfoV3.td index ead3b41c891..9024a43aa7e 100644 --- a/lib/Target/Hexagon/HexagonInstrInfoV3.td +++ b/lib/Target/Hexagon/HexagonInstrInfoV3.td @@ -21,25 +21,26 @@ def callv3nr : SDNode<"HexagonISD::CALLv3nr", SDT_SPCall, // J + //===----------------------------------------------------------------------===// // Call subroutine. -let isCall = 1, hasSideEffects = 1, Defs = VolatileV3.Regs, isPredicable = 1, +let isCall = 1, hasSideEffects = 1, isPredicable = 1, isExtended = 0, isExtendable = 1, opExtendable = 0, isExtentSigned = 1, opExtentBits = 24, opExtentAlign = 2 in -class T_Call +class T_Call : JInst<(outs), (ins calltarget:$dst), "call " # ExtStr # "$dst", [], "", J_tc_2early_SLOT23> { let BaseOpcode = "call"; bits<24> dst; + let Defs = !if (CSR, VolatileV3.Regs, []); let IClass = 0b0101; let Inst{27-25} = 0b101; let Inst{24-16,13-1} = dst{23-2}; let Inst{0} = 0b0; } -let isCall = 1, hasSideEffects = 1, Defs = VolatileV3.Regs, isPredicated = 1, +let isCall = 1, hasSideEffects = 1, isPredicated = 1, isExtended = 0, isExtendable = 1, opExtendable = 1, isExtentSigned = 1, opExtentBits = 17, opExtentAlign = 2 in -class T_CallPred +class T_CallPred : JInst<(outs), (ins PredRegs:$Pu, calltarget:$dst), CondStr<"$Pu", IfTrue, 0>.S # "call " # ExtStr # "$dst", [], "", J_tc_2early_SLOT23> { @@ -48,6 +49,7 @@ class T_CallPred bits<2> Pu; bits<17> dst; + let Defs = !if (CSR, VolatileV3.Regs, []); let IClass = 0b0101; let Inst{27-24} = 0b1101; let Inst{23-22,20-16,13,7-1} = dst{16-2}; @@ -56,19 +58,19 @@ class T_CallPred let Inst{9-8} = Pu; } -multiclass T_Calls { - def NAME : T_Call; - def t : T_CallPred<1, ExtStr>; - def f : T_CallPred<0, ExtStr>; +multiclass T_Calls { + def NAME : T_Call; + def t : T_CallPred; + def f : T_CallPred; } -defm J2_call: T_Calls<"">, PredRel; +defm J2_call: T_Calls<1, "">, PredRel; let isCodeGenOnly = 1, isCall = 1, hasSideEffects = 1, Defs = VolatileV3.Regs in -def CALLv3nr : T_Call<"">, PredRel; +def CALLv3nr : T_Call<1, "">, PredRel; let isCodeGenOnly = 1, isCall = 1, hasSideEffects = 1, Defs = [PC, R31, R6, R7, P0] in -def CALLstk : T_Call<"">, PredRel; +def CALLstk : T_Call<0, "">, PredRel; //===----------------------------------------------------------------------===// // J - diff --git a/lib/Target/Hexagon/HexagonInstrInfoV4.td b/lib/Target/Hexagon/HexagonInstrInfoV4.td index 4dc8b70cb5a..a1895cf76d1 100644 --- a/lib/Target/Hexagon/HexagonInstrInfoV4.td +++ b/lib/Target/Hexagon/HexagonInstrInfoV4.td @@ -3288,43 +3288,43 @@ let isCall = 1, isBarrier = 1, isReturn = 1, isTerminator = 1, // Restore registers and dealloc frame before a tail call. let isCall = 1, Defs = [R29, R30, R31, PC], isAsmParserOnly = 1 in { - def RESTORE_DEALLOC_BEFORE_TAILCALL_V4 : T_Call<"">, PredRel; + def RESTORE_DEALLOC_BEFORE_TAILCALL_V4 : T_Call<0, "">, PredRel; let isExtended = 1, opExtendable = 0 in - def RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT : T_Call<"">, PredRel; + def RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT : T_Call<0, "">, PredRel; let Defs = [R14, R15, R28, R29, R30, R31, PC] in { - def RESTORE_DEALLOC_BEFORE_TAILCALL_V4_PIC : T_Call<"">, PredRel; + def RESTORE_DEALLOC_BEFORE_TAILCALL_V4_PIC : T_Call<0, "">, PredRel; let isExtended = 1, opExtendable = 0 in - def RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT_PIC : T_Call<"">, PredRel; + def RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT_PIC : T_Call<0, "">, PredRel; } } // Save registers function call. let isCall = 1, Uses = [R29, R31], isAsmParserOnly = 1 in { - def SAVE_REGISTERS_CALL_V4 : T_Call<"">, PredRel; + def SAVE_REGISTERS_CALL_V4 : T_Call<0, "">, PredRel; let isExtended = 1, opExtendable = 0 in - def SAVE_REGISTERS_CALL_V4_EXT : T_Call<"">, PredRel; + def SAVE_REGISTERS_CALL_V4_EXT : T_Call<0, "">, PredRel; let Defs = [P0] in - def SAVE_REGISTERS_CALL_V4STK : T_Call<"">, PredRel; + def SAVE_REGISTERS_CALL_V4STK : T_Call<0, "">, PredRel; let Defs = [P0], isExtended = 1, opExtendable = 0 in - def SAVE_REGISTERS_CALL_V4STK_EXT : T_Call<"">, PredRel; + def SAVE_REGISTERS_CALL_V4STK_EXT : T_Call<0, "">, PredRel; let Defs = [R14, R15, R28] in - def SAVE_REGISTERS_CALL_V4_PIC : T_Call<"">, PredRel; + def SAVE_REGISTERS_CALL_V4_PIC : T_Call<0, "">, PredRel; let Defs = [R14, R15, R28], isExtended = 1, opExtendable = 0 in - def SAVE_REGISTERS_CALL_V4_EXT_PIC : T_Call<"">, PredRel; + def SAVE_REGISTERS_CALL_V4_EXT_PIC : T_Call<0, "">, PredRel; let Defs = [R14, R15, R28, P0] in - def SAVE_REGISTERS_CALL_V4STK_PIC : T_Call<"">, PredRel; + def SAVE_REGISTERS_CALL_V4STK_PIC : T_Call<0, "">, PredRel; let Defs = [R14, R15, R28, P0], isExtended = 1, opExtendable = 0 in - def SAVE_REGISTERS_CALL_V4STK_EXT_PIC : T_Call<"">, PredRel; + def SAVE_REGISTERS_CALL_V4STK_EXT_PIC : T_Call<0, "">, PredRel; } //===----------------------------------------------------------------------===// diff --git a/test/CodeGen/Hexagon/csr-func-usedef.ll b/test/CodeGen/Hexagon/csr-func-usedef.ll new file mode 100644 index 00000000000..a9f81b9f521 --- /dev/null +++ b/test/CodeGen/Hexagon/csr-func-usedef.ll @@ -0,0 +1,72 @@ +; RUN: llc -march=hexagon < %s +; REQUIRES: asserts + +target triple = "hexagon" + +declare i8* @llvm.hexagon.circ.ldb(i8*, i8*, i32, i32) #1 +declare i8* @llvm.hexagon.circ.stb(i8*, i32, i32, i32) #1 + +define zeroext i8 @circular_loop_test10(i8* %A, i8* %B, i32 %x, i32 %y, i32 %z, i32 %w) #0 { +entry: + %element_load0 = alloca i8, align 1 + %element_load2 = alloca i8, align 1 + %element_load3 = alloca i8, align 1 + %element_load5 = alloca i8, align 1 + %or = or i32 %x, 100663296 + %or5 = or i32 %z, 100663296 + %or7 = or i32 %w, 100663296 + br label %for.body + +for.body: ; preds = %for.body, %entry + %p0.082 = phi i8* [ %A, %entry ], [ undef, %for.body ] + %element_load.080 = phi i32 [ 0, %entry ], [ %add18, %for.body ] + %p1.079 = phi i8* [ %B, %entry ], [ %1, %for.body ] + %p2.078 = phi i8* [ undef, %entry ], [ %3, %for.body ] + %p3.077 = phi i8* [ undef, %entry ], [ %4, %for.body ] + %0 = call i8* @llvm.hexagon.circ.ldb(i8* %p0.082, i8* nonnull %element_load0, i32 %or, i32 2) + %1 = call i8* @llvm.hexagon.circ.ldb(i8* %p1.079, i8* nonnull null, i32 0, i32 1) + %2 = call i8* @llvm.hexagon.circ.ldb(i8* %p2.078, i8* nonnull %element_load2, i32 %or5, i32 3) + %3 = call i8* @llvm.hexagon.circ.ldb(i8* %2, i8* nonnull %element_load5, i32 %or5, i32 1) + %4 = call i8* @llvm.hexagon.circ.ldb(i8* %p3.077, i8* nonnull %element_load3, i32 %or7, i32 1) + %5 = load i8, i8* null, align 1 + %conv = zext i8 %5 to i32 + %6 = load i8, i8* %element_load2, align 1 + %conv8 = zext i8 %6 to i32 + %7 = load i8, i8* %element_load3, align 1 + %conv9 = zext i8 %7 to i32 + %8 = load i8, i8* undef, align 1 + %conv11 = zext i8 %8 to i32 + %9 = load i8, i8* %element_load5, align 1 + %conv13 = zext i8 %9 to i32 + %10 = load i8, i8* %element_load0, align 1 + %conv15 = zext i8 %10 to i32 + %conv17 = and i32 %element_load.080, 255 + %add = add nuw nsw i32 %conv, %conv17 + %add10 = add nuw nsw i32 %add, %conv8 + %add12 = add nuw nsw i32 %add10, %conv9 + %add14 = add nuw nsw i32 %add12, %conv11 + %add16 = add nuw nsw i32 %add14, %conv13 + %add18 = add nuw nsw i32 %add16, %conv15 + %exitcond84 = icmp eq i32 undef, 200 + br i1 %exitcond84, label %for.body23, label %for.body + +for.body23: ; preds = %for.body23, %for.body + %11 = call i8* @llvm.hexagon.circ.stb(i8* undef, i32 undef, i32 %or, i32 3) + br i1 undef, label %for.body34, label %for.body23 + +for.body34: ; preds = %for.body34, %for.body23 + %element_load.173 = phi i32 [ %add38, %for.body34 ], [ %add18, %for.body23 ] + %arrayidx35 = getelementptr inbounds i8, i8* %B, i32 0 + %12 = load i8, i8* %arrayidx35, align 1 + %conv36 = zext i8 %12 to i32 + %conv37 = and i32 %element_load.173, 255 + %add38 = add nuw nsw i32 %conv36, %conv37 + br i1 undef, label %for.end42, label %for.body34 + +for.end42: ; preds = %for.body34 + %conv39 = trunc i32 %add38 to i8 + ret i8 %conv39 +} + +attributes #0 = { nounwind optsize } +attributes #1 = { argmemonly nounwind }