[llvm-commits] CVS: llvm/lib/CodeGen/LiveInterval.cpp

Chris Lattner lattner at cs.uiuc.edu
Sun Jul 25 00:11:29 PDT 2004



Changes in directory llvm/lib/CodeGen:

LiveInterval.cpp updated: 1.9 -> 1.10

---
Log message:

This patch makes use of the infrastructure implemented before to safely and
aggressively coallesce live ranges even if they overlap.  Consider this LLVM
code for example:

int %test(int %X) {
        %Y = mul int %X, 1      ;; Codegens to Y = X
        %Z = add int %X, %Y
        ret int %Z
}

The mul is just there to get a copy into the code stream.  This produces
this machine code:

 (0x869e5a8, LLVM BB @0x869b9a0):
        %reg1024 = mov <fi#-2>, 1, %NOREG, 0    ;; "X"
        %reg1025 = mov %reg1024                 ;; "Y"  (subsumed by X)
        %reg1026 = add %reg1024, %reg1025
        %EAX = mov %reg1026
        ret

Note that the life times of reg1024 and reg1025 overlap, even though they
contain the same value.  This results in this machine code:

test:
        mov %EAX, DWORD PTR [%ESP + 4]
        mov %ECX, %EAX
        add %EAX, %ECX
        ret

Another, worse case involves loops and PHI nodes.  Consider this trivial loop:
testcase:

int %test2(int %X) {
entry:
        br label %Loop
Loop:
        %Y = phi int [%X, %entry], [%Z, %Loop]
        %Z = add int %Y, 1
        %cond = seteq int %Z, 100
        br bool %cond, label %Out, label %Loop
Out:
        ret int %Z
}

Because of interactions between the PHI elimination pass and the register
allocator, this got compiled to this code:

test2:
        mov %ECX, DWORD PTR [%ESP + 4]
.LBBtest2_1:
***     mov %EAX, %ECX
        inc %EAX
        cmp %EAX, 100
***     mov %ECX, %EAX
        jne .LBBtest2_1

        ret

Or on powerpc, this code:

_test2:
        mflr r0
        stw r0, 8(r1)
        stwu r1, -60(r1)
.LBB_test2_1:
        addi r2, r3, 1
        cmpwi cr0, r2, 100
***     or r3, r2, r2
        bne cr0, .LBB_test2_1

***     or r3, r2, r2
        lwz r0, 68(r1)
        mtlr r0
        addi r1, r1, 60
        blr 0



With this improvement in place, we now generate this code for these two
testcases, which is what we want:


test:
        mov %EAX, DWORD PTR [%ESP + 4]
        add %EAX, %EAX
        ret 

test2:
        mov %EAX, DWORD PTR [%ESP + 4]
.LBBtest2_1:
        inc %EAX
        cmp %EAX, 100
        jne .LBBtest2_1 # Loop
        ret 

Or on PPC:

_test2:
        mflr r0
        stw r0, 8(r1)
        stwu r1, -60(r1)
.LBB_test2_1:
        addi r3, r3, 1
        cmpwi cr0, r3, 100
        bne cr0, .LBB_test2_1

        lwz r0, 68(r1)
        mtlr r0
        addi r1, r1, 60
        blr 0


Static numbers for spill code loads/stores/reg-reg copies (smaller is better):

em3d:       before: 47/25/26         after: 44/22/24
164.gzip:   before: 433/245/310      after: 403/231/278
175.vpr:    before: 3721/2189/1581   after: 4144/2081/1423
176.gcc:    before: 26195/8866/9235  after: 25942/8082/8275
186.crafty: before: 4295/2587/3079   after: 4119/2519/2916
252.eon:    before: 12754/7585/5803  after: 12508/7425/5643
256.bzip2:  before: 463/226/315      after: 482:241/309


Runtime perf number samples on X86:

gzip: before: 41.09 after: 39.86
bzip2: runtime: before: 56.71s after: 57.07s
gcc: before: 6.16 after: 6.12
eon: before: 2.03s after: 2.00s




---
Diffs of the changes:  (+43 -1)

Index: llvm/lib/CodeGen/LiveInterval.cpp
diff -u llvm/lib/CodeGen/LiveInterval.cpp:1.9 llvm/lib/CodeGen/LiveInterval.cpp:1.10
--- llvm/lib/CodeGen/LiveInterval.cpp:1.9	Sun Jul 25 01:23:01 2004
+++ llvm/lib/CodeGen/LiveInterval.cpp	Sun Jul 25 02:11:19 2004
@@ -60,6 +60,7 @@
   Ranges::const_iterator ie = ranges.end();
   Ranges::const_iterator j = other.ranges.begin();
   Ranges::const_iterator je = other.ranges.end();
+
   if (i->start < j->start) {
     i = std::upper_bound(i, ie, j->start);
     if (i != ranges.begin()) --i;
@@ -92,7 +93,48 @@
 /// or if the destination of the copy is a single assignment value, and it
 /// only overlaps with one value in the source interval.
 bool LiveInterval::joinable(const LiveInterval &other, unsigned CopyIdx) const {
-  return overlaps(other);
+  const LiveRange *SourceLR = other.getLiveRangeContaining(CopyIdx-1);
+  const LiveRange *DestLR = getLiveRangeContaining(CopyIdx);
+  assert(SourceLR && DestLR && "Not joining due to a copy?");
+  unsigned OtherValIdx = SourceLR->ValId;
+  unsigned ThisValIdx = DestLR->ValId;
+
+  Ranges::const_iterator i = ranges.begin();
+  Ranges::const_iterator ie = ranges.end();
+  Ranges::const_iterator j = other.ranges.begin();
+  Ranges::const_iterator je = other.ranges.end();
+
+  if (i->start < j->start) {
+    i = std::upper_bound(i, ie, j->start);
+    if (i != ranges.begin()) --i;
+  } else if (j->start < i->start) {
+    j = std::upper_bound(j, je, i->start);
+    if (j != other.ranges.begin()) --j;
+  }
+
+  while (i != ie && j != je) {
+    if (i->start == j->start) {
+      // If this is not the allowed value merge, we cannot join.
+      if (i->ValId != ThisValIdx || j->ValId != OtherValIdx)
+        return true;
+    } else if (i->start < j->start) {
+      if (i->end > j->start) {
+        if (i->ValId != ThisValIdx || j->ValId != OtherValIdx)
+          return true;
+      }
+    } else {
+      if (j->end > i->start) {
+        if (i->ValId != ThisValIdx || j->ValId != OtherValIdx)
+          return true;
+      }
+    }
+    if (i->end < j->end)
+      ++i;
+    else
+      ++j;
+  }
+
+  return false;
 }
 
 





More information about the llvm-commits mailing list