| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 |
| ; Test avoiding the unnecessary spill by marking loads as rematerializable and |
| ; just directly loading from where the argument was originally passed on the |
| ; stack - moving the load down to the remat site. |
| |
| ; RUN: llc < %s -verify-machineinstrs -mtriple=s390x-linux-gnu -O1 | FileCheck %s |
| |
| define void @remat_load( |
| ; CHECK-LABEL: remat_load: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: stmg %r6, %r15, 48(%r15) |
| ; CHECK-NEXT: aghi %r15, -64 |
| ; CHECK-NEXT: std %f8, 56(%r15) # 8-byte Spill |
| ; CHECK-NEXT: std %f9, 48(%r15) # 8-byte Spill |
| ; CHECK-NEXT: std %f10, 40(%r15) # 8-byte Spill |
| ; CHECK-NEXT: std %f11, 32(%r15) # 8-byte Spill |
| ; CHECK-NEXT: std %f12, 24(%r15) # 8-byte Spill |
| ; CHECK-NEXT: std %f13, 16(%r15) # 8-byte Spill |
| ; CHECK-NEXT: std %f14, 8(%r15) # 8-byte Spill |
| ; CHECK-NEXT: std %f15, 0(%r15) # 8-byte Spill |
| ; CHECK-NEXT: lg %r0, 232(%r15) |
| ; CHECK-NEXT: lg %r1, 224(%r15) |
| ; CHECK-NEXT: ld %f0, 280(%r15) |
| ; CHECK-NEXT: le %f1, 276(%r15) |
| ; CHECK-NEXT: le %f2, 268(%r15) |
| ; CHECK-NEXT: lg %r14, 288(%r15) |
| ; CHECK-NEXT: le %f3, 260(%r15) |
| ; CHECK-NEXT: l %r3, 244(%r15) |
| ; CHECK-NEXT: lg %r2, 248(%r15) |
| ; CHECK-NEXT: stc %r1, 0(%r14) |
| ; CHECK-NEXT: sth %r0, 0(%r14) |
| ; CHECK-NEXT: st %r3, 0(%r14) |
| ; CHECK-NEXT: stg %r2, 0(%r14) |
| ; CHECK-NEXT: ste %f3, 0(%r14) |
| ; CHECK-NEXT: ste %f2, 0(%r14) |
| ; CHECK-NEXT: ste %f1, 0(%r14) |
| ; CHECK-NEXT: std %f0, 0(%r14) |
| ; CHECK-NEXT: #APP |
| ; CHECK-NEXT: #NO_APP |
| ; CHECK-NEXT: lg %r0, 224(%r15) |
| ; CHECK-NEXT: stc %r0, 0(%r14) |
| ; CHECK-NEXT: lg %r0, 232(%r15) |
| ; CHECK-NEXT: sth %r0, 0(%r14) |
| ; CHECK-NEXT: l %r0, 244(%r15) |
| ; CHECK-NEXT: st %r0, 0(%r14) |
| ; CHECK-NEXT: lg %r0, 248(%r15) |
| ; CHECK-NEXT: stg %r0, 0(%r14) |
| ; CHECK-NEXT: le %f0, 260(%r15) |
| ; CHECK-NEXT: ste %f0, 0(%r14) |
| ; CHECK-NEXT: le %f0, 268(%r15) |
| ; CHECK-NEXT: ste %f0, 0(%r14) |
| ; CHECK-NEXT: le %f0, 276(%r15) |
| ; CHECK-NEXT: ste %f0, 0(%r14) |
| ; CHECK-NEXT: ld %f0, 280(%r15) |
| ; CHECK-NEXT: std %f0, 0(%r14) |
| ; CHECK-NEXT: ld %f8, 56(%r15) # 8-byte Reload |
| ; CHECK-NEXT: ld %f9, 48(%r15) # 8-byte Reload |
| ; CHECK-NEXT: ld %f10, 40(%r15) # 8-byte Reload |
| ; CHECK-NEXT: ld %f11, 32(%r15) # 8-byte Reload |
| ; CHECK-NEXT: ld %f12, 24(%r15) # 8-byte Reload |
| ; CHECK-NEXT: ld %f13, 16(%r15) # 8-byte Reload |
| ; CHECK-NEXT: ld %f14, 8(%r15) # 8-byte Reload |
| ; CHECK-NEXT: ld %f15, 0(%r15) # 8-byte Reload |
| ; CHECK-NEXT: lmg %r6, %r15, 112(%r15) |
| ; CHECK-NEXT: br %r14 |
| i64 %i0, i64 %i1, i64 %i2, i64 %i3, i64 %i4, ; r2-r6 |
| double %f0, double %f1, double %f2, double %f3, ; f0, f2, f4, f6 |
| i8 signext %stackarg0, |
| i16 zeroext %stackarg1, |
| i32 %stackarg2, |
| i64 %stackarg3, |
| float %stackarg4, |
| float %stackarg5, |
| float %stackarg6, |
| double %stackarg7, |
| ptr %p |
| ) nounwind { |
| entry: |
| ; Add a use of the stack arguments here so that we will have to load them from |
| ; the stack before the inline asm. Otherwise we would be exercising the |
| ; machine scheduler, not rematerialization. |
| store volatile i8 %stackarg0, ptr %p |
| store volatile i16 %stackarg1, ptr %p |
| store volatile i32 %stackarg2, ptr %p |
| store volatile i64 %stackarg3, ptr %p |
| store volatile float %stackarg4, ptr %p |
| store volatile float %stackarg5, ptr %p |
| store volatile float %stackarg6, ptr %p |
| store volatile double %stackarg7, ptr %p |
| ; Clobber registers to force re-loads |
| tail call void asm sideeffect "", "~{r0},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{f0},~{f1},~{f2},~{f3},~{f4},~{f5},~{f6},~{f7},~{f8},~{f9},~{f10},~{f11},~{f12},~{f13},~{f14},~{f15}"() |
| ; Now use them after spilling everything to force rematerialization |
| store volatile i8 %stackarg0, ptr %p |
| store volatile i16 %stackarg1, ptr %p |
| store volatile i32 %stackarg2, ptr %p |
| store volatile i64 %stackarg3, ptr %p |
| store volatile float %stackarg4, ptr %p |
| store volatile float %stackarg5, ptr %p |
| store volatile float %stackarg6, ptr %p |
| store volatile double %stackarg7, ptr %p |
| ret void |
| } |
| |
| @const = external constant i32 |
| ; Remat the load of the constant global. |
| define i32 @constglobal_load() nounwind { |
| ; CHECK-LABEL: constglobal_load: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: stmg %r6, %r15, 48(%r15) |
| ; CHECK-NEXT: #APP |
| ; CHECK-NEXT: #NO_APP |
| ; CHECK-NEXT: lhi %r2, 1 |
| ; CHECK-NEXT: lgrl %r1, const@GOT |
| ; CHECK-NEXT: a %r2, 0(%r1) |
| ; CHECK-NEXT: lmg %r6, %r15, 48(%r15) |
| ; CHECK-NEXT: br %r14 |
| entry: |
| %global = load i32, ptr @const |
| tail call void asm sideeffect "", "~{r0},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15}"() |
| %a = add i32 %global, 1 |
| ret i32 %a |
| } |