Index: llvm/include/llvm/CodeGen/TargetInstrInfo.h =================================================================== --- llvm/include/llvm/CodeGen/TargetInstrInfo.h +++ llvm/include/llvm/CodeGen/TargetInstrInfo.h @@ -129,6 +129,14 @@ isReallyTriviallyReMaterializableGeneric(MI, AA))); } + /// Given \p MO is a PhysReg use return if it is a real or ambient use. + /// An ambient use is to model the execution environment not affecting + /// an instruction execution itself. Used to allow rematerialization of + /// an instruction using a predicate like register. + virtual bool isAmbientPhysRegUse(const MachineOperand &MO) const { + return false; + } + protected: /// For instructions with opcodes for which the M_REMATERIALIZABLE flag is /// set, this hook lets the target specify whether the instruction is actually Index: llvm/lib/CodeGen/LiveRangeEdit.cpp =================================================================== --- llvm/lib/CodeGen/LiveRangeEdit.cpp +++ llvm/lib/CodeGen/LiveRangeEdit.cpp @@ -115,7 +115,7 @@ // We can't remat physreg uses, unless it is a constant. if (Register::isPhysicalRegister(MO.getReg())) { - if (MRI.isConstantPhysReg(MO.getReg())) + if (MRI.isConstantPhysReg(MO.getReg()) || TII.isAmbientPhysRegUse(MO)) continue; return false; } Index: llvm/lib/Target/AMDGPU/SIInstrInfo.h =================================================================== --- llvm/lib/Target/AMDGPU/SIInstrInfo.h +++ llvm/lib/Target/AMDGPU/SIInstrInfo.h @@ -181,6 +181,8 @@ bool isReallyTriviallyReMaterializable(const MachineInstr &MI, AAResults *AA) const override; + bool isAmbientPhysRegUse(const MachineOperand &MO) const override; + bool areLoadsFromSameBasePtr(SDNode *Load1, SDNode *Load2, int64_t &Offset1, int64_t &Offset2) const override; Index: llvm/lib/Target/AMDGPU/SIInstrInfo.cpp =================================================================== --- llvm/lib/Target/AMDGPU/SIInstrInfo.cpp +++ llvm/lib/Target/AMDGPU/SIInstrInfo.cpp @@ -126,6 +126,11 @@ } } +bool SIInstrInfo::isAmbientPhysRegUse(const MachineOperand &MO) const { + // And implicit use of exec is not a real register read. + return MO.getReg() == AMDGPU::EXEC && MO.isImplicit(); +} + bool SIInstrInfo::areLoadsFromSameBasePtr(SDNode *Load0, SDNode *Load1, int64_t &Offset0, int64_t &Offset1) const { Index: llvm/test/CodeGen/AMDGPU/remat-vop.mir =================================================================== --- llvm/test/CodeGen/AMDGPU/remat-vop.mir +++ llvm/test/CodeGen/AMDGPU/remat-vop.mir @@ -52,6 +52,31 @@ S_ENDPGM 0 ... --- +name: test_remat_v_mov_b32_e32_exec_def +tracksRegLiveness: true +machineFunctionInfo: + stackPtrOffsetReg: $sgpr32 +body: | + bb.0: + ; GCN-LABEL: name: test_remat_v_mov_b32_e32_exec_def + ; GCN: renamable $vgpr0 = V_MOV_B32_e32 1, implicit $exec + ; GCN: renamable $vgpr1 = V_MOV_B32_e32 2, implicit $exec + ; GCN: S_NOP 0, implicit killed renamable $vgpr0 + ; GCN: S_NOP 0, implicit killed renamable $vgpr1 + ; GCN: renamable $vgpr0 = V_MOV_B32_e32 3, implicit $exec + ; GCN: S_NOP 0, implicit killed renamable $vgpr0 + ; GCN: $exec = S_ANDN2_B64_term $exec, undef renamable $sgpr0_sgpr1, implicit-def $scc + ; GCN: S_ENDPGM 0 + %0:vgpr_32 = V_MOV_B32_e32 1, implicit $exec + %1:vgpr_32 = V_MOV_B32_e32 2, implicit $exec + %2:vgpr_32 = V_MOV_B32_e32 3, implicit $exec + S_NOP 0, implicit %0 + S_NOP 0, implicit %1 + S_NOP 0, implicit %2 + $exec = S_ANDN2_B64_term $exec, undef %4:sreg_64, implicit-def $scc + S_ENDPGM 0 +... +--- name: test_remat_v_mov_b32_e64 tracksRegLiveness: true body: |