// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
// RUN: %clang_cc1 -triple thumbv8.1m.main-none-none-eabi -target-feature +mve.fp -mfloat-abi hard -fallow-half-arguments-and-returns -O0 -disable-O0-optnone -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s

#include <arm_mve.h>

// CHECK-LABEL: @test_asrl(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[TMP0:%.*]] = lshr i64 [[VALUE:%.*]], 32
// CHECK-NEXT:    [[TMP1:%.*]] = trunc i64 [[TMP0]] to i32
// CHECK-NEXT:    [[TMP2:%.*]] = trunc i64 [[VALUE]] to i32
// CHECK-NEXT:    [[TMP3:%.*]] = call { i32, i32 } @llvm.arm.mve.asrl(i32 [[TMP2]], i32 [[TMP1]], i32 [[SHIFT:%.*]])
// CHECK-NEXT:    [[TMP4:%.*]] = extractvalue { i32, i32 } [[TMP3]], 1
// CHECK-NEXT:    [[TMP5:%.*]] = zext i32 [[TMP4]] to i64
// CHECK-NEXT:    [[TMP6:%.*]] = shl i64 [[TMP5]], 32
// CHECK-NEXT:    [[TMP7:%.*]] = extractvalue { i32, i32 } [[TMP3]], 0
// CHECK-NEXT:    [[TMP8:%.*]] = zext i32 [[TMP7]] to i64
// CHECK-NEXT:    [[TMP9:%.*]] = or i64 [[TMP6]], [[TMP8]]
// CHECK-NEXT:    ret i64 [[TMP9]]
//
int64_t test_asrl(int64_t value, int32_t shift)
{
    return asrl(value, shift);
}

// CHECK-LABEL: @test_lsll(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[TMP0:%.*]] = lshr i64 [[VALUE:%.*]], 32
// CHECK-NEXT:    [[TMP1:%.*]] = trunc i64 [[TMP0]] to i32
// CHECK-NEXT:    [[TMP2:%.*]] = trunc i64 [[VALUE]] to i32
// CHECK-NEXT:    [[TMP3:%.*]] = call { i32, i32 } @llvm.arm.mve.lsll(i32 [[TMP2]], i32 [[TMP1]], i32 [[SHIFT:%.*]])
// CHECK-NEXT:    [[TMP4:%.*]] = extractvalue { i32, i32 } [[TMP3]], 1
// CHECK-NEXT:    [[TMP5:%.*]] = zext i32 [[TMP4]] to i64
// CHECK-NEXT:    [[TMP6:%.*]] = shl i64 [[TMP5]], 32
// CHECK-NEXT:    [[TMP7:%.*]] = extractvalue { i32, i32 } [[TMP3]], 0
// CHECK-NEXT:    [[TMP8:%.*]] = zext i32 [[TMP7]] to i64
// CHECK-NEXT:    [[TMP9:%.*]] = or i64 [[TMP6]], [[TMP8]]
// CHECK-NEXT:    ret i64 [[TMP9]]
//
uint64_t test_lsll(uint64_t value, int32_t shift)
{
    return lsll(value, shift);
}

// CHECK-LABEL: @test_sqrshr(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[TMP0:%.*]] = call i32 @llvm.arm.mve.sqrshr(i32 [[VALUE:%.*]], i32 [[SHIFT:%.*]])
// CHECK-NEXT:    ret i32 [[TMP0]]
//
int32_t test_sqrshr(int32_t value, int32_t shift)
{
    return sqrshr(value, shift);
}

// CHECK-LABEL: @test_sqrshrl(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[TMP0:%.*]] = lshr i64 [[VALUE:%.*]], 32
// CHECK-NEXT:    [[TMP1:%.*]] = trunc i64 [[TMP0]] to i32
// CHECK-NEXT:    [[TMP2:%.*]] = trunc i64 [[VALUE]] to i32
// CHECK-NEXT:    [[TMP3:%.*]] = call { i32, i32 } @llvm.arm.mve.sqrshrl(i32 [[TMP2]], i32 [[TMP1]], i32 [[SHIFT:%.*]], i32 64)
// CHECK-NEXT:    [[TMP4:%.*]] = extractvalue { i32, i32 } [[TMP3]], 1
// CHECK-NEXT:    [[TMP5:%.*]] = zext i32 [[TMP4]] to i64
// CHECK-NEXT:    [[TMP6:%.*]] = shl i64 [[TMP5]], 32
// CHECK-NEXT:    [[TMP7:%.*]] = extractvalue { i32, i32 } [[TMP3]], 0
// CHECK-NEXT:    [[TMP8:%.*]] = zext i32 [[TMP7]] to i64
// CHECK-NEXT:    [[TMP9:%.*]] = or i64 [[TMP6]], [[TMP8]]
// CHECK-NEXT:    ret i64 [[TMP9]]
//
int64_t test_sqrshrl(int64_t value, int32_t shift)
{
    return sqrshrl(value, shift);
}

// CHECK-LABEL: @test_sqrshrl_sat48(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[TMP0:%.*]] = lshr i64 [[VALUE:%.*]], 32
// CHECK-NEXT:    [[TMP1:%.*]] = trunc i64 [[TMP0]] to i32
// CHECK-NEXT:    [[TMP2:%.*]] = trunc i64 [[VALUE]] to i32
// CHECK-NEXT:    [[TMP3:%.*]] = call { i32, i32 } @llvm.arm.mve.sqrshrl(i32 [[TMP2]], i32 [[TMP1]], i32 [[SHIFT:%.*]], i32 48)
// CHECK-NEXT:    [[TMP4:%.*]] = extractvalue { i32, i32 } [[TMP3]], 1
// CHECK-NEXT:    [[TMP5:%.*]] = zext i32 [[TMP4]] to i64
// CHECK-NEXT:    [[TMP6:%.*]] = shl i64 [[TMP5]], 32
// CHECK-NEXT:    [[TMP7:%.*]] = extractvalue { i32, i32 } [[TMP3]], 0
// CHECK-NEXT:    [[TMP8:%.*]] = zext i32 [[TMP7]] to i64
// CHECK-NEXT:    [[TMP9:%.*]] = or i64 [[TMP6]], [[TMP8]]
// CHECK-NEXT:    ret i64 [[TMP9]]
//
int64_t test_sqrshrl_sat48(int64_t value, int32_t shift)
{
    return sqrshrl_sat48(value, shift);
}

// CHECK-LABEL: @test_sqshl(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[TMP0:%.*]] = call i32 @llvm.arm.mve.sqshl(i32 [[VALUE:%.*]], i32 2)
// CHECK-NEXT:    ret i32 [[TMP0]]
//
int32_t test_sqshl(int32_t value)
{
    return sqshl(value, 2);
}

// CHECK-LABEL: @test_sqshll(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[TMP0:%.*]] = lshr i64 [[VALUE:%.*]], 32
// CHECK-NEXT:    [[TMP1:%.*]] = trunc i64 [[TMP0]] to i32
// CHECK-NEXT:    [[TMP2:%.*]] = trunc i64 [[VALUE]] to i32
// CHECK-NEXT:    [[TMP3:%.*]] = call { i32, i32 } @llvm.arm.mve.sqshll(i32 [[TMP2]], i32 [[TMP1]], i32 17)
// CHECK-NEXT:    [[TMP4:%.*]] = extractvalue { i32, i32 } [[TMP3]], 1
// CHECK-NEXT:    [[TMP5:%.*]] = zext i32 [[TMP4]] to i64
// CHECK-NEXT:    [[TMP6:%.*]] = shl i64 [[TMP5]], 32
// CHECK-NEXT:    [[TMP7:%.*]] = extractvalue { i32, i32 } [[TMP3]], 0
// CHECK-NEXT:    [[TMP8:%.*]] = zext i32 [[TMP7]] to i64
// CHECK-NEXT:    [[TMP9:%.*]] = or i64 [[TMP6]], [[TMP8]]
// CHECK-NEXT:    ret i64 [[TMP9]]
//
int64_t test_sqshll(int64_t value)
{
    return sqshll(value, 17);
}

// CHECK-LABEL: @test_srshr(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[TMP0:%.*]] = call i32 @llvm.arm.mve.srshr(i32 [[VALUE:%.*]], i32 6)
// CHECK-NEXT:    ret i32 [[TMP0]]
//
int32_t test_srshr(int32_t value)
{
    return srshr(value, 6);
}

// CHECK-LABEL: @test_srshrl(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[TMP0:%.*]] = lshr i64 [[VALUE:%.*]], 32
// CHECK-NEXT:    [[TMP1:%.*]] = trunc i64 [[TMP0]] to i32
// CHECK-NEXT:    [[TMP2:%.*]] = trunc i64 [[VALUE]] to i32
// CHECK-NEXT:    [[TMP3:%.*]] = call { i32, i32 } @llvm.arm.mve.srshrl(i32 [[TMP2]], i32 [[TMP1]], i32 26)
// CHECK-NEXT:    [[TMP4:%.*]] = extractvalue { i32, i32 } [[TMP3]], 1
// CHECK-NEXT:    [[TMP5:%.*]] = zext i32 [[TMP4]] to i64
// CHECK-NEXT:    [[TMP6:%.*]] = shl i64 [[TMP5]], 32
// CHECK-NEXT:    [[TMP7:%.*]] = extractvalue { i32, i32 } [[TMP3]], 0
// CHECK-NEXT:    [[TMP8:%.*]] = zext i32 [[TMP7]] to i64
// CHECK-NEXT:    [[TMP9:%.*]] = or i64 [[TMP6]], [[TMP8]]
// CHECK-NEXT:    ret i64 [[TMP9]]
//
int64_t test_srshrl(int64_t value)
{
    return srshrl(value, 26);
}

// CHECK-LABEL: @test_uqrshl(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[TMP0:%.*]] = call i32 @llvm.arm.mve.uqrshl(i32 [[VALUE:%.*]], i32 [[SHIFT:%.*]])
// CHECK-NEXT:    ret i32 [[TMP0]]
//
uint32_t test_uqrshl(uint32_t value, int32_t shift)
{
    return uqrshl(value, shift);
}

// CHECK-LABEL: @test_uqrshll(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[TMP0:%.*]] = lshr i64 [[VALUE:%.*]], 32
// CHECK-NEXT:    [[TMP1:%.*]] = trunc i64 [[TMP0]] to i32
// CHECK-NEXT:    [[TMP2:%.*]] = trunc i64 [[VALUE]] to i32
// CHECK-NEXT:    [[TMP3:%.*]] = call { i32, i32 } @llvm.arm.mve.uqrshll(i32 [[TMP2]], i32 [[TMP1]], i32 [[SHIFT:%.*]], i32 64)
// CHECK-NEXT:    [[TMP4:%.*]] = extractvalue { i32, i32 } [[TMP3]], 1
// CHECK-NEXT:    [[TMP5:%.*]] = zext i32 [[TMP4]] to i64
// CHECK-NEXT:    [[TMP6:%.*]] = shl i64 [[TMP5]], 32
// CHECK-NEXT:    [[TMP7:%.*]] = extractvalue { i32, i32 } [[TMP3]], 0
// CHECK-NEXT:    [[TMP8:%.*]] = zext i32 [[TMP7]] to i64
// CHECK-NEXT:    [[TMP9:%.*]] = or i64 [[TMP6]], [[TMP8]]
// CHECK-NEXT:    ret i64 [[TMP9]]
//
uint64_t test_uqrshll(uint64_t value, int32_t shift)
{
    return uqrshll(value, shift);
}

// CHECK-LABEL: @test_uqrshll_sat48(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[TMP0:%.*]] = lshr i64 [[VALUE:%.*]], 32
// CHECK-NEXT:    [[TMP1:%.*]] = trunc i64 [[TMP0]] to i32
// CHECK-NEXT:    [[TMP2:%.*]] = trunc i64 [[VALUE]] to i32
// CHECK-NEXT:    [[TMP3:%.*]] = call { i32, i32 } @llvm.arm.mve.uqrshll(i32 [[TMP2]], i32 [[TMP1]], i32 [[SHIFT:%.*]], i32 48)
// CHECK-NEXT:    [[TMP4:%.*]] = extractvalue { i32, i32 } [[TMP3]], 1
// CHECK-NEXT:    [[TMP5:%.*]] = zext i32 [[TMP4]] to i64
// CHECK-NEXT:    [[TMP6:%.*]] = shl i64 [[TMP5]], 32
// CHECK-NEXT:    [[TMP7:%.*]] = extractvalue { i32, i32 } [[TMP3]], 0
// CHECK-NEXT:    [[TMP8:%.*]] = zext i32 [[TMP7]] to i64
// CHECK-NEXT:    [[TMP9:%.*]] = or i64 [[TMP6]], [[TMP8]]
// CHECK-NEXT:    ret i64 [[TMP9]]
//
uint64_t test_uqrshll_sat48(uint64_t value, int32_t shift)
{
    return uqrshll_sat48(value, shift);
}

// CHECK-LABEL: @test_uqshl(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[TMP0:%.*]] = call i32 @llvm.arm.mve.uqshl(i32 [[VALUE:%.*]], i32 21)
// CHECK-NEXT:    ret i32 [[TMP0]]
//
uint32_t test_uqshl(uint32_t value)
{
    return uqshl(value, 21);
}

// CHECK-LABEL: @test_uqshll(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[TMP0:%.*]] = lshr i64 [[VALUE:%.*]], 32
// CHECK-NEXT:    [[TMP1:%.*]] = trunc i64 [[TMP0]] to i32
// CHECK-NEXT:    [[TMP2:%.*]] = trunc i64 [[VALUE]] to i32
// CHECK-NEXT:    [[TMP3:%.*]] = call { i32, i32 } @llvm.arm.mve.uqshll(i32 [[TMP2]], i32 [[TMP1]], i32 16)
// CHECK-NEXT:    [[TMP4:%.*]] = extractvalue { i32, i32 } [[TMP3]], 1
// CHECK-NEXT:    [[TMP5:%.*]] = zext i32 [[TMP4]] to i64
// CHECK-NEXT:    [[TMP6:%.*]] = shl i64 [[TMP5]], 32
// CHECK-NEXT:    [[TMP7:%.*]] = extractvalue { i32, i32 } [[TMP3]], 0
// CHECK-NEXT:    [[TMP8:%.*]] = zext i32 [[TMP7]] to i64
// CHECK-NEXT:    [[TMP9:%.*]] = or i64 [[TMP6]], [[TMP8]]
// CHECK-NEXT:    ret i64 [[TMP9]]
//
uint64_t test_uqshll(uint64_t value)
{
    return uqshll(value, 16);
}

// CHECK-LABEL: @test_urshr(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[TMP0:%.*]] = call i32 @llvm.arm.mve.urshr(i32 [[VALUE:%.*]], i32 22)
// CHECK-NEXT:    ret i32 [[TMP0]]
//
uint32_t test_urshr(uint32_t value)
{
    return urshr(value, 22);
}

// CHECK-LABEL: @test_urshrl(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[TMP0:%.*]] = lshr i64 [[VALUE:%.*]], 32
// CHECK-NEXT:    [[TMP1:%.*]] = trunc i64 [[TMP0]] to i32
// CHECK-NEXT:    [[TMP2:%.*]] = trunc i64 [[VALUE]] to i32
// CHECK-NEXT:    [[TMP3:%.*]] = call { i32, i32 } @llvm.arm.mve.urshrl(i32 [[TMP2]], i32 [[TMP1]], i32 6)
// CHECK-NEXT:    [[TMP4:%.*]] = extractvalue { i32, i32 } [[TMP3]], 1
// CHECK-NEXT:    [[TMP5:%.*]] = zext i32 [[TMP4]] to i64
// CHECK-NEXT:    [[TMP6:%.*]] = shl i64 [[TMP5]], 32
// CHECK-NEXT:    [[TMP7:%.*]] = extractvalue { i32, i32 } [[TMP3]], 0
// CHECK-NEXT:    [[TMP8:%.*]] = zext i32 [[TMP7]] to i64
// CHECK-NEXT:    [[TMP9:%.*]] = or i64 [[TMP6]], [[TMP8]]
// CHECK-NEXT:    ret i64 [[TMP9]]
//
uint64_t test_urshrl(uint64_t value)
{
    return urshrl(value, 6);
}
