diff --git a/llvm/lib/Target/EraVM/EraVMAsmPrinter.cpp b/llvm/lib/Target/EraVM/EraVMAsmPrinter.cpp index 5280ae55e284..558d20023c56 100644 --- a/llvm/lib/Target/EraVM/EraVMAsmPrinter.cpp +++ b/llvm/lib/Target/EraVM/EraVMAsmPrinter.cpp @@ -150,6 +150,17 @@ void EraVMAsmPrinter::emitInstruction(const MachineInstr *MI) { llvm_unreachable("pseudo opcode found in emitInstruction()"); } + // All non-pseudo instructions can be predicated. + const auto *CCOperand = EraVM::ccIterator(*MI); + unsigned CondCode = getImmOrCImm(*CCOperand); + assert(CondCode != (unsigned)EraVMCC::COND_INVALID); + if (CondCode && !MI->hasRegisterImplicitUseOperand(EraVM::Flags)) { +#ifndef NDEBUG + MI->dump(); +#endif + llvm_unreachable("Predicated instruction should use Flags register"); + } + MCInstLowering.Lower(MI, TmpInst); EmitToStreamer(*OutStreamer, TmpInst); } diff --git a/llvm/lib/Target/EraVM/EraVMISelLowering.cpp b/llvm/lib/Target/EraVM/EraVMISelLowering.cpp index 9d8fd470e377..852d6f756431 100644 --- a/llvm/lib/Target/EraVM/EraVMISelLowering.cpp +++ b/llvm/lib/Target/EraVM/EraVMISelLowering.cpp @@ -1411,11 +1411,6 @@ void EraVMTargetLowering::AdjustInstrPostInstrSelection(MachineInstr &MI, SDNode *Node) const { assert(MI.hasPostISelHook() && "Expected instruction to have post-isel hook"); - // Set NoMerge to gasleft instructions. This has to be in sync with nomerge - // attribute in IntrinsicsEraVM.td for this intrinsic. - if (MI.getOpcode() == EraVM::CTXGasLeft) - MI.setFlag(MachineInstr::MIFlag::NoMerge); - // The overflow LT aka COND_OF caused by uaddo and umulo hasn't reversal // version actually, the GE can't be used according to the spec. We need to // add early-clobber attribute to the output register to prevent the RegAlloc @@ -1425,12 +1420,35 @@ void EraVMTargetLowering::AdjustInstrPostInstrSelection(MachineInstr &MI, // out = SELrrr i1 %ov, in0, in1, COND_OF // // when out and in0 are assigned to same register. - if (EraVM::isSelect(MI) && - getImmOrCImm(*EraVM::ccIterator(MI)) == EraVMCC::COND_OF) { + if (EraVM::isSelect(MI)) { + if (getImmOrCImm(*EraVM::ccIterator(MI)) != EraVMCC::COND_OF) + return; assert( (EraVM::argumentType(EraVM::ArgumentKind::In0, MI.getOpcode()) == EraVM::ArgumentType::Register) && "Expect register operand for the 1st input of SELECT with overflow LT"); EraVM::out0Iterator(MI)->setIsEarlyClobber(); + return; + } + + switch (MI.getOpcode()) { + default: + llvm_unreachable("Unexpected instruction passed to post-isel hook"); + case EraVM::JCl: { + const auto *CCOperand = EraVM::ccIterator(MI); + if (getImmOrCImm(*CCOperand) == EraVMCC::COND_NONE) { + // Instruction is not predicated - drop implicit use of Flags register. + int FlagsUseIdx = MI.findRegisterUseOperandIdx(EraVM::Flags); + assert(FlagsUseIdx < 0 && "Conservative Uses=[Flags] expected"); + assert(MI.getOperand(FlagsUseIdx).isImplicit()); + MI.removeOperand(FlagsUseIdx); + } + break; + } + case EraVM::CTXGasLeft: + // Set NoMerge to gasleft instructions. This has to be in sync with nomerge + // attribute in IntrinsicsEraVM.td for this intrinsic. + MI.setFlag(MachineInstr::MIFlag::NoMerge); + break; } } diff --git a/llvm/lib/Target/EraVM/EraVMInstrFormats.td b/llvm/lib/Target/EraVM/EraVMInstrFormats.td index 1a61c87171c3..016a4670565a 100644 --- a/llvm/lib/Target/EraVM/EraVMInstrFormats.td +++ b/llvm/lib/Target/EraVM/EraVMInstrFormats.td @@ -310,6 +310,19 @@ class IForm Uses = [Flags]; + bit hasPostISelHook = true; +} + class IJump pattern> diff --git a/llvm/lib/Target/EraVM/EraVMInstrInfo.cpp b/llvm/lib/Target/EraVM/EraVMInstrInfo.cpp index 2b10ca9a063e..3ea8c24f7c70 100644 --- a/llvm/lib/Target/EraVM/EraVMInstrInfo.cpp +++ b/llvm/lib/Target/EraVM/EraVMInstrInfo.cpp @@ -405,8 +405,12 @@ unsigned EraVMInstrInfo::insertBranch( } // Conditional branch. unsigned Count = 0; - auto cond_code = getImmOrCImm(Cond[0]); - BuildMI(&MBB, DL, get(EraVM::JCl)).addMBB(TBB).addImm(cond_code); + auto CondCode = getImmOrCImm(Cond[0]); + const MachineInstrBuilder &MIB = + BuildMI(&MBB, DL, get(EraVM::JCl)).addMBB(TBB).addImm(CondCode); + // Do not accidentally use a dead register. + if (CondCode != EraVMCC::COND_NONE) + MIB.addUse(EraVM::Flags, RegState::Implicit); ++Count; if (FBB) { diff --git a/llvm/lib/Target/EraVM/EraVMInstrInfo.td b/llvm/lib/Target/EraVM/EraVMInstrInfo.td index 7c7933e4f6cc..0e745150e94c 100644 --- a/llvm/lib/Target/EraVM/EraVMInstrInfo.td +++ b/llvm/lib/Target/EraVM/EraVMInstrInfo.td @@ -971,10 +971,9 @@ class JumpViaStack : JumpViaConst; // a return address operand can be used as a cheaper replacement for "call", // so it may be worth making it non-terminator in the future. -let Uses = [Flags] in // TODO Do not set implicit use unconditionally. def JCl : IJump, - JumpWithoutRetAddr, JumpViaLabel; + JumpWithoutRetAddr, JumpViaLabel, MayBePredicatedViaPattern; def JClr : IJump, JumpWithRetAddr, JumpViaLabel; diff --git a/llvm/lib/Target/EraVM/EraVMOptimizeSelectPostRA.cpp b/llvm/lib/Target/EraVM/EraVMOptimizeSelectPostRA.cpp index 588911438e42..2a78def45860 100644 --- a/llvm/lib/Target/EraVM/EraVMOptimizeSelectPostRA.cpp +++ b/llvm/lib/Target/EraVM/EraVMOptimizeSelectPostRA.cpp @@ -232,8 +232,7 @@ bool EraVMOptimizeSelectPostRA::runOnMachineFunction(MachineFunction &MF) { for (auto [CMov, FoldInst] : Deleted) { LLVM_DEBUG(dbgs() << "== Folding cond move:"; CMov->dump(); dbgs() << " into:"; FoldInst->dump();); - EraVM::ccIterator(*FoldInst)->ChangeToImmediate( - getImmOrCImm(*EraVM::ccIterator(*CMov))); + TII->PredicateInstruction(*FoldInst, ArrayRef(*EraVM::ccIterator(*CMov))); EraVM::out0Iterator(*FoldInst)->setReg( EraVM::out0Iterator(*CMov)->getReg()); CMov->eraseFromParent(); diff --git a/llvm/test/CodeGen/EraVM/select_fold.mir b/llvm/test/CodeGen/EraVM/select_fold.mir index 19b97621a30a..4178892d83be 100644 --- a/llvm/test/CodeGen/EraVM/select_fold.mir +++ b/llvm/test/CodeGen/EraVM/select_fold.mir @@ -46,7 +46,7 @@ --- # CHECK-LABEL: test_add_reg # CHECK-LABEL: bb.0: -# CHECK: $r1 = ADDrrr_s $r1, $r1, 9 +# CHECK: $r1 = ADDrrr_s $r1, $r1, i256 9, implicit $flags name: test_add_reg tracksRegLiveness: true body: |