diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp b/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp index 4019fc45158d..4c65899024e4 100644 --- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp +++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp @@ -131,7 +131,8 @@ void SystemZInstrInfo::expandRIEPseudo(MachineInstr &MI, unsigned LowOpcode, MI.setDesc(get(LowOpcodeK)); else { emitGRX32Move(*MI.getParent(), MI, MI.getDebugLoc(), DestReg, SrcReg, - SystemZ::LR, 32, MI.getOperand(1).isKill()); + SystemZ::LR, 32, MI.getOperand(1).isKill(), + MI.getOperand(1).isUndef()); MI.setDesc(get(DestIsHigh ? HighOpcode : LowOpcode)); MI.getOperand(1).setReg(DestReg); MI.tieOperands(0, 1); @@ -187,7 +188,7 @@ void SystemZInstrInfo::expandZExtPseudo(MachineInstr &MI, unsigned LowOpcode, unsigned Size) const { emitGRX32Move(*MI.getParent(), MI, MI.getDebugLoc(), MI.getOperand(0).getReg(), MI.getOperand(1).getReg(), LowOpcode, - Size, MI.getOperand(1).isKill()); + Size, MI.getOperand(1).isKill(), MI.getOperand(1).isUndef()); MI.eraseFromParent(); } @@ -231,7 +232,8 @@ void SystemZInstrInfo::emitGRX32Move(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, unsigned LowLowOpcode, - unsigned Size, bool KillSrc) const { + unsigned Size, bool KillSrc, + bool UndefSrc) const { unsigned Opcode; bool DestIsHigh = isHighReg(DestReg); bool SrcIsHigh = isHighReg(SrcReg); @@ -243,13 +245,13 @@ void SystemZInstrInfo::emitGRX32Move(MachineBasicBlock &MBB, Opcode = SystemZ::RISBLH; else { BuildMI(MBB, MBBI, DL, get(LowLowOpcode), DestReg) - .addReg(SrcReg, getKillRegState(KillSrc)); + .addReg(SrcReg, getKillRegState(KillSrc) | getUndefRegState(UndefSrc)); return; } unsigned Rotate = (DestIsHigh != SrcIsHigh ? 32 : 0); BuildMI(MBB, MBBI, DL, get(Opcode), DestReg) .addReg(DestReg, RegState::Undef) - .addReg(SrcReg, getKillRegState(KillSrc)) + .addReg(SrcReg, getKillRegState(KillSrc) | getUndefRegState(UndefSrc)) .addImm(32 - Size).addImm(128 + 31).addImm(Rotate); } @@ -814,7 +816,8 @@ void SystemZInstrInfo::copyPhysReg(MachineBasicBlock &MBB, } if (SystemZ::GRX32BitRegClass.contains(DestReg, SrcReg)) { - emitGRX32Move(MBB, MBBI, DL, DestReg, SrcReg, SystemZ::LR, 32, KillSrc); + emitGRX32Move(MBB, MBBI, DL, DestReg, SrcReg, SystemZ::LR, 32, KillSrc, + false); return; } diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.h b/llvm/lib/Target/SystemZ/SystemZInstrInfo.h index 794b193a501e..d44ce719b7fa 100644 --- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.h +++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.h @@ -151,7 +151,8 @@ class SystemZInstrInfo : public SystemZGenInstrInfo { void expandLoadStackGuard(MachineInstr *MI) const; void emitGRX32Move(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, - unsigned LowLowOpcode, unsigned Size, bool KillSrc) const; + unsigned LowLowOpcode, unsigned Size, bool KillSrc, + bool UndefSrc) const; virtual void anchor(); protected: diff --git a/llvm/test/CodeGen/SystemZ/undef-flag.ll b/llvm/test/CodeGen/SystemZ/undef-flag.ll new file mode 100644 index 000000000000..761559aa5a82 --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/undef-flag.ll @@ -0,0 +1,24 @@ +; Test that the backend does not mess up the I/R in case of a use of an undef +; register. This typically happens while expanding a pseudo or otherwise +; replacing an instruction for another. +; +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z13 -verify-machineinstrs \ +; RUN: |& FileCheck %s + + +; LLCRMux +define void @f1(i8*) { +; CHECK-LABEL: f1: +; CHECK-NOT: *** Bad machine code: Using an undefined physical register *** +BB: + %L5 = load i8, i8* %0 + %B9 = lshr i8 %L5, -1 + br label %CF + +CF: ; preds = %CF, %BB + %Cmp25 = icmp ne i8 27, %B9 + br i1 %Cmp25, label %CF, label %CF34 + +CF34: ; preds = %CF + ret void +}