| ; Test loading of 64-bit constants. |
| ; |
| ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s |
| |
| declare void @foo(i64, i64, i64, i64) |
| |
| ; Check 0. |
| define i64 @f1() { |
| ; CHECK-LABEL: f1: |
| ; CHECK: lghi %r2, 0 |
| ; CHECK-NEXT: br %r14 |
| ret i64 0 |
| } |
| |
| ; Check the high end of the LGHI range. |
| define i64 @f2() { |
| ; CHECK-LABEL: f2: |
| ; CHECK: lghi %r2, 32767 |
| ; CHECK-NEXT: br %r14 |
| ret i64 32767 |
| } |
| |
| ; Check the next value up, which must use LLILL instead. |
| define i64 @f3() { |
| ; CHECK-LABEL: f3: |
| ; CHECK: llill %r2, 32768 |
| ; CHECK-NEXT: br %r14 |
| ret i64 32768 |
| } |
| |
| ; Check the high end of the LLILL range. |
| define i64 @f4() { |
| ; CHECK-LABEL: f4: |
| ; CHECK: llill %r2, 65535 |
| ; CHECK-NEXT: br %r14 |
| ret i64 65535 |
| } |
| |
| ; Check the first useful LLILH value, which is the next one up. |
| define i64 @f5() { |
| ; CHECK-LABEL: f5: |
| ; CHECK: llilh %r2, 1 |
| ; CHECK-NEXT: br %r14 |
| ret i64 65536 |
| } |
| |
| ; Check the first useful LGFI value, which is the next one up again. |
| define i64 @f6() { |
| ; CHECK-LABEL: f6: |
| ; CHECK: lgfi %r2, 65537 |
| ; CHECK-NEXT: br %r14 |
| ret i64 65537 |
| } |
| |
| ; Check the high end of the LGFI range. |
| define i64 @f7() { |
| ; CHECK-LABEL: f7: |
| ; CHECK: lgfi %r2, 2147483647 |
| ; CHECK-NEXT: br %r14 |
| ret i64 2147483647 |
| } |
| |
| ; Check the next value up, which should use LLILH instead. |
| define i64 @f8() { |
| ; CHECK-LABEL: f8: |
| ; CHECK: llilh %r2, 32768 |
| ; CHECK-NEXT: br %r14 |
| ret i64 2147483648 |
| } |
| |
| ; Check the next value up again, which should use LLILF. |
| define i64 @f9() { |
| ; CHECK-LABEL: f9: |
| ; CHECK: llilf %r2, 2147483649 |
| ; CHECK-NEXT: br %r14 |
| ret i64 2147483649 |
| } |
| |
| ; Check the high end of the LLILH range. |
| define i64 @f10() { |
| ; CHECK-LABEL: f10: |
| ; CHECK: llilh %r2, 65535 |
| ; CHECK-NEXT: br %r14 |
| ret i64 4294901760 |
| } |
| |
| ; Check the next value up, which must use LLILF. |
| define i64 @f11() { |
| ; CHECK-LABEL: f11: |
| ; CHECK: llilf %r2, 4294901761 |
| ; CHECK-NEXT: br %r14 |
| ret i64 4294901761 |
| } |
| |
| ; Check the high end of the LLILF range. |
| define i64 @f12() { |
| ; CHECK-LABEL: f12: |
| ; CHECK: llilf %r2, 4294967295 |
| ; CHECK-NEXT: br %r14 |
| ret i64 4294967295 |
| } |
| |
| ; Check the lowest useful LLIHL value, which is the next one up. |
| define i64 @f13() { |
| ; CHECK-LABEL: f13: |
| ; CHECK: llihl %r2, 1 |
| ; CHECK-NEXT: br %r14 |
| ret i64 4294967296 |
| } |
| |
| ; Check the next value up, which must use a combination of two instructions. |
| define i64 @f14() { |
| ; CHECK-LABEL: f14: |
| ; CHECK: llihl %r2, 1 |
| ; CHECK-NEXT: oill %r2, 1 |
| ; CHECK-NEXT: br %r14 |
| ret i64 4294967297 |
| } |
| |
| ; Check the high end of the OILL range. |
| define i64 @f15() { |
| ; CHECK-LABEL: f15: |
| ; CHECK: llihl %r2, 1 |
| ; CHECK-NEXT: oill %r2, 65535 |
| ; CHECK-NEXT: br %r14 |
| ret i64 4295032831 |
| } |
| |
| ; Check the next value up, which should use OILH instead. |
| define i64 @f16() { |
| ; CHECK-LABEL: f16: |
| ; CHECK: llihl %r2, 1 |
| ; CHECK-NEXT: oilh %r2, 1 |
| ; CHECK-NEXT: br %r14 |
| ret i64 4295032832 |
| } |
| |
| ; Check the next value up again, which should use OILF. |
| define i64 @f17() { |
| ; CHECK-LABEL: f17: |
| ; CHECK: llihl %r2, 1 |
| ; CHECK-NEXT: oilf %r2, 65537 |
| ; CHECK-NEXT: br %r14 |
| ret i64 4295032833 |
| } |
| |
| ; Check the high end of the OILH range. |
| define i64 @f18() { |
| ; CHECK-LABEL: f18: |
| ; CHECK: llihl %r2, 1 |
| ; CHECK-NEXT: oilh %r2, 65535 |
| ; CHECK-NEXT: br %r14 |
| ret i64 8589869056 |
| } |
| |
| ; Check the high end of the OILF range. |
| define i64 @f19() { |
| ; CHECK-LABEL: f19: |
| ; CHECK: llihl %r2, 1 |
| ; CHECK-NEXT: oilf %r2, 4294967295 |
| ; CHECK-NEXT: br %r14 |
| ret i64 8589934591 |
| } |
| |
| ; Check the high end of the LLIHL range. |
| define i64 @f20() { |
| ; CHECK-LABEL: f20: |
| ; CHECK: llihl %r2, 65535 |
| ; CHECK-NEXT: br %r14 |
| ret i64 281470681743360 |
| } |
| |
| ; Check the lowest useful LLIHH value, which is 1<<32 greater than the above. |
| define i64 @f21() { |
| ; CHECK-LABEL: f21: |
| ; CHECK: llihh %r2, 1 |
| ; CHECK-NEXT: br %r14 |
| ret i64 281474976710656 |
| } |
| |
| ; Check the lowest useful LLIHF value, which is 1<<32 greater again. |
| define i64 @f22() { |
| ; CHECK-LABEL: f22: |
| ; CHECK: llihf %r2, 65537 |
| ; CHECK-NEXT: br %r14 |
| ret i64 281479271677952 |
| } |
| |
| ; Check the highest end of the LLIHH range. |
| define i64 @f23() { |
| ; CHECK-LABEL: f23: |
| ; CHECK: llihh %r2, 65535 |
| ; CHECK-NEXT: br %r14 |
| ret i64 -281474976710656 |
| } |
| |
| ; Check the next value up, which must use OILL too. |
| define i64 @f24() { |
| ; CHECK-LABEL: f24: |
| ; CHECK: llihh %r2, 65535 |
| ; CHECK-NEXT: oill %r2, 1 |
| ; CHECK-NEXT: br %r14 |
| ret i64 -281474976710655 |
| } |
| |
| ; Check the high end of the LLIHF range. |
| define i64 @f25() { |
| ; CHECK-LABEL: f25: |
| ; CHECK: llihf %r2, 4294967295 |
| ; CHECK-NEXT: br %r14 |
| ret i64 -4294967296 |
| } |
| |
| ; Check -1. |
| define i64 @f26() { |
| ; CHECK-LABEL: f26: |
| ; CHECK: lghi %r2, -1 |
| ; CHECK-NEXT: br %r14 |
| ret i64 -1 |
| } |
| |
| ; Check the low end of the LGHI range. |
| define i64 @f27() { |
| ; CHECK-LABEL: f27: |
| ; CHECK: lghi %r2, -32768 |
| ; CHECK-NEXT: br %r14 |
| ret i64 -32768 |
| } |
| |
| ; Check the next value down, which must use LGFI instead. |
| define i64 @f28() { |
| ; CHECK-LABEL: f28: |
| ; CHECK: lgfi %r2, -32769 |
| ; CHECK-NEXT: br %r14 |
| ret i64 -32769 |
| } |
| |
| ; Check the low end of the LGFI range. |
| define i64 @f29() { |
| ; CHECK-LABEL: f29: |
| ; CHECK: lgfi %r2, -2147483648 |
| ; CHECK-NEXT: br %r14 |
| ret i64 -2147483648 |
| } |
| |
| ; Check the next value down, which needs a two-instruction sequence. |
| define i64 @f30() { |
| ; CHECK-LABEL: f30: |
| ; CHECK: llihf %r2, 4294967295 |
| ; CHECK-NEXT: oilf %r2, 2147483647 |
| ; CHECK-NEXT: br %r14 |
| ret i64 -2147483649 |
| } |
| |
| ; Check that constant loads are rematerialized. |
| define i64 @f31() { |
| ; CHECK-LABEL: f31: |
| ; CHECK-DAG: lghi %r2, 42 |
| ; CHECK-DAG: lgfi %r3, 65537 |
| ; CHECK-DAG: llilf %r4, 2147483649 |
| ; CHECK-DAG: llihf %r5, 65537 |
| ; CHECK: brasl %r14, foo@PLT |
| ; CHECK-DAG: llill %r2, 32768 |
| ; CHECK-DAG: llilh %r3, 1 |
| ; CHECK-DAG: llihl %r4, 1 |
| ; CHECK-DAG: llihh %r5, 1 |
| ; CHECK: brasl %r14, foo@PLT |
| ; CHECK-DAG: lghi %r2, 42 |
| ; CHECK-DAG: lgfi %r3, 65537 |
| ; CHECK-DAG: llilf %r4, 2147483649 |
| ; CHECK-DAG: llihf %r5, 65537 |
| ; CHECK: brasl %r14, foo@PLT |
| ; CHECK-DAG: llill %r2, 32768 |
| ; CHECK-DAG: llilh %r3, 1 |
| ; CHECK-DAG: llihl %r4, 1 |
| ; CHECK-DAG: llihh %r5, 1 |
| ; CHECK: brasl %r14, foo@PLT |
| ; CHECK: lghi %r2, 42 |
| ; CHECK: br %r14 |
| call void @foo(i64 42, i64 65537, i64 2147483649, i64 281479271677952) |
| call void @foo(i64 32768, i64 65536, i64 4294967296, i64 281474976710656) |
| call void @foo(i64 42, i64 65537, i64 2147483649, i64 281479271677952) |
| call void @foo(i64 32768, i64 65536, i64 4294967296, i64 281474976710656) |
| ret i64 42 |
| } |
| |
| ; Verify that we do not crash on OR with two constant inputs |
| ; (this was PR34859). |
| define i64 @f32(i64 *%ptr) { |
| ; CHECK-LABEL: f32: |
| ; CHECK: llihf %r1, 918324340 |
| ; CHECK: oilf %r1, 1806197964 |
| ; CHECK: la %r0, 1(%r1) |
| store i64 -1, i64* %ptr, align 8 |
| %1 = load i64, i64* %ptr, align 8 |
| %2 = icmp ne i64 %1, 0 |
| %3 = zext i1 %2 to i64 |
| %4 = or i64 %3, 3944173009226982604 |
| store i64 %4, i64* %ptr, align 8 |
| ret i64 3944173009226982604 |
| } |
| |