diff --git a/lib/CodeGen/MachineCSE.cpp b/lib/CodeGen/MachineCSE.cpp index 0143d0fbea2..fc3f5943d71 100644 --- a/lib/CodeGen/MachineCSE.cpp +++ b/lib/CodeGen/MachineCSE.cpp @@ -24,7 +24,6 @@ #include "llvm/ADT/ScopedHashTable.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/Statistic.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" using namespace llvm; @@ -33,6 +32,7 @@ STATISTIC(NumCoalesces, "Number of copies coalesced"); STATISTIC(NumCSEs, "Number of common subexpression eliminated"); STATISTIC(NumPhysCSEs, "Number of physreg referencing common subexpr eliminated"); +STATISTIC(NumCommutes, "Number of copies coalesced after commuting"); namespace { class MachineCSE : public MachineFunctionPass { @@ -368,7 +368,22 @@ bool MachineCSE::ProcessBlock(MachineBasicBlock *MBB) { FoundCSE = VNT.count(MI); } } - // FIXME: commute commutable instructions? + + // Commute commutable instructions. + bool Commuted = false; + if (!FoundCSE && MI->getDesc().isCommutable()) { + MachineInstr *NewMI = TII->commuteInstruction(MI); + if (NewMI) { + Commuted = true; + FoundCSE = VNT.count(NewMI); + if (NewMI != MI) + // New instruction. It doesn't need to be kept. + NewMI->eraseFromParent(); + else if (!FoundCSE) + // MI was changed but it didn't help, commute it back! + (void)TII->commuteInstruction(MI); + } + } // If the instruction defines physical registers and the values *may* be // used, then it's not safe to replace it with a common subexpression. @@ -430,6 +445,8 @@ bool MachineCSE::ProcessBlock(MachineBasicBlock *MBB) { ++NumCSEs; if (!PhysRefs.empty()) ++NumPhysCSEs; + if (Commuted) + ++NumCommutes; } else { DEBUG(dbgs() << "*** Not profitable, avoid CSE!\n"); VNT.insert(MI, CurrVN++); diff --git a/test/CodeGen/X86/machine-cse.ll b/test/CodeGen/X86/machine-cse.ll index a8afdc84c51..e284776ed02 100644 --- a/test/CodeGen/X86/machine-cse.ll +++ b/test/CodeGen/X86/machine-cse.ll @@ -37,3 +37,43 @@ bb3: declare void @bar(i32*) declare fastcc i8* @foo(%struct.s2*) nounwind + +; rdar://8773371 + +declare void @printf(...) nounwind + +define void @commute(i32 %test_case, i32 %scale) nounwind ssp { +; CHECK: commute: +entry: + switch i32 %test_case, label %sw.bb307 [ + i32 1, label %sw.bb + i32 2, label %sw.bb + i32 3, label %sw.bb + ] + +sw.bb: ; preds = %entry, %entry, %entry + %mul = mul nsw i32 %test_case, 3 + %mul20 = mul nsw i32 %mul, %scale + br i1 undef, label %if.end34, label %sw.bb307 + +if.end34: ; preds = %sw.bb +; CHECK: %if.end34 +; CHECK: imull +; CHECK: leal +; CHECK-NOT: imull + tail call void (...)* @printf(i32 %test_case, i32 %mul20) nounwind + %tmp = mul i32 %scale, %test_case + %tmp752 = mul i32 %tmp, 3 + %tmp753 = zext i32 %tmp752 to i64 + br label %bb.nph743.us + +for.body53.us: ; preds = %bb.nph743.us, %for.body53.us + %exitcond = icmp eq i64 undef, %tmp753 + br i1 %exitcond, label %bb.nph743.us, label %for.body53.us + +bb.nph743.us: ; preds = %for.body53.us, %if.end34 + br label %for.body53.us + +sw.bb307: ; preds = %sw.bb, %entry + ret void +}