| ; 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 | |
| } | |