[PATCH] D152248: [AVR] Fix incorrect expanded pseudo instruction ROLBRd
Patryk Wychowaniec via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 6 03:02:42 PDT 2023
Patryk27 added inline comments.
================
Comment at: llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp:1488
+ // due to aykevl's comment in https://reviews.llvm.org/D152063 .
+ buildMI(MBB, MBBI, AVR::EORRdRr)
+ .addReg(TmpReg, RegState::Define)
----------------
Patryk27 wrote:
> benshi001 wrote:
> > Patryk27 wrote:
> > > Hmm, this feels kinda excessive - wouldn't adding `let Uses = [R1]` to `ROLBRd` be sufficient?
> > >
> > > ```
> > > let Uses = [R1] in
> > > def ROLBRd : Pseudo<(outs GPR8
> > > : $rd),
> > > (ins GPR8
> > > : $src),
> > > "rolb\t$rd",
> > > [(set i8
> > > : $rd, (AVRrol i8
> > > : $src)),
> > > (implicit SREG)]>;
> > > ```
> > Because it maybe `R17` on AVRTINY.
> ah, true, true
Maybe we could have two separate instructions, then?
Something like:
```
diff --git a/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp b/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
index 726ed7303746..94cabb4e1387 100644
--- a/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
@@ -1481,7 +1481,48 @@ bool AVRExpandPseudo::expand<AVR::POPWRd>(Block &MBB, BlockIt MBBI) {
}
template <>
-bool AVRExpandPseudo::expand<AVR::ROLBRd>(Block &MBB, BlockIt MBBI) {
+bool AVRExpandPseudo::expand<AVR::ROLBRdNT>(Block &MBB, BlockIt MBBI) {
+ // In AVR, the rotate instructions behave quite unintuitively. They rotate
+ // bits through the carry bit in SREG, effectively rotating over 9 bits,
+ // instead of 8. This is useful when we are dealing with numbers over
+ // multiple registers, but when we actually need to rotate stuff, we have
+ // to explicitly add the carry bit.
+
+ const AVRSubtarget &STI = MBB.getParent()->getSubtarget<AVRSubtarget>();
+
+ MachineInstr &MI = *MBBI;
+ unsigned OpShift, OpCarry;
+ Register DstReg = MI.getOperand(0).getReg();
+ Register ZeroReg = STI.getZeroRegister();
+ bool DstIsDead = MI.getOperand(0).isDead();
+ bool DstIsKill = MI.getOperand(1).isKill();
+ OpShift = AVR::ADDRdRr;
+ OpCarry = AVR::ADCRdRr;
+
+ // add r16, r16
+ // adc r16, r1
+
+ // Shift part
+ buildMI(MBB, MBBI, OpShift)
+ .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
+ .addReg(DstReg, RegState::Kill)
+ .addReg(DstReg, RegState::Kill);
+
+ // Add the carry bit
+ auto MIB = buildMI(MBB, MBBI, OpCarry)
+ .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
+ .addReg(DstReg, getKillRegState(DstIsKill))
+ .addReg(ZeroReg);
+
+ MIB->getOperand(3).setIsDead(); // SREG is always dead
+ MIB->getOperand(4).setIsKill(); // SREG is always implicitly killed
+
+ MI.eraseFromParent();
+ return true;
+}
+
+template <>
+bool AVRExpandPseudo::expand<AVR::ROLBRdT>(Block &MBB, BlockIt MBBI) {
// In AVR, the rotate instructions behave quite unintuitively. They rotate
// bits through the carry bit in SREG, effectively rotating over 9 bits,
// instead of 8. This is useful when we are dealing with numbers over
@@ -2605,7 +2646,8 @@ bool AVRExpandPseudo::expandMI(Block &MBB, BlockIt MBBI) {
EXPAND(AVR::OUTWARr);
EXPAND(AVR::PUSHWRr);
EXPAND(AVR::POPWRd);
- EXPAND(AVR::ROLBRd);
+ EXPAND(AVR::ROLBRdNT);
+ EXPAND(AVR::ROLBRdT);
EXPAND(AVR::RORBRd);
EXPAND(AVR::LSLWRd);
EXPAND(AVR::LSRWRd);
diff --git a/llvm/lib/Target/AVR/AVRISelLowering.cpp b/llvm/lib/Target/AVR/AVRISelLowering.cpp
index e44ef51ab3a8..d97b02681f2e 100644
--- a/llvm/lib/Target/AVR/AVRISelLowering.cpp
+++ b/llvm/lib/Target/AVR/AVRISelLowering.cpp
@@ -1758,6 +1758,7 @@ MachineBasicBlock *AVRTargetLowering::insertShift(MachineInstr &MI,
MachineFunction *F = BB->getParent();
MachineRegisterInfo &RI = F->getRegInfo();
const TargetInstrInfo &TII = *Subtarget.getInstrInfo();
+ const AVRSubtarget &STI = F->getSubtarget<AVRSubtarget>();
DebugLoc dl = MI.getDebugLoc();
switch (MI.getOpcode()) {
@@ -1789,7 +1790,7 @@ MachineBasicBlock *AVRTargetLowering::insertShift(MachineInstr &MI,
RC = &AVR::DREGSRegClass;
break;
case AVR::Rol8:
- Opc = AVR::ROLBRd;
+ Opc = STI.hasTinyEncoding() ? AVR::ROLBRdT : AVR::ROLBRdNT;
RC = &AVR::GPR8RegClass;
break;
case AVR::Rol16:
diff --git a/llvm/lib/Target/AVR/AVRInstrInfo.td b/llvm/lib/Target/AVR/AVRInstrInfo.td
index d0e75733114a..630369d2d25e 100644
--- a/llvm/lib/Target/AVR/AVRInstrInfo.td
+++ b/llvm/lib/Target/AVR/AVRInstrInfo.td
@@ -2029,7 +2029,8 @@ let Constraints = "$src = $rd", Defs = [SREG] in {
def ASRWLoRd : Pseudo<(outs DREGS:$rd), (ins DREGS:$src), "asrwlo\t$rd",
[(set i16:$rd, (AVRasrlo i16:$src)), (implicit SREG)]>;
- def ROLBRd : Pseudo<(outs GPR8
+ let Uses = [R1] in
+ def ROLBRdNT : Pseudo<(outs GPR8
: $rd),
(ins GPR8
: $src),
@@ -2037,7 +2038,20 @@ let Constraints = "$src = $rd", Defs = [SREG] in {
[(set i8
: $rd, (AVRrol i8
: $src)),
- (implicit SREG)]>;
+ (implicit SREG)]>,
+ Requires<[HasNonTinyEncoding]>;
+
+ let Uses = [R17] in
+ def ROLBRdT : Pseudo<(outs GPR8
+ : $rd),
+ (ins GPR8
+ : $src),
+ "rolb\t$rd",
+ [(set i8
+ : $rd, (AVRrol i8
+ : $src)),
+ (implicit SREG)]>,
+ Requires<[HasTinyEncoding]>;
def RORBRd : Pseudo<(outs GPR8
: $rd),
```
Of course, this naive approach copy-pastes the code responsible for expanding the pseudo-instruction, but that could should be pretty easy to de-duplicate.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D152248/new/
https://reviews.llvm.org/D152248
More information about the llvm-commits
mailing list