Skip to content

Commit

Permalink
[EraVM] Do not set Uses=[Flags] unconditionally in JCl
Browse files Browse the repository at this point in the history
  • Loading branch information
atrosinenko committed Jun 12, 2024
1 parent 628e115 commit c359618
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 14 deletions.
11 changes: 11 additions & 0 deletions llvm/lib/Target/EraVM/EraVMAsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
32 changes: 25 additions & 7 deletions llvm/lib/Target/EraVM/EraVMISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
}
}
13 changes: 13 additions & 0 deletions llvm/lib/Target/EraVM/EraVMInstrFormats.td
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,19 @@ class IForm <EraVMOpcode opcode,
let UseLogicalOperandMappings = true;
}

// Mix-in class for IForm instances that can be predicated by the
// tablegen-erated instruction selector rules.
// Note: if marking an instruction with this mix-in, add one more `case` line
// to EraVMTargetLowering::AdjustInstrPostInstrSelection.
class MayBePredicatedViaPattern {
// Make ISel conservatively assume Flags register is used by this instruction
// and drop this Use in AdjustInstrPostInstrSelection as needed.
// This prevents incorrecly marking previous Defs as dead if the instruction
// is actually predicated.
list<Register> Uses = [Flags];
bit hasPostISelHook = true;
}

class IJump<EraVMOpcode opcode,
SrcMode src,
dag outs, dag ins, string asmstr, list<dag> pattern>
Expand Down
8 changes: 6 additions & 2 deletions llvm/lib/Target/EraVM/EraVMInstrInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
3 changes: 1 addition & 2 deletions llvm/lib/Target/EraVM/EraVMInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -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<OpJump, SrcImm, (outs), (ins jmptarget:$dest), "$dest",
[(EraVMbrcc bb:$dest, imm:$cc)]>,
JumpWithoutRetAddr, JumpViaLabel;
JumpWithoutRetAddr, JumpViaLabel, MayBePredicatedViaPattern;
def JClr : IJump<OpJump, SrcImm, (outs GR256:$ret_addr), (ins jmptarget:$dest), "$dest, $ret_addr", []>,
JumpWithRetAddr, JumpViaLabel;

Expand Down
3 changes: 1 addition & 2 deletions llvm/lib/Target/EraVM/EraVMOptimizeSelectPostRA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/CodeGen/EraVM/select_fold.mir
Original file line number Diff line number Diff line change
Expand Up @@ -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: |
Expand Down

0 comments on commit c359618

Please sign in to comment.