| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 |
| ; RUN: llc -verify-machineinstrs -o - %s -mtriple=arm64-apple-ios7.0 | FileCheck %s --check-prefixes=CHECK,CHECK-SD |
| ; RUN: llc -verify-machineinstrs -o - %s -mtriple=arm64-apple-ios7.0 -global-isel | FileCheck %s --check-prefixes=CHECK,CHECK-GI |
| |
| define i32 @test_madd32(i32 %val0, i32 %val1, i32 %val2) { |
| ; CHECK-LABEL: test_madd32: |
| ; CHECK: ; %bb.0: |
| ; CHECK-NEXT: madd w0, w1, w2, w0 |
| ; CHECK-NEXT: ret |
| %mid = mul i32 %val1, %val2 |
| %res = add i32 %val0, %mid |
| ret i32 %res |
| } |
| |
| define i64 @test_madd64(i64 %val0, i64 %val1, i64 %val2) { |
| ; CHECK-LABEL: test_madd64: |
| ; CHECK: ; %bb.0: |
| ; CHECK-NEXT: madd x0, x1, x2, x0 |
| ; CHECK-NEXT: ret |
| %mid = mul i64 %val1, %val2 |
| %res = add i64 %val0, %mid |
| ret i64 %res |
| } |
| |
| define i32 @test_msub32(i32 %val0, i32 %val1, i32 %val2) { |
| ; CHECK-LABEL: test_msub32: |
| ; CHECK: ; %bb.0: |
| ; CHECK-NEXT: msub w0, w1, w2, w0 |
| ; CHECK-NEXT: ret |
| %mid = mul i32 %val1, %val2 |
| %res = sub i32 %val0, %mid |
| ret i32 %res |
| } |
| |
| define i64 @test_msub64(i64 %val0, i64 %val1, i64 %val2) { |
| ; CHECK-LABEL: test_msub64: |
| ; CHECK: ; %bb.0: |
| ; CHECK-NEXT: msub x0, x1, x2, x0 |
| ; CHECK-NEXT: ret |
| %mid = mul i64 %val1, %val2 |
| %res = sub i64 %val0, %mid |
| ret i64 %res |
| } |
| |
| define i64 @test_smaddl(i64 %acc, i32 %val1, i32 %val2) { |
| ; CHECK-LABEL: test_smaddl: |
| ; CHECK: ; %bb.0: |
| ; CHECK-NEXT: smaddl x0, w1, w2, x0 |
| ; CHECK-NEXT: ret |
| %ext1 = sext i32 %val1 to i64 |
| %ext2 = sext i32 %val2 to i64 |
| %prod = mul i64 %ext1, %ext2 |
| %res = add i64 %acc, %prod |
| ret i64 %res |
| } |
| |
| define i64 @test_smsubl(i64 %acc, i32 %val1, i32 %val2) { |
| ; CHECK-LABEL: test_smsubl: |
| ; CHECK: ; %bb.0: |
| ; CHECK-NEXT: smsubl x0, w1, w2, x0 |
| ; CHECK-NEXT: ret |
| %ext1 = sext i32 %val1 to i64 |
| %ext2 = sext i32 %val2 to i64 |
| %prod = mul i64 %ext1, %ext2 |
| %res = sub i64 %acc, %prod |
| ret i64 %res |
| } |
| |
| define i64 @test_umaddl(i64 %acc, i32 %val1, i32 %val2) { |
| ; CHECK-LABEL: test_umaddl: |
| ; CHECK: ; %bb.0: |
| ; CHECK-NEXT: umaddl x0, w1, w2, x0 |
| ; CHECK-NEXT: ret |
| %ext1 = zext i32 %val1 to i64 |
| %ext2 = zext i32 %val2 to i64 |
| %prod = mul i64 %ext1, %ext2 |
| %res = add i64 %acc, %prod |
| ret i64 %res |
| } |
| |
| define i64 @test_umsubl(i64 %acc, i32 %val1, i32 %val2) { |
| ; CHECK-LABEL: test_umsubl: |
| ; CHECK: ; %bb.0: |
| ; CHECK-NEXT: umsubl x0, w1, w2, x0 |
| ; CHECK-NEXT: ret |
| %ext1 = zext i32 %val1 to i64 |
| %ext2 = zext i32 %val2 to i64 |
| %prod = mul i64 %ext1, %ext2 |
| %res = sub i64 %acc, %prod |
| ret i64 %res |
| } |
| |
| define i64 @test_smulh(i64 %lhs, i64 %rhs) { |
| ; CHECK-SD-LABEL: test_smulh: |
| ; CHECK-SD: ; %bb.0: |
| ; CHECK-SD-NEXT: smulh x0, x0, x1 |
| ; CHECK-SD-NEXT: ret |
| ; |
| ; CHECK-GI-LABEL: test_smulh: |
| ; CHECK-GI: ; %bb.0: |
| ; CHECK-GI-NEXT: asr x8, x1, #63 |
| ; CHECK-GI-NEXT: asr x9, x0, #63 |
| ; CHECK-GI-NEXT: umulh x10, x0, x1 |
| ; CHECK-GI-NEXT: mul x8, x0, x8 |
| ; CHECK-GI-NEXT: madd x8, x9, x1, x8 |
| ; CHECK-GI-NEXT: add x0, x8, x10 |
| ; CHECK-GI-NEXT: ret |
| %ext1 = sext i64 %lhs to i128 |
| %ext2 = sext i64 %rhs to i128 |
| %res = mul i128 %ext1, %ext2 |
| %high = lshr i128 %res, 64 |
| %val = trunc i128 %high to i64 |
| ret i64 %val |
| } |
| |
| define i64 @test_umulh(i64 %lhs, i64 %rhs) { |
| ; CHECK-LABEL: test_umulh: |
| ; CHECK: ; %bb.0: |
| ; CHECK-NEXT: umulh x0, x0, x1 |
| ; CHECK-NEXT: ret |
| %ext1 = zext i64 %lhs to i128 |
| %ext2 = zext i64 %rhs to i128 |
| %res = mul i128 %ext1, %ext2 |
| %high = lshr i128 %res, 64 |
| %val = trunc i128 %high to i64 |
| ret i64 %val |
| } |
| |
| define i32 @test_mul32(i32 %lhs, i32 %rhs) { |
| ; CHECK-LABEL: test_mul32: |
| ; CHECK: ; %bb.0: |
| ; CHECK-NEXT: mul w0, w0, w1 |
| ; CHECK-NEXT: ret |
| %res = mul i32 %lhs, %rhs |
| ret i32 %res |
| } |
| |
| define i64 @test_mul64(i64 %lhs, i64 %rhs) { |
| ; CHECK-LABEL: test_mul64: |
| ; CHECK: ; %bb.0: |
| ; CHECK-NEXT: mul x0, x0, x1 |
| ; CHECK-NEXT: ret |
| %res = mul i64 %lhs, %rhs |
| ret i64 %res |
| } |
| |
| define i32 @test_mneg32(i32 %lhs, i32 %rhs) { |
| ; CHECK-LABEL: test_mneg32: |
| ; CHECK: ; %bb.0: |
| ; CHECK-NEXT: mneg w0, w0, w1 |
| ; CHECK-NEXT: ret |
| %prod = mul i32 %lhs, %rhs |
| %res = sub i32 0, %prod |
| ret i32 %res |
| } |
| |
| define i64 @test_mneg64(i64 %lhs, i64 %rhs) { |
| ; CHECK-LABEL: test_mneg64: |
| ; CHECK: ; %bb.0: |
| ; CHECK-NEXT: mneg x0, x0, x1 |
| ; CHECK-NEXT: ret |
| %prod = mul i64 %lhs, %rhs |
| %res = sub i64 0, %prod |
| ret i64 %res |
| } |
| |
| define i64 @test_smull(i32 %lhs, i32 %rhs) { |
| ; CHECK-LABEL: test_smull: |
| ; CHECK: ; %bb.0: |
| ; CHECK-NEXT: smull x0, w0, w1 |
| ; CHECK-NEXT: ret |
| %ext1 = sext i32 %lhs to i64 |
| %ext2 = sext i32 %rhs to i64 |
| %res = mul i64 %ext1, %ext2 |
| ret i64 %res |
| } |
| |
| define i64 @test_umull(i32 %lhs, i32 %rhs) { |
| ; CHECK-LABEL: test_umull: |
| ; CHECK: ; %bb.0: |
| ; CHECK-NEXT: umull x0, w0, w1 |
| ; CHECK-NEXT: ret |
| %ext1 = zext i32 %lhs to i64 |
| %ext2 = zext i32 %rhs to i64 |
| %res = mul i64 %ext1, %ext2 |
| ret i64 %res |
| } |
| |
| define i64 @test_smnegl(i32 %lhs, i32 %rhs) { |
| ; CHECK-LABEL: test_smnegl: |
| ; CHECK: ; %bb.0: |
| ; CHECK-NEXT: smnegl x0, w0, w1 |
| ; CHECK-NEXT: ret |
| %ext1 = sext i32 %lhs to i64 |
| %ext2 = sext i32 %rhs to i64 |
| %prod = mul i64 %ext1, %ext2 |
| %res = sub i64 0, %prod |
| ret i64 %res |
| } |
| |
| define i64 @test_umnegl(i32 %lhs, i32 %rhs) { |
| ; CHECK-LABEL: test_umnegl: |
| ; CHECK: ; %bb.0: |
| ; CHECK-NEXT: umnegl x0, w0, w1 |
| ; CHECK-NEXT: ret |
| %ext1 = zext i32 %lhs to i64 |
| %ext2 = zext i32 %rhs to i64 |
| %prod = mul i64 %ext1, %ext2 |
| %res = sub i64 0, %prod |
| ret i64 %res |
| } |
| |
| @a = common global i32 0, align 4 |
| @b = common global i32 0, align 4 |
| @c = common global i32 0, align 4 |
| |
| define void @test_mneg(){ |
| ; CHECK-LABEL: test_mneg: |
| ; CHECK: ; %bb.0: |
| ; CHECK-NEXT: Lloh0: |
| ; CHECK-NEXT: adrp x8, _a@GOTPAGE |
| ; CHECK-NEXT: Lloh1: |
| ; CHECK-NEXT: adrp x9, _b@GOTPAGE |
| ; CHECK-NEXT: Lloh2: |
| ; CHECK-NEXT: ldr x8, [x8, _a@GOTPAGEOFF] |
| ; CHECK-NEXT: Lloh3: |
| ; CHECK-NEXT: ldr x9, [x9, _b@GOTPAGEOFF] |
| ; CHECK-NEXT: Lloh4: |
| ; CHECK-NEXT: ldr w8, [x8] |
| ; CHECK-NEXT: Lloh5: |
| ; CHECK-NEXT: ldr w9, [x9] |
| ; CHECK-NEXT: mneg w8, w8, w9 |
| ; CHECK-NEXT: Lloh6: |
| ; CHECK-NEXT: adrp x9, _c@GOTPAGE |
| ; CHECK-NEXT: Lloh7: |
| ; CHECK-NEXT: ldr x9, [x9, _c@GOTPAGEOFF] |
| ; CHECK-NEXT: Lloh8: |
| ; CHECK-NEXT: str w8, [x9] |
| ; CHECK-NEXT: ret |
| ; CHECK-NEXT: .loh AdrpLdrGotStr Lloh6, Lloh7, Lloh8 |
| ; CHECK-NEXT: .loh AdrpLdrGotLdr Lloh1, Lloh3, Lloh5 |
| ; CHECK-NEXT: .loh AdrpLdrGotLdr Lloh0, Lloh2, Lloh4 |
| %1 = load i32, ptr @a, align 4 |
| %2 = load i32, ptr @b, align 4 |
| %3 = sub i32 0, %1 |
| %4 = mul i32 %2, %3 |
| store i32 %4, ptr @c, align 4 |
| ret void |
| } |