aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2005-09-09 18:17:41 +0000
committerChris Lattner <sabre@nondot.org>2005-09-09 18:17:41 +0000
commit043870dd85ea41e8972c304b122070a417c8a4bc (patch)
tree3fd01c064cce7304e5c9dcf1243a20f8ebb3ed13
parented628ce7bffeda318c4ef7b245f2f0fdc31596f4 (diff)
Teach the code generator that rlwimi is commutable if the rotate amount
is zero. This lets the register allocator elide some copies in some cases. This implements CodeGen/PowerPC/rlwimi-commute.ll git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23292 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/PowerPC/PPCInstrInfo.cpp32
-rw-r--r--lib/Target/PowerPC/PPCInstrInfo.h4
-rw-r--r--lib/Target/PowerPC/PPCInstrInfo.td3
3 files changed, 38 insertions, 1 deletions
diff --git a/lib/Target/PowerPC/PPCInstrInfo.cpp b/lib/Target/PowerPC/PPCInstrInfo.cpp
index 50ad423cf7..3ec78e3456 100644
--- a/lib/Target/PowerPC/PPCInstrInfo.cpp
+++ b/lib/Target/PowerPC/PPCInstrInfo.cpp
@@ -76,3 +76,35 @@ bool PPC32InstrInfo::isMoveInstr(const MachineInstr& MI,
}
return false;
}
+
+// commuteInstruction - We can commute rlwimi instructions, but only if the
+// rotate amt is zero. We also have to munge the immediates a bit.
+MachineInstr *PPC32InstrInfo::commuteInstruction(MachineInstr *MI) const {
+ // Normal instructions can be commuted the obvious way.
+ if (MI->getOpcode() != PPC::RLWIMI)
+ return TargetInstrInfo::commuteInstruction(MI);
+
+ // Cannot commute if it has a non-zero rotate count.
+ if (MI->getOperand(3).getImmedValue() != 0)
+ return 0;
+
+ // If we have a zero rotate count, we have:
+ // M = mask(MB,ME)
+ // Op0 = (Op1 & ~M) | (Op2 & M)
+ // Change this to:
+ // M = mask((ME+1)&31, (MB-1)&31)
+ // Op0 = (Op2 & ~M) | (Op1 & M)
+
+ // Swap op1/op2
+ unsigned Reg1 = MI->getOperand(1).getReg();
+ unsigned Reg2 = MI->getOperand(2).getReg();
+ MI->SetMachineOperandReg(2, Reg1);
+ MI->SetMachineOperandReg(1, Reg2);
+
+ // Swap the mask around.
+ unsigned MB = MI->getOperand(4).getImmedValue();
+ unsigned ME = MI->getOperand(5).getImmedValue();
+ MI->getOperand(4).setImmedValue((ME+1) & 31);
+ MI->getOperand(5).setImmedValue((MB-1) & 31);
+ return MI;
+}
diff --git a/lib/Target/PowerPC/PPCInstrInfo.h b/lib/Target/PowerPC/PPCInstrInfo.h
index 35bab982f0..bbc0be4cd5 100644
--- a/lib/Target/PowerPC/PPCInstrInfo.h
+++ b/lib/Target/PowerPC/PPCInstrInfo.h
@@ -38,6 +38,10 @@ public:
unsigned& sourceReg,
unsigned& destReg) const;
+ // commuteInstruction - We can commute rlwimi instructions, but only if the
+ // rotate amt is zero. We also have to munge the immediates a bit.
+ virtual MachineInstr *commuteInstruction(MachineInstr *MI) const;
+
static unsigned invertPPCBranchOpcode(unsigned Opcode) {
switch (Opcode) {
default: assert(0 && "Unknown PPC branch opcode!");
diff --git a/lib/Target/PowerPC/PPCInstrInfo.td b/lib/Target/PowerPC/PPCInstrInfo.td
index 33c52441f0..96a8ea7bce 100644
--- a/lib/Target/PowerPC/PPCInstrInfo.td
+++ b/lib/Target/PowerPC/PPCInstrInfo.td
@@ -733,7 +733,8 @@ def FSUBS : AForm_2<59, 20,
// M-Form instructions. rotate and mask instructions.
//
-let isTwoAddress = 1 in {
+let isTwoAddress = 1, isCommutable = 1 in {
+// RLWIMI can be commuted if the rotate amount is zero.
def RLWIMI : MForm_2<20,
(ops GPRC:$rA, GPRC:$rSi, GPRC:$rS, u5imm:$SH, u5imm:$MB,
u5imm:$ME), "rlwimi $rA, $rS, $SH, $MB, $ME">;