<html><head><meta http-equiv="Content-Type" content="text/html charset=windows-1252"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><br><div><div>On Jun 23, 2013, at 6:17 AM, Hal Finkel <<a href="mailto:hfinkel@anl.gov">hfinkel@anl.gov</a>> wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div style="letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">----- Original Message -----<br><blockquote type="cite">Author: atrick<br>Date: Sun Jun 23 04:00:28 2013<br>New Revision: 184664<br><br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project?rev=184664&view=rev">http://llvm.org/viewvc/llvm-project?rev=184664&view=rev</a><br>Log:<br>Add MI-Sched support for x86 macro fusion.<br><br>This is an awful implementation of the target hook. But we don't have<br>abstractions yet for common machine ops, and I don't see any quick<br>way<br>to make it table-driven.<br></blockquote><br>This may not be 'quick' (or sufficiently clean), but if you were to define pseudo-instructions to represent FuseTest, FuseCmp, FuseInc, then you could use TableGen's InstrMapping backend to generate a query function for these.<br></div></blockquote><div dir="auto"><br></div><div dir="auto">Yes, exactly. That’s how I would like it to work. It would take me a bit of time to figure out how, and I’m also not sure it will be cleaner. I’m can’t say when I’ll get to this cleanup task, so if anyone else wants to tackle it, be my guest.</div><div dir="auto"><br></div><div dir="auto">Thanks for the suggestion,</div><div dir="auto">-Andy</div><br><blockquote type="cite"><div style="letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><blockquote type="cite">Added:<br>   llvm/trunk/test/CodeGen/X86/misched-fusion.ll<br>Modified:<br>   llvm/trunk/lib/Target/X86/X86InstrInfo.cpp<br>   llvm/trunk/lib/Target/X86/X86InstrInfo.h<br><br>Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.cpp<br>URL:<br><a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.cpp?rev=184664&r1=184663&r2=184664&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.cpp?rev=184664&r1=184663&r2=184664&view=diff</a><br>==============================================================================<br>--- llvm/trunk/lib/Target/X86/X86InstrInfo.cpp (original)<br>+++ llvm/trunk/lib/Target/X86/X86InstrInfo.cpp Sun Jun 23 04:00:28<br>2013<br>@@ -4647,6 +4647,167 @@ bool X86InstrInfo::shouldScheduleLoadsNe<br>  return true;<br>}<br><br>+bool X86InstrInfo::shouldScheduleAdjacent(MachineInstr* First,<br>+                                          MachineInstr *Second)<br>const {<br>+  // Check if this processor supports macro-fusion. Since this is a<br>minor<br>+  // heuristic, we haven't specifically reserved a feature. hasAVX<br>is a decent<br>+  // proxy for SandyBridge+.<br>+  if (!TM.getSubtarget<X86Subtarget>().hasAVX())<br>+    return false;<br>+<br>+  enum {<br>+    FuseTest,<br>+    FuseCmp,<br>+    FuseInc<br>+  } FuseKind;<br>+<br>+  switch(Second->getOpcode()) {<br>+  default:<br>+    return false;<br>+  case X86::JE_4:<br>+  case X86::JNE_4:<br>+  case X86::JL_4:<br>+  case X86::JLE_4:<br>+  case X86::JG_4:<br>+  case X86::JGE_4:<br>+    FuseKind = FuseInc;<br>+    break;<br>+  case X86::JB_4:<br>+  case X86::JBE_4:<br>+  case X86::JA_4:<br>+  case X86::JAE_4:<br>+    FuseKind = FuseCmp;<br>+    break;<br>+  case X86::JS_4:<br>+  case X86::JNS_4:<br>+  case X86::JP_4:<br>+  case X86::JNP_4:<br>+  case X86::JO_4:<br>+  case X86::JNO_4:<br>+    FuseKind = FuseTest;<br>+    break;<br>+  }<br>+  switch (First->getOpcode()) {<br>+  default:<br>+    return false;<br>+  case X86::TEST8rr:<br>+  case X86::TEST16rr:<br>+  case X86::TEST32rr:<br>+  case X86::TEST64rr:<br>+  case X86::TEST8ri:<br>+  case X86::TEST16ri:<br>+  case X86::TEST32ri:<br>+  case X86::TEST32i32:<br>+  case X86::TEST64i32:<br>+  case X86::TEST64ri32:<br>+  case X86::TEST8rm:<br>+  case X86::TEST16rm:<br>+  case X86::TEST32rm:<br>+  case X86::TEST64rm:<br>+  case X86::AND16i16:<br>+  case X86::AND16ri:<br>+  case X86::AND16ri8:<br>+  case X86::AND16rm:<br>+  case X86::AND16rr:<br>+  case X86::AND32i32:<br>+  case X86::AND32ri:<br>+  case X86::AND32ri8:<br>+  case X86::AND32rm:<br>+  case X86::AND32rr:<br>+  case X86::AND64i32:<br>+  case X86::AND64ri32:<br>+  case X86::AND64ri8:<br>+  case X86::AND64rm:<br>+  case X86::AND64rr:<br>+  case X86::AND8i8:<br>+  case X86::AND8ri:<br>+  case X86::AND8rm:<br>+  case X86::AND8rr:<br>+    return true;<br>+  case X86::CMP16i16:<br>+  case X86::CMP16ri:<br>+  case X86::CMP16ri8:<br>+  case X86::CMP16rm:<br>+  case X86::CMP16rr:<br>+  case X86::CMP32i32:<br>+  case X86::CMP32ri:<br>+  case X86::CMP32ri8:<br>+  case X86::CMP32rm:<br>+  case X86::CMP32rr:<br>+  case X86::CMP64i32:<br>+  case X86::CMP64ri32:<br>+  case X86::CMP64ri8:<br>+  case X86::CMP64rm:<br>+  case X86::CMP64rr:<br>+  case X86::CMP8i8:<br>+  case X86::CMP8ri:<br>+  case X86::CMP8rm:<br>+  case X86::CMP8rr:<br>+  case X86::ADD16i16:<br>+  case X86::ADD16ri:<br>+  case X86::ADD16ri8:<br>+  case X86::ADD16ri8_DB:<br>+  case X86::ADD16ri_DB:<br>+  case X86::ADD16rm:<br>+  case X86::ADD16rr:<br>+  case X86::ADD16rr_DB:<br>+  case X86::ADD32i32:<br>+  case X86::ADD32ri:<br>+  case X86::ADD32ri8:<br>+  case X86::ADD32ri8_DB:<br>+  case X86::ADD32ri_DB:<br>+  case X86::ADD32rm:<br>+  case X86::ADD32rr:<br>+  case X86::ADD32rr_DB:<br>+  case X86::ADD64i32:<br>+  case X86::ADD64ri32:<br>+  case X86::ADD64ri32_DB:<br>+  case X86::ADD64ri8:<br>+  case X86::ADD64ri8_DB:<br>+  case X86::ADD64rm:<br>+  case X86::ADD64rr:<br>+  case X86::ADD64rr_DB:<br>+  case X86::ADD8i8:<br>+  case X86::ADD8mi:<br>+  case X86::ADD8mr:<br>+  case X86::ADD8ri:<br>+  case X86::ADD8rm:<br>+  case X86::ADD8rr:<br>+  case X86::SUB16i16:<br>+  case X86::SUB16ri:<br>+  case X86::SUB16ri8:<br>+  case X86::SUB16rm:<br>+  case X86::SUB16rr:<br>+  case X86::SUB32i32:<br>+  case X86::SUB32ri:<br>+  case X86::SUB32ri8:<br>+  case X86::SUB32rm:<br>+  case X86::SUB32rr:<br>+  case X86::SUB64i32:<br>+  case X86::SUB64ri32:<br>+  case X86::SUB64ri8:<br>+  case X86::SUB64rm:<br>+  case X86::SUB64rr:<br>+  case X86::SUB8i8:<br>+  case X86::SUB8ri:<br>+  case X86::SUB8rm:<br>+  case X86::SUB8rr:<br>+    return FuseKind == FuseCmp || FuseKind == FuseInc;<br>+  case X86::INC16r:<br>+  case X86::INC32r:<br>+  case X86::INC64_16r:<br>+  case X86::INC64_32r:<br>+  case X86::INC64r:<br>+  case X86::INC8r:<br>+  case X86::DEC16r:<br>+  case X86::DEC32r:<br>+  case X86::DEC64_16r:<br>+  case X86::DEC64_32r:<br>+  case X86::DEC64r:<br>+  case X86::DEC8r:<br>+    return FuseKind == FuseInc;<br>+  }<br>+}<br><br>bool X86InstrInfo::<br>ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const<br>{<br><br>Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.h<br>URL:<br><a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.h?rev=184664&r1=184663&r2=184664&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.h?rev=184664&r1=184663&r2=184664&view=diff</a><br>==============================================================================<br>--- llvm/trunk/lib/Target/X86/X86InstrInfo.h (original)<br>+++ llvm/trunk/lib/Target/X86/X86InstrInfo.h Sun Jun 23 04:00:28 2013<br>@@ -339,6 +339,9 @@ public:<br>                                       int64_t Offset1, int64_t<br>                                       Offset2,<br>                                       unsigned NumLoads) const;<br><br>+  virtual bool shouldScheduleAdjacent(MachineInstr* First,<br>+                                      MachineInstr *Second) const<br>LLVM_OVERRIDE;<br>+<br>  virtual void getNoopForMachoTarget(MCInst &NopInst) const;<br><br>  virtual<br><br>Added: llvm/trunk/test/CodeGen/X86/misched-fusion.ll<br>URL:<br><a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/misched-fusion.ll?rev=184664&view=auto">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/misched-fusion.ll?rev=184664&view=auto</a><br>==============================================================================<br>--- llvm/trunk/test/CodeGen/X86/misched-fusion.ll (added)<br>+++ llvm/trunk/test/CodeGen/X86/misched-fusion.ll Sun Jun 23 04:00:28<br>2013<br>@@ -0,0 +1,108 @@<br>+; RUN: llc < %s -march=x86-64 -mcpu=corei7-avx -disable-lsr<br>-pre-RA-sched=source -enable-misched -verify-machineinstrs |<br>FileCheck %s<br>+<br>+; Verify that TEST+JE are scheduled together.<br>+; CHECK: test_je<br>+; CHECK: %loop<br>+; CHECK: test<br>+; CHECK-NEXT: je<br>+define void @test_je() {<br>+entry:<br>+  br label %loop<br>+<br>+loop:<br>+  %var = phi i32* [ null, %entry ], [ %next.load, %loop1 ], [ %var,<br>%loop2 ]<br>+  %next.ptr = phi i32** [ null, %entry ], [ %next.ptr, %loop1 ], [<br>%gep, %loop2 ]<br>+  br label %loop1<br>+<br>+loop1:<br>+  %cond = icmp eq i32* %var, null<br>+  %next.load = load i32** %next.ptr<br>+  br i1 %cond, label %loop, label %loop2<br>+<br>+loop2:                                           ; preds = %loop1<br>+  %gep = getelementptr inbounds i32** %next.ptr, i32 1<br>+  store i32* %next.load, i32** undef<br>+  br label %loop<br>+}<br>+<br>+; Verify that DEC+JE are scheduled together.<br>+; CHECK: dec_je<br>+; CHECK: %loop1<br>+; CHECK: dec<br>+; CHECK-NEXT: je<br>+define void @dec_je() {<br>+entry:<br>+  br label %loop<br>+<br>+loop:<br>+  %var = phi i32 [ 0, %entry ], [ %next.var, %loop1 ], [ %var2,<br>%loop2 ]<br>+  %next.ptr = phi i32** [ null, %entry ], [ %next.ptr, %loop1 ], [<br>%gep, %loop2 ]<br>+  br label %loop1<br>+<br>+loop1:<br>+  %var2 = sub i32 %var, 1<br>+  %cond = icmp eq i32 %var2, 0<br>+  %next.load = load i32** %next.ptr<br>+  %next.var = load i32* %next.load<br>+  br i1 %cond, label %loop, label %loop2<br>+<br>+loop2:<br>+  %gep = getelementptr inbounds i32** %next.ptr, i32 1<br>+  store i32* %next.load, i32** undef<br>+  br label %loop<br>+}<br>+<br>+; DEC+JS should *not* be scheduled together.<br>+; CHECK: dec_js<br>+; CHECK: %loop1<br>+; CHECK: dec<br>+; CHECK: mov<br>+; CHECK: js<br>+define void @dec_js() {<br>+entry:<br>+  br label %loop2a<br>+<br>+loop2a:                                           ; preds = %loop1,<br>%body, %entry<br>+  %var = phi i32 [ 0, %entry ], [ %next.var, %loop1 ], [ %var2,<br>%loop2b ]<br>+  %next.ptr = phi i32** [ null, %entry ], [ %next.ptr, %loop1 ], [<br>%gep, %loop2b ]<br>+  br label %loop1<br>+<br>+loop1:                                            ; preds = %loop2a,<br>%loop2b<br>+  %var2 = sub i32 %var, 1<br>+  %cond = icmp slt i32 %var2, 0<br>+  %next.load = load i32** %next.ptr<br>+  %next.var = load i32* %next.load<br>+  br i1 %cond, label %loop2a, label %loop2b<br>+<br>+loop2b:                                           ; preds = %loop1<br>+  %gep = getelementptr inbounds i32** %next.ptr, i32 1<br>+  store i32* %next.load, i32** undef<br>+  br label %loop2a<br>+}<br>+<br>+; Verify that CMP+JB are scheduled together.<br>+; CHECK: cmp_jb<br>+; CHECK: %loop1<br>+; CHECK: cmp<br>+; CHECK-NEXT: jb<br>+define void @cmp_jb(i32 %n) {<br>+entry:<br>+  br label %loop2a<br>+<br>+loop2a:                                           ; preds = %loop1,<br>%body, %entry<br>+  %var = phi i32 [ 0, %entry ], [ %next.var, %loop1 ], [ %var2,<br>%loop2b ]<br>+  %next.ptr = phi i32** [ null, %entry ], [ %next.ptr, %loop1 ], [<br>%gep, %loop2b ]<br>+  br label %loop1<br>+<br>+loop1:                                            ; preds = %loop2a,<br>%loop2b<br>+  %var2 = sub i32 %var, 1<br>+  %cond = icmp ult i32 %var2, %n<br>+  %next.load = load i32** %next.ptr<br>+  %next.var = load i32* %next.load<br>+  br i1 %cond, label %loop2a, label %loop2b<br>+<br>+loop2b:                                           ; preds = %loop1<br>+  %gep = getelementptr inbounds i32** %next.ptr, i32 1<br>+  store i32* %next.load, i32** undef<br>+  br label %loop2a<br>+}<br><br><br>_______________________________________________<br>llvm-commits mailing list<br><a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br><a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br><br></blockquote><br>--<span class="Apple-converted-space"> </span><br>Hal Finkel<br>Assistant Computational Scientist<br>Leadership Computing Facility<br>Argonne National Laboratory</div></blockquote></div><br></body></html>