This is an archive of the discontinued LLVM Phabricator instance.

[AVR] Optimize away cpi instructions when possible
Needs RevisionPublic

Authored by aykevl on Jan 3 2023, 12:35 PM.

Details

Summary

In many cases, the cpi instruction can be skipped because a previous instruction already sets the needed flags.

This saves around 1% in binary size.

Future improvements:

  • remove cp in sub r1, r2 and cp r1, r2
  • optimize andi + breq/brne to sbrs/sbrc + rjmp like avr-gcc does (this avoids clobbering a register and should therefore result in better generated code)
  • maybe do the same optimization for other flags too?

Diff Detail

Event Timeline

aykevl created this revision.Jan 3 2023, 12:35 PM
Herald added a project: Restricted Project. · View Herald TranscriptJan 3 2023, 12:35 PM
Herald added subscribers: Jim, hiraditya. · View Herald Transcript
aykevl requested review of this revision.Jan 3 2023, 12:35 PM
Herald added a project: Restricted Project. · View Herald TranscriptJan 3 2023, 12:35 PM
aykevl updated this revision to Diff 486052.Jan 3 2023, 12:41 PM
aykevl edited the summary of this revision. (Show Details)
  • update branch relaxation tests that got changed by this patch

This patch was largely based on X86InstrInfo::optimizeCompareInstr in llvm/lib/Target/X86/X86InstrInfo.cpp. Of course, the X86 version is much, much larger.

aykevl edited the summary of this revision. (Show Details)Jan 3 2023, 1:09 PM
aykevl set the repository for this revision to rG LLVM Github Monorepo.
aykevl edited the summary of this revision. (Show Details)
aykevl added a comment.Jan 6 2023, 1:26 PM

I ran the TinyGo tests with this patch and all tests still pass, while code size is reduced by 0.75%.

After this patch is merged I'd like to try implementing the sbic/sbis + rjmp optimization and see whether it indeed reduces code size (I think it will avoid some unnecessary copies and reduce register pressure).

benshi001 added inline comments.Jan 9 2023, 7:28 PM
llvm/lib/Target/AVR/AVRInstrInfo.cpp
202

It would be better to add a range check here.

  1. The MI.getOperand(1).getImm(); should be in range [0, 255], otherwise llvm_unreachable();
  2. The CmpMask should be 255, since it is int64_t type.
207

Can the form be that

switch {
default:
  // TOTO: Implement more compare instructions.
  return false;

case AVR::CPIRdK:
  ..
}
218

I think it would better to use a std::array than switch.

233

Why LSL, ROL are not in this list ?

benshi001 added inline comments.Jan 9 2023, 8:11 PM
llvm/lib/Target/AVR/AVRInstrInfo.cpp
214

Rename this function to setsZeroFlagInstr.

252

Can it be

if ((CmpMask & CmpValue) != 0)
  return false;

This look more clear.

267

const MachineBasicBlock & ?

269

Use auto From ?

273

This piece of searching previous instr clobbers SREG code, can be isolated to a stand alone bool function, it may be used by future optimizations you have planed.

Generally speaking

llvm/lib/Target/AVR/AVRInstrInfo.cpp
214

change the parameter to const MachineInstr * .

251

Generally speaking, I suggest you make a skeleton first, then handle special situations (current cpi and further ones you mentioned in your commit message) in stand alone funcitons, this way would make the code looks more clear.

256

const auto * ?

268

FoundDef -> FoundClobber .

benshi001 requested changes to this revision.Jan 9 2023, 8:36 PM
This revision now requires changes to proceed.Jan 9 2023, 8:36 PM
benshi001 added inline comments.Jan 9 2023, 8:42 PM
llvm/test/CodeGen/AVR/branch-relaxation.ll
4

CHECK-NOT: cpi

llvm/test/CodeGen/AVR/fold-cmp.mir
13

It would be better to add CHECK-NOT: cpi in all your tests.

benshi001 added inline comments.Jan 9 2023, 11:35 PM
llvm/lib/Target/AVR/AVRInstrInfo.cpp
290

Can it be if (Instr.getOpcode() == AVR::BRNEk || Instr.getOpcode() == AVR::BREQk) ? I do not think we need a switch which means more than 2 choices.

301

Is this comment line correct? May it be

// This instruction might read other flags (than Z) which are set by CPI.

Does this pass happpen before the expansion of pseudoes or after? Do we have to consider pseudoes ?

benshi001 added inline comments.Jan 9 2023, 11:51 PM
llvm/test/CodeGen/AVR/fold-cmp.mir
84

How about adding more cases

  1. that there is a stand alone CPI (the ANDI maybe in a preceeding block), in which the CPI is not deleted.
  2. ADIW + CPI, the CPI should not be deleted.