@@ -1854,32 +1854,133 @@ bool Z80InstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
18541854 // Expand 8-bit ALU Pseudos into physical accumulator sequence:
18551855 // COPY src1 → A, ALU op, COPY A → dst
18561856 case Z80::ADD8_gisel:
1857+ case Z80::ADD8_gisel_p:
1858+ case Z80::ADD8_gisel_o:
18571859 case Z80::SUB8_gisel:
1860+ case Z80::SUB8_gisel_p:
1861+ case Z80::SUB8_gisel_o:
18581862 case Z80::AND8_gisel:
1863+ case Z80::AND8_gisel_p:
1864+ case Z80::AND8_gisel_o:
18591865 case Z80::OR8_gisel:
1860- case Z80::XOR8_gisel: {
1866+ case Z80::OR8_gisel_p:
1867+ case Z80::OR8_gisel_o:
1868+ case Z80::XOR8_gisel:
1869+ case Z80::XOR8_gisel_p:
1870+ case Z80::XOR8_gisel_o: {
18611871 unsigned RealOpc;
18621872 switch (Opc) {
18631873 default : llvm_unreachable (" Unknown gisel opcode" );
1864- case Z80::ADD8_gisel: RealOpc = Z80::ADD8ar; break ;
1865- case Z80::SUB8_gisel: RealOpc = Z80::SUB8ar; break ;
1866- case Z80::AND8_gisel: RealOpc = Z80::AND8ar; break ;
1867- case Z80::OR8_gisel: RealOpc = Z80::OR8ar; break ;
1868- case Z80::XOR8_gisel: RealOpc = Z80::XOR8ar; break ;
1874+ case Z80::ADD8_gisel: RealOpc = Z80::ADD8ar; break ;
1875+ case Z80::ADD8_gisel_p: RealOpc = Z80::ADD8ap; break ;
1876+ case Z80::ADD8_gisel_o: RealOpc = Z80::ADD8ao; break ;
1877+ case Z80::SUB8_gisel: RealOpc = Z80::SUB8ar; break ;
1878+ case Z80::SUB8_gisel_p: RealOpc = Z80::SUB8ap; break ;
1879+ case Z80::SUB8_gisel_o: RealOpc = Z80::SUB8ao; break ;
1880+ case Z80::AND8_gisel: RealOpc = Z80::AND8ar; break ;
1881+ case Z80::AND8_gisel_p: RealOpc = Z80::AND8ap; break ;
1882+ case Z80::AND8_gisel_o: RealOpc = Z80::AND8ao; break ;
1883+ case Z80::OR8_gisel: RealOpc = Z80::OR8ar; break ;
1884+ case Z80::OR8_gisel_p: RealOpc = Z80::OR8ap; break ;
1885+ case Z80::OR8_gisel_o: RealOpc = Z80::OR8ao; break ;
1886+ case Z80::XOR8_gisel: RealOpc = Z80::XOR8ar; break ;
1887+ case Z80::XOR8_gisel_p: RealOpc = Z80::XOR8ap; break ;
1888+ case Z80::XOR8_gisel_o: RealOpc = Z80::XOR8ao; break ;
18691889 }
18701890 Register DstReg = MI.getOperand (0 ).getReg ();
18711891 Register Src1 = MI.getOperand (1 ).getReg ();
1872- Register Src2 = MI.getOperand (2 ).getReg ();
1892+
1893+ auto hasOtherUseOfReg = [&](MachineInstr &UseMI, Register Reg,
1894+ unsigned OperandNo) {
1895+ for (unsigned I = 0 , E = UseMI.getNumOperands (); I != E; ++I) {
1896+ if (I == OperandNo)
1897+ continue ;
1898+ MachineOperand &MO = UseMI.getOperand (I);
1899+ if (MO.isReg () && MO.isUse () && MO.getReg () &&
1900+ TRI.regsOverlap (MO.getReg (), Reg))
1901+ return true ;
1902+ }
1903+ return false ;
1904+ };
1905+
1906+ if (Src1 != Z80::A && MI.getOperand (1 ).isKill () &&
1907+ !hasOtherUseOfReg (MI, Src1, 1 ) &&
1908+ MachineBasicBlock::iterator (MI) != MBB.begin ()) {
1909+ auto PrevMI = prev_nodbg (MachineBasicBlock::iterator (MI), MBB.begin ());
1910+ if (!PrevMI->isDebugInstr () &&
1911+ (PrevMI->getOpcode () == Z80::LD8gp ||
1912+ PrevMI->getOpcode () == Z80::LD8go) &&
1913+ PrevMI->getOperand (0 ).getReg () == Src1) {
1914+ PrevMI->getOperand (0 ).setReg (Z80::A);
1915+ MI.getOperand (1 ).setReg (Z80::A);
1916+ Src1 = Z80::A;
1917+ }
1918+ }
18731919
18741920 // 1. Copy Src1 to Accumulator (if not already there)
18751921 if (Src1 != Z80::A)
18761922 copyPhysReg (MBB, MI, DL, Z80::A, Src1, true );
18771923
18781924 // 2. Execute ALU Instruction (implicitly uses A, defines A and F)
1879- BuildMI (MBB, MI, DL, get (RealOpc)).addReg (Src2);
1925+ MachineInstrBuilder Alu = BuildMI (MBB, MI, DL, get (RealOpc));
1926+ switch (Opc) {
1927+ default :
1928+ Alu.add (MI.getOperand (2 ));
1929+ break ;
1930+ case Z80::ADD8_gisel_o:
1931+ case Z80::SUB8_gisel_o:
1932+ case Z80::AND8_gisel_o:
1933+ case Z80::OR8_gisel_o:
1934+ case Z80::XOR8_gisel_o:
1935+ Alu.add (MI.getOperand (2 )).add (MI.getOperand (3 ));
1936+ break ;
1937+ }
1938+ Alu.cloneMemRefs (MI);
18801939
18811940 // 3. Copy Accumulator to Dst (if Dst is not A)
1882- if (DstReg != Z80::A)
1941+ auto forwardAResultToOperand = [&](MachineInstr &UseMI, unsigned OperandNo) {
1942+ MachineOperand &UseMO = UseMI.getOperand (OperandNo);
1943+ if (UseMO.getReg () != DstReg || !UseMO.isKill () ||
1944+ hasOtherUseOfReg (UseMI, DstReg, OperandNo))
1945+ return false ;
1946+ UseMO.setReg (Z80::A);
1947+ return true ;
1948+ };
1949+
1950+ auto canForwardAResult = [&]() {
1951+ if (MI.getOperand (0 ).isDead ())
1952+ return true ;
1953+
1954+ auto NextMI = skipDebugInstructionsForward (Next, MBB.end ());
1955+ if (NextMI == MBB.end ())
1956+ return false ;
1957+
1958+ switch (NextMI->getOpcode ()) {
1959+ default :
1960+ return false ;
1961+ case Z80::ADD8_gisel:
1962+ case Z80::ADD8_gisel_p:
1963+ case Z80::ADD8_gisel_o:
1964+ case Z80::SUB8_gisel:
1965+ case Z80::SUB8_gisel_p:
1966+ case Z80::SUB8_gisel_o:
1967+ case Z80::AND8_gisel:
1968+ case Z80::AND8_gisel_p:
1969+ case Z80::AND8_gisel_o:
1970+ case Z80::OR8_gisel:
1971+ case Z80::OR8_gisel_p:
1972+ case Z80::OR8_gisel_o:
1973+ case Z80::XOR8_gisel:
1974+ case Z80::XOR8_gisel_p:
1975+ case Z80::XOR8_gisel_o:
1976+ case Z80::LD8pg:
1977+ return forwardAResultToOperand (*NextMI, 1 );
1978+ case Z80::LD8og:
1979+ return forwardAResultToOperand (*NextMI, 2 );
1980+ }
1981+ };
1982+
1983+ if (DstReg != Z80::A && !canForwardAResult ())
18831984 copyPhysReg (MBB, MI, DL, DstReg, Z80::A, true );
18841985
18851986 MI.eraseFromParent ();
@@ -2657,6 +2758,42 @@ MachineInstr *Z80InstrInfo::foldMemoryOperandImpl(
26572758
26582759 unsigned Opc;
26592760 unsigned OpSize = 1 ;
2761+ if (OpNum == 1 ) {
2762+ unsigned CommuteOpc = 0 ;
2763+ switch (MI.getOpcode ()) {
2764+ default :
2765+ break ;
2766+ case Z80::ADD8_gisel:
2767+ CommuteOpc = IsOff ? Z80::ADD8_gisel_o : Z80::ADD8_gisel_p;
2768+ break ;
2769+ case Z80::AND8_gisel:
2770+ CommuteOpc = IsOff ? Z80::AND8_gisel_o : Z80::AND8_gisel_p;
2771+ break ;
2772+ case Z80::XOR8_gisel:
2773+ CommuteOpc = IsOff ? Z80::XOR8_gisel_o : Z80::XOR8_gisel_p;
2774+ break ;
2775+ case Z80::OR8_gisel:
2776+ CommuteOpc = IsOff ? Z80::OR8_gisel_o : Z80::OR8_gisel_p;
2777+ break ;
2778+ }
2779+
2780+ if (CommuteOpc) {
2781+ if (Size && Size != OpSize)
2782+ return nullptr ;
2783+
2784+ MachineInstrBuilder MIB (
2785+ MF, MF.CreateMachineInstr (get (CommuteOpc), MI.getDebugLoc (), true ));
2786+ MIB.add (MI.getOperand (0 )).add (MI.getOperand (2 ));
2787+ for (auto &AddrMO : MOs)
2788+ MIB.add (AddrMO);
2789+ for (auto &MO : MI.implicit_operands ())
2790+ MIB.add (MO);
2791+ updateOperandRegConstraints (MF, *MIB);
2792+ InsertPt->getParent ()->insert (InsertPt, MIB);
2793+ return MIB;
2794+ }
2795+ }
2796+
26602797 switch (OpNum) {
26612798 default : return nullptr ;
26622799 case 0 :
@@ -2692,6 +2829,16 @@ MachineInstr *Z80InstrInfo::foldMemoryOperandImpl(
26922829 break ;
26932830 }
26942831 break ;
2832+ case 2 :
2833+ switch (MI.getOpcode ()) {
2834+ default : return nullptr ;
2835+ case Z80::ADD8_gisel: Opc = IsOff ? Z80::ADD8_gisel_o : Z80::ADD8_gisel_p; break ;
2836+ case Z80::SUB8_gisel: Opc = IsOff ? Z80::SUB8_gisel_o : Z80::SUB8_gisel_p; break ;
2837+ case Z80::AND8_gisel: Opc = IsOff ? Z80::AND8_gisel_o : Z80::AND8_gisel_p; break ;
2838+ case Z80::XOR8_gisel: Opc = IsOff ? Z80::XOR8_gisel_o : Z80::XOR8_gisel_p; break ;
2839+ case Z80::OR8_gisel: Opc = IsOff ? Z80::OR8_gisel_o : Z80::OR8_gisel_p; break ;
2840+ }
2841+ break ;
26952842 }
26962843
26972844 if (Size && Size != OpSize)
0 commit comments