// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-globals --include-generated-funcs
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +ls64 -target-feature +fullfp16 -S -emit-llvm -o - %s | FileCheck %s
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature -fmv -S -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK-NOFMV

int __attribute__((target_version("rng+flagm+fp16fml"))) fmv(void) { return 1; }
int __attribute__((target_version("flagm2+sme-i16i64"))) fmv(void) { return 2; }
int __attribute__((target_version("lse+sha2"))) fmv(void) { return 3; }
int __attribute__((target_version("dotprod+ls64_accdata"))) fmv(void) { return 4; }
int __attribute__((target_version("fp16fml+memtag"))) fmv(void) { return 5; }
int __attribute__((target_version("fp+aes"))) fmv(void) { return 6; }
int __attribute__((target_version("crc+ls64_v"))) fmv(void) { return 7; }
int __attribute__((target_version("bti"))) fmv(void) { return 8; }
int __attribute__((target_version("sme2"))) fmv(void) { return 9; }
int __attribute__((target_version("default"))) fmv(void) { return 0; }
int __attribute__((target_version("ls64+simd"))) fmv_one(void) { return 1; }
int __attribute__((target_version("dpb"))) fmv_one(void) { return 2; }
int __attribute__((target_version("default"))) fmv_one(void) { return 0; }
int __attribute__((target_version("fp"))) fmv_two(void) { return 1; }
int __attribute__((target_version("simd"))) fmv_two(void) { return 2; }
int __attribute__((target_version("dgh"))) fmv_two(void) { return 3; }
int __attribute__((target_version("fp16+simd"))) fmv_two(void) { return 4; }
int __attribute__((target_version("default"))) fmv_two(void) { return 0; }
int foo() {
  return fmv()+fmv_one()+fmv_two();
}

inline int __attribute__((target_version("sha1+pmull+f64mm"))) fmv_inline(void) { return 1; }
inline int __attribute__((target_version("fp16+fcma+sme+ fp16 "))) fmv_inline(void) { return 2; }
inline int __attribute__((target_version("sha3+i8mm+f32mm"))) fmv_inline(void) { return 12; }
inline int __attribute__((target_version("dit+sve-ebf16"))) fmv_inline(void) { return 8; }
inline int __attribute__((target_version("dpb+rcpc2 "))) fmv_inline(void) { return 6; }
inline int __attribute__((target_version(" dpb2 + jscvt"))) fmv_inline(void) { return 7; }
inline int __attribute__((target_version("rcpc+frintts"))) fmv_inline(void) { return 3; }
inline int __attribute__((target_version("sve+sve-bf16"))) fmv_inline(void) { return 4; }
inline int __attribute__((target_version("sve2-aes+sve2-sha3"))) fmv_inline(void) { return 5; }
inline int __attribute__((target_version("sve2+sve2-pmull128+sve2-bitperm"))) fmv_inline(void) { return 9; }
inline int __attribute__((target_version("sve2-sm4+memtag2"))) fmv_inline(void) { return 10; }
inline int __attribute__((target_version("memtag3"))) fmv_inline(void) { return 11; }
inline int __attribute__((target_version("default"))) fmv_inline(void) { return 3; }

__attribute__((target_version("ls64"))) int fmv_e(void);
int fmv_e(void) { return 20; }

static __attribute__((target_version("sb"))) inline int fmv_d(void);
static __attribute__((target_version("default"))) inline int fmv_d(void);

int __attribute__((target_version("default"))) fmv_default(void) { return 111; }
int fmv_default(void);

void fmv_c(void);
void __attribute__((target_version("ssbs"))) fmv_c(void){};
void __attribute__((target_version("default"))) fmv_c(void){};

int goo() {
  fmv_inline();
  fmv_e();
  fmv_d();
  fmv_c();
  return fmv_default();
}
static inline int __attribute__((target_version("sb"))) fmv_d(void) { return 0; }
static inline int __attribute__((target_version(" default "))) fmv_d(void) { return 1; }

static void func(void) {}
inline __attribute__((target_version("default"))) void recb(void) { func(); }
inline __attribute__((target_version("default"))) void reca(void) { recb(); }
void recur(void) { reca(); }

int __attribute__((target_version("default"))) main(void) {
  recur();
  return goo();
}

typedef int (*Fptr)();
void f(Fptr);
int hoo(void) {
  f(fmv);
  Fptr fp1 = &fmv;
  Fptr fp2 = fmv;
  return fp1() + fp2();
}

// CHECK: @__aarch64_cpu_features = external dso_local global { i64 }
// CHECK: @fmv.ifunc = weak_odr ifunc i32 (), ptr @fmv.resolver
// CHECK: @fmv_one.ifunc = weak_odr ifunc i32 (), ptr @fmv_one.resolver
// CHECK: @fmv_two.ifunc = weak_odr ifunc i32 (), ptr @fmv_two.resolver
// CHECK: @fmv_inline.ifunc = weak_odr ifunc i32 (), ptr @fmv_inline.resolver
// CHECK: @fmv_e.ifunc = weak_odr ifunc i32 (), ptr @fmv_e.resolver
// CHECK: @fmv_d.ifunc = internal ifunc i32 (), ptr @fmv_d.resolver
// CHECK: @fmv_c.ifunc = weak_odr ifunc void (), ptr @fmv_c.resolver

// CHECK-LABEL: @fmv._MrngMflagmMfp16fml(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    ret i32 1
// CHECK-LABEL: @fmv._Mflagm2Msme-i16i64(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    ret i32 2
// CHECK-LABEL: @fmv._MlseMsha2(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    ret i32 3
// CHECK-LABEL: @fmv._MdotprodMls64_accdata(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    ret i32 4
// CHECK-LABEL: @fmv._Mfp16fmlMmemtag(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    ret i32 5
// CHECK-LABEL: @fmv._MfpMaes(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    ret i32 6
// CHECK-LABEL: @fmv._McrcMls64_v(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    ret i32 7
// CHECK-LABEL: @fmv._Mbti(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    ret i32 8
// CHECK-LABEL: @fmv._Msme2(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    ret i32 9
// CHECK-LABEL: @fmv(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    ret i32 0
// CHECK-LABEL: @fmv_one._Mls64Msimd(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    ret i32 1
// CHECK-LABEL: @fmv_one._Mdpb(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    ret i32 2
// CHECK-LABEL: @fmv_one(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    ret i32 0
// CHECK-LABEL: @fmv_two._Mfp(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    ret i32 1
// CHECK-LABEL: @fmv_two._Msimd(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    ret i32 2
// CHECK-LABEL: @fmv_two._Mdgh(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    ret i32 3
// CHECK-LABEL: @fmv_two._Mfp16Msimd(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    ret i32 4
// CHECK-LABEL: @fmv_two(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    ret i32 0
// CHECK-LABEL: @foo(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[CALL:%.*]] = call i32 @fmv.ifunc()
// CHECK-NEXT:    [[CALL1:%.*]] = call i32 @fmv_one.ifunc()
// CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[CALL]], [[CALL1]]
// CHECK-NEXT:    [[CALL2:%.*]] = call i32 @fmv_two.ifunc()
// CHECK-NEXT:    [[ADD3:%.*]] = add nsw i32 [[ADD]], [[CALL2]]
// CHECK-NEXT:    ret i32 [[ADD3]]
// CHECK-LABEL: @fmv.resolver(
// CHECK-NEXT:  resolver_entry:
// CHECK-NEXT:    call void @init_cpu_features_resolver()
// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[TMP0]], 11
// CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 11
// CHECK-NEXT:    [[TMP3:%.*]] = and i1 true, [[TMP2]]
// CHECK-NEXT:    br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
// CHECK:       resolver_return:
// CHECK-NEXT:    ret ptr @fmv._MrngMflagmMfp16fml
// CHECK:       resolver_else:
// CHECK-NEXT:    [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT:    [[TMP5:%.*]] = and i64 [[TMP4]], 72057594037927940
// CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 72057594037927940
// CHECK-NEXT:    [[TMP7:%.*]] = and i1 true, [[TMP6]]
// CHECK-NEXT:    br i1 [[TMP7]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]]
// CHECK:       resolver_return1:
// CHECK-NEXT:    ret ptr @fmv._Mflagm2Msme-i16i64
// CHECK:       resolver_else2:
// CHECK-NEXT:    [[TMP8:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT:    [[TMP9:%.*]] = and i64 [[TMP8]], 16
// CHECK-NEXT:    [[TMP10:%.*]] = icmp eq i64 [[TMP9]], 16
// CHECK-NEXT:    [[TMP11:%.*]] = and i1 true, [[TMP10]]
// CHECK-NEXT:    br i1 [[TMP11]], label [[RESOLVER_RETURN3:%.*]], label [[RESOLVER_ELSE4:%.*]]
// CHECK:       resolver_return3:
// CHECK-NEXT:    ret ptr @fmv._MdotprodMls64_accdata
// CHECK:       resolver_else4:
// CHECK-NEXT:    [[TMP12:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT:    [[TMP13:%.*]] = and i64 [[TMP12]], 1024
// CHECK-NEXT:    [[TMP14:%.*]] = icmp eq i64 [[TMP13]], 1024
// CHECK-NEXT:    [[TMP15:%.*]] = and i1 true, [[TMP14]]
// CHECK-NEXT:    br i1 [[TMP15]], label [[RESOLVER_RETURN5:%.*]], label [[RESOLVER_ELSE6:%.*]]
// CHECK:       resolver_return5:
// CHECK-NEXT:    ret ptr @fmv._McrcMls64_v
// CHECK:       resolver_else6:
// CHECK-NEXT:    [[TMP16:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT:    [[TMP17:%.*]] = and i64 [[TMP16]], 8796093022216
// CHECK-NEXT:    [[TMP18:%.*]] = icmp eq i64 [[TMP17]], 8796093022216
// CHECK-NEXT:    [[TMP19:%.*]] = and i1 true, [[TMP18]]
// CHECK-NEXT:    br i1 [[TMP19]], label [[RESOLVER_RETURN7:%.*]], label [[RESOLVER_ELSE8:%.*]]
// CHECK:       resolver_return7:
// CHECK-NEXT:    ret ptr @fmv._Mfp16fmlMmemtag
// CHECK:       resolver_else8:
// CHECK-NEXT:    [[TMP20:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT:    [[TMP21:%.*]] = and i64 [[TMP20]], 16384
// CHECK-NEXT:    [[TMP22:%.*]] = icmp eq i64 [[TMP21]], 16384
// CHECK-NEXT:    [[TMP23:%.*]] = and i1 true, [[TMP22]]
// CHECK-NEXT:    br i1 [[TMP23]], label [[RESOLVER_RETURN9:%.*]], label [[RESOLVER_ELSE10:%.*]]
// CHECK:       resolver_return9:
// CHECK-NEXT:    ret ptr @fmv._MfpMaes
// CHECK:       resolver_else10:
// CHECK-NEXT:    [[TMP24:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT:    [[TMP25:%.*]] = and i64 [[TMP24]], 4224
// CHECK-NEXT:    [[TMP26:%.*]] = icmp eq i64 [[TMP25]], 4224
// CHECK-NEXT:    [[TMP27:%.*]] = and i1 true, [[TMP26]]
// CHECK-NEXT:    br i1 [[TMP27]], label [[RESOLVER_RETURN11:%.*]], label [[RESOLVER_ELSE12:%.*]]
// CHECK:       resolver_return11:
// CHECK-NEXT:    ret ptr @fmv._MlseMsha2
// CHECK:       resolver_else12:
// CHECK-NEXT:    [[TMP28:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT:    [[TMP29:%.*]] = and i64 [[TMP28]], 144115188075855872
// CHECK-NEXT:    [[TMP30:%.*]] = icmp eq i64 [[TMP29]], 144115188075855872
// CHECK-NEXT:    [[TMP31:%.*]] = and i1 true, [[TMP30]]
// CHECK-NEXT:    br i1 [[TMP31]], label [[RESOLVER_RETURN13:%.*]], label [[RESOLVER_ELSE14:%.*]]
// CHECK:       resolver_return13:
// CHECK-NEXT:    ret ptr @fmv._Msme2
// CHECK:       resolver_else14:
// CHECK-NEXT:    [[TMP32:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT:    [[TMP33:%.*]] = and i64 [[TMP32]], 1125899906842624
// CHECK-NEXT:    [[TMP34:%.*]] = icmp eq i64 [[TMP33]], 1125899906842624
// CHECK-NEXT:    [[TMP35:%.*]] = and i1 true, [[TMP34]]
// CHECK-NEXT:    br i1 [[TMP35]], label [[RESOLVER_RETURN15:%.*]], label [[RESOLVER_ELSE16:%.*]]
// CHECK:       resolver_return15:
// CHECK-NEXT:    ret ptr @fmv._Mbti
// CHECK:       resolver_else16:
// CHECK-NEXT:    ret ptr @fmv
// CHECK-LABEL: @fmv_one.resolver(
// CHECK-NEXT:  resolver_entry:
// CHECK-NEXT:    ret ptr @fmv_one._Mls64Msimd
// CHECK-LABEL: @fmv_two.resolver(
// CHECK-NEXT:  resolver_entry:
// CHECK-NEXT:    ret ptr @fmv_two._Mfp16Msimd
// CHECK-LABEL: @fmv_e(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    ret i32 20
// CHECK-LABEL: @fmv_default(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    ret i32 111
// CHECK-LABEL: @fmv_c._Mssbs(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    ret void
// CHECK-LABEL: @fmv_c(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    ret void
// CHECK-LABEL: @goo(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[CALL:%.*]] = call i32 @fmv_inline.ifunc()
// CHECK-NEXT:    [[CALL1:%.*]] = call i32 @fmv_e.ifunc()
// CHECK-NEXT:    [[CALL2:%.*]] = call i32 @fmv_d.ifunc()
// CHECK-NEXT:    call void @fmv_c.ifunc()
// CHECK-NEXT:    [[CALL3:%.*]] = call i32 @fmv_default()
// CHECK-NEXT:    ret i32 [[CALL3]]
// CHECK-LABEL: @fmv_inline.resolver(
// CHECK-NEXT:  resolver_entry:
// CHECK-NEXT:    call void @init_cpu_features_resolver()
// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[TMP0]], 4398048608256
// CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 4398048608256
// CHECK-NEXT:    [[TMP3:%.*]] = and i1 true, [[TMP2]]
// CHECK-NEXT:    br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
// CHECK:       resolver_return:
// CHECK-NEXT:    ret ptr @fmv_inline._Mfp16MfcmaMsmeMfp16
// CHECK:       resolver_else:
// CHECK-NEXT:    [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT:    [[TMP5:%.*]] = and i64 [[TMP4]], 893353197568
// CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 893353197568
// CHECK-NEXT:    [[TMP7:%.*]] = and i1 true, [[TMP6]]
// CHECK-NEXT:    br i1 [[TMP7]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]]
// CHECK:       resolver_return1:
// CHECK-NEXT:    ret ptr @fmv_inline._Msve2Msve2-pmull128Msve2-bitperm
// CHECK:       resolver_else2:
// CHECK-NEXT:    [[TMP8:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT:    [[TMP9:%.*]] = and i64 [[TMP8]], 34359773184
// CHECK-NEXT:    [[TMP10:%.*]] = icmp eq i64 [[TMP9]], 34359773184
// CHECK-NEXT:    [[TMP11:%.*]] = and i1 true, [[TMP10]]
// CHECK-NEXT:    br i1 [[TMP11]], label [[RESOLVER_RETURN3:%.*]], label [[RESOLVER_ELSE4:%.*]]
// CHECK:       resolver_return3:
// CHECK-NEXT:    ret ptr @fmv_inline._Msha1MpmullMf64mm
// CHECK:       resolver_else4:
// CHECK-NEXT:    [[TMP12:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT:    [[TMP13:%.*]] = and i64 [[TMP12]], 17246986240
// CHECK-NEXT:    [[TMP14:%.*]] = icmp eq i64 [[TMP13]], 17246986240
// CHECK-NEXT:    [[TMP15:%.*]] = and i1 true, [[TMP14]]
// CHECK-NEXT:    br i1 [[TMP15]], label [[RESOLVER_RETURN5:%.*]], label [[RESOLVER_ELSE6:%.*]]
// CHECK:       resolver_return5:
// CHECK-NEXT:    ret ptr @fmv_inline._Msha3Mi8mmMf32mm
// CHECK:       resolver_else6:
// CHECK-NEXT:    [[TMP16:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT:    [[TMP17:%.*]] = and i64 [[TMP16]], 19791209299968
// CHECK-NEXT:    [[TMP18:%.*]] = icmp eq i64 [[TMP17]], 19791209299968
// CHECK-NEXT:    [[TMP19:%.*]] = and i1 true, [[TMP18]]
// CHECK-NEXT:    br i1 [[TMP19]], label [[RESOLVER_RETURN7:%.*]], label [[RESOLVER_ELSE8:%.*]]
// CHECK:       resolver_return7:
// CHECK-NEXT:    ret ptr @fmv_inline._Msve2-sm4Mmemtag2
// CHECK:       resolver_else8:
// CHECK-NEXT:    [[TMP20:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT:    [[TMP21:%.*]] = and i64 [[TMP20]], 1236950581248
// CHECK-NEXT:    [[TMP22:%.*]] = icmp eq i64 [[TMP21]], 1236950581248
// CHECK-NEXT:    [[TMP23:%.*]] = and i1 true, [[TMP22]]
// CHECK-NEXT:    br i1 [[TMP23]], label [[RESOLVER_RETURN9:%.*]], label [[RESOLVER_ELSE10:%.*]]
// CHECK:       resolver_return9:
// CHECK-NEXT:    ret ptr @fmv_inline._Msve2-aesMsve2-sha3
// CHECK:       resolver_else10:
// CHECK-NEXT:    [[TMP24:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT:    [[TMP25:%.*]] = and i64 [[TMP24]], 4295098368
// CHECK-NEXT:    [[TMP26:%.*]] = icmp eq i64 [[TMP25]], 4295098368
// CHECK-NEXT:    [[TMP27:%.*]] = and i1 true, [[TMP26]]
// CHECK-NEXT:    br i1 [[TMP27]], label [[RESOLVER_RETURN11:%.*]], label [[RESOLVER_ELSE12:%.*]]
// CHECK:       resolver_return11:
// CHECK-NEXT:    ret ptr @fmv_inline._MditMsve-ebf16
// CHECK:       resolver_else12:
// CHECK-NEXT:    [[TMP28:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT:    [[TMP29:%.*]] = and i64 [[TMP28]], 3221225472
// CHECK-NEXT:    [[TMP30:%.*]] = icmp eq i64 [[TMP29]], 3221225472
// CHECK-NEXT:    [[TMP31:%.*]] = and i1 true, [[TMP30]]
// CHECK-NEXT:    br i1 [[TMP31]], label [[RESOLVER_RETURN13:%.*]], label [[RESOLVER_ELSE14:%.*]]
// CHECK:       resolver_return13:
// CHECK-NEXT:    ret ptr @fmv_inline._MsveMsve-bf16
// CHECK:       resolver_else14:
// CHECK-NEXT:    [[TMP32:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT:    [[TMP33:%.*]] = and i64 [[TMP32]], 20971520
// CHECK-NEXT:    [[TMP34:%.*]] = icmp eq i64 [[TMP33]], 20971520
// CHECK-NEXT:    [[TMP35:%.*]] = and i1 true, [[TMP34]]
// CHECK-NEXT:    br i1 [[TMP35]], label [[RESOLVER_RETURN15:%.*]], label [[RESOLVER_ELSE16:%.*]]
// CHECK:       resolver_return15:
// CHECK-NEXT:    ret ptr @fmv_inline._MrcpcMfrintts
// CHECK:       resolver_else16:
// CHECK-NEXT:    [[TMP36:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT:    [[TMP37:%.*]] = and i64 [[TMP36]], 8650752
// CHECK-NEXT:    [[TMP38:%.*]] = icmp eq i64 [[TMP37]], 8650752
// CHECK-NEXT:    [[TMP39:%.*]] = and i1 true, [[TMP38]]
// CHECK-NEXT:    br i1 [[TMP39]], label [[RESOLVER_RETURN17:%.*]], label [[RESOLVER_ELSE18:%.*]]
// CHECK:       resolver_return17:
// CHECK-NEXT:    ret ptr @fmv_inline._MdpbMrcpc2
// CHECK:       resolver_else18:
// CHECK-NEXT:    [[TMP40:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT:    [[TMP41:%.*]] = and i64 [[TMP40]], 1572864
// CHECK-NEXT:    [[TMP42:%.*]] = icmp eq i64 [[TMP41]], 1572864
// CHECK-NEXT:    [[TMP43:%.*]] = and i1 true, [[TMP42]]
// CHECK-NEXT:    br i1 [[TMP43]], label [[RESOLVER_RETURN19:%.*]], label [[RESOLVER_ELSE20:%.*]]
// CHECK:       resolver_return19:
// CHECK-NEXT:    ret ptr @fmv_inline._Mdpb2Mjscvt
// CHECK:       resolver_else20:
// CHECK-NEXT:    [[TMP44:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT:    [[TMP45:%.*]] = and i64 [[TMP44]], 35184372088832
// CHECK-NEXT:    [[TMP46:%.*]] = icmp eq i64 [[TMP45]], 35184372088832
// CHECK-NEXT:    [[TMP47:%.*]] = and i1 true, [[TMP46]]
// CHECK-NEXT:    br i1 [[TMP47]], label [[RESOLVER_RETURN21:%.*]], label [[RESOLVER_ELSE22:%.*]]
// CHECK:       resolver_return21:
// CHECK-NEXT:    ret ptr @fmv_inline._Mmemtag3
// CHECK:       resolver_else22:
// CHECK-NEXT:    ret ptr @fmv_inline
// CHECK-LABEL: @fmv_e.resolver(
// CHECK-NEXT:  resolver_entry:
// CHECK-NEXT:    ret ptr @fmv_e._Mls64
// CHECK-LABEL: @fmv_d.resolver(
// CHECK-NEXT:  resolver_entry:
// CHECK-NEXT:    call void @init_cpu_features_resolver()
// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[TMP0]], 70368744177664
// CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 70368744177664
// CHECK-NEXT:    [[TMP3:%.*]] = and i1 true, [[TMP2]]
// CHECK-NEXT:    br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
// CHECK:       resolver_return:
// CHECK-NEXT:    ret ptr @fmv_d._Msb
// CHECK:       resolver_else:
// CHECK-NEXT:    ret ptr @fmv_d
// CHECK-LABEL: @fmv_c.resolver(
// CHECK-NEXT:  resolver_entry:
// CHECK-NEXT:    call void @init_cpu_features_resolver()
// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[TMP0]], 281474976710656
// CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 281474976710656
// CHECK-NEXT:    [[TMP3:%.*]] = and i1 true, [[TMP2]]
// CHECK-NEXT:    br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
// CHECK:       resolver_return:
// CHECK-NEXT:    ret ptr @fmv_c._Mssbs
// CHECK:       resolver_else:
// CHECK-NEXT:    ret ptr @fmv_c
// CHECK-LABEL: @recur(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    call void @reca()
// CHECK-NEXT:    ret void
// CHECK-LABEL: @main(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[RETVAL:%.*]] = alloca i32, align 4
// CHECK-NEXT:    store i32 0, ptr [[RETVAL]], align 4
// CHECK-NEXT:    call void @recur()
// CHECK-NEXT:    [[CALL:%.*]] = call i32 @goo()
// CHECK-NEXT:    ret i32 [[CALL]]
// CHECK-LABEL: @hoo(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[FP1:%.*]] = alloca ptr, align 8
// CHECK-NEXT:    [[FP2:%.*]] = alloca ptr, align 8
// CHECK-NEXT:    call void @f(ptr noundef @fmv.ifunc)
// CHECK-NEXT:    store ptr @fmv.ifunc, ptr [[FP1]], align 8
// CHECK-NEXT:    store ptr @fmv.ifunc, ptr [[FP2]], align 8
// CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[FP1]], align 8
// CHECK-NEXT:    [[CALL:%.*]] = call i32 [[TMP0]]()
// CHECK-NEXT:    [[TMP1:%.*]] = load ptr, ptr [[FP2]], align 8
// CHECK-NEXT:    [[CALL1:%.*]] = call i32 [[TMP1]]()
// CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[CALL]], [[CALL1]]
// CHECK-NEXT:    ret i32 [[ADD]]
// CHECK-LABEL: @fmv_inline._Msha1MpmullMf64mm(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    ret i32 1
// CHECK-LABEL: @fmv_inline._Mfp16MfcmaMsmeMfp16(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    ret i32 2
// CHECK-LABEL: @fmv_inline._Msha3Mi8mmMf32mm(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    ret i32 12
// CHECK-LABEL: @fmv_inline._MditMsve-ebf16(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    ret i32 8
// CHECK-LABEL: @fmv_inline._MdpbMrcpc2(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    ret i32 6
// CHECK-LABEL: @fmv_inline._Mdpb2Mjscvt(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    ret i32 7
// CHECK-LABEL: @fmv_inline._MrcpcMfrintts(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    ret i32 3
// CHECK-LABEL: @fmv_inline._MsveMsve-bf16(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    ret i32 4
// CHECK-LABEL: @fmv_inline._Msve2-aesMsve2-sha3(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    ret i32 5
// CHECK-LABEL: @fmv_inline._Msve2Msve2-pmull128Msve2-bitperm(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    ret i32 9
// CHECK-LABEL: @fmv_inline._Msve2-sm4Mmemtag2(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    ret i32 10
// CHECK-LABEL: @fmv_inline._Mmemtag3(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    ret i32 11
// CHECK-LABEL: @fmv_inline(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    ret i32 3
// CHECK-LABEL: @fmv_d._Msb(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    ret i32 0
// CHECK-LABEL: define internal i32 @fmv_d(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    ret i32 1
// CHECK-NOFMV-LABEL: @fmv(
// CHECK-NOFMV-NEXT:  entry:
// CHECK-NOFMV-NEXT:    ret i32 0
// CHECK-NOFMV-LABEL: @fmv_one(
// CHECK-NOFMV-NEXT:  entry:
// CHECK-NOFMV-NEXT:    ret i32 0
// CHECK-NOFMV-LABEL: @fmv_two(
// CHECK-NOFMV-NEXT:  entry:
// CHECK-NOFMV-NEXT:    ret i32 0
// CHECK-NOFMV-LABEL: @foo(
// CHECK-NOFMV-NEXT:  entry:
// CHECK-NOFMV-NEXT:    [[CALL:%.*]] = call i32 @fmv()
// CHECK-NOFMV-NEXT:    [[CALL1:%.*]] = call i32 @fmv_one()
// CHECK-NOFMV-NEXT:    [[ADD:%.*]] = add nsw i32 [[CALL]], [[CALL1]]
// CHECK-NOFMV-NEXT:    [[CALL2:%.*]] = call i32 @fmv_two()
// CHECK-NOFMV-NEXT:    [[ADD3:%.*]] = add nsw i32 [[ADD]], [[CALL2]]
// CHECK-NOFMV-NEXT:    ret i32 [[ADD3]]
// CHECK-NOFMV-LABEL: @fmv_e(
// CHECK-NOFMV-NEXT:  entry:
// CHECK-NOFMV-NEXT:    ret i32 20
// CHECK-NOFMV-LABEL: @fmv_default(
// CHECK-NOFMV-NEXT:  entry:
// CHECK-NOFMV-NEXT:    ret i32 111
// CHECK-NOFMV-LABEL: @fmv_c(
// CHECK-NOFMV-NEXT:  entry:
// CHECK-NOFMV-NEXT:    ret void
// CHECK-NOFMV-LABEL: @goo(
// CHECK-NOFMV-NEXT:  entry:
// CHECK-NOFMV-NEXT:    [[CALL:%.*]] = call i32 @fmv_inline()
// CHECK-NOFMV-NEXT:    [[CALL1:%.*]] = call i32 @fmv_e()
// CHECK-NOFMV-NEXT:    [[CALL2:%.*]] = call i32 @fmv_d()
// CHECK-NOFMV-NEXT:    call void @fmv_c()
// CHECK-NOFMV-NEXT:    [[CALL3:%.*]] = call i32 @fmv_default()
// CHECK-NOFMV-NEXT:    ret i32 [[CALL3]]
// CHECK-NOFMV-LABEL: define internal i32 @fmv_d(
// CHECK-NOFMV-NEXT:  entry:
// CHECK-NOFMV-NEXT:    ret i32 1
// CHECK-NOFMV-LABEL: @recur(
// CHECK-NOFMV-NEXT:  entry:
// CHECK-NOFMV-NEXT:    call void @reca()
// CHECK-NOFMV-NEXT:    ret void
// CHECK-NOFMV-LABEL: @main(
// CHECK-NOFMV-NEXT:  entry:
// CHECK-NOFMV-NEXT:    [[RETVAL:%.*]] = alloca i32, align 4
// CHECK-NOFMV-NEXT:    store i32 0, ptr [[RETVAL]], align 4
// CHECK-NOFMV-NEXT:    call void @recur()
// CHECK-NOFMV-NEXT:    [[CALL:%.*]] = call i32 @goo()
// CHECK-NOFMV-NEXT:    ret i32 [[CALL]]
// CHECK-NOFMV-LABEL: @hoo(
// CHECK-NOFMV-NEXT:  entry:
// CHECK-NOFMV-NEXT:    [[FP1:%.*]] = alloca ptr, align 8
// CHECK-NOFMV-NEXT:    [[FP2:%.*]] = alloca ptr, align 8
// CHECK-NOFMV-NEXT:    call void @f(ptr noundef @fmv)
// CHECK-NOFMV-NEXT:    store ptr @fmv, ptr [[FP1]], align 8
// CHECK-NOFMV-NEXT:    store ptr @fmv, ptr [[FP2]], align 8
// CHECK-NOFMV-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[FP1]], align 8
// CHECK-NOFMV-NEXT:    [[CALL:%.*]] = call i32 [[TMP0]]()
// CHECK-NOFMV-NEXT:    [[TMP1:%.*]] = load ptr, ptr [[FP2]], align 8
// CHECK-NOFMV-NEXT:    [[CALL1:%.*]] = call i32 [[TMP1]]()
// CHECK-NOFMV-NEXT:    [[ADD:%.*]] = add nsw i32 [[CALL]], [[CALL1]]
// CHECK-NOFMV-NEXT:    ret i32 [[ADD]]

// CHECK: attributes #0 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+flagm,+fp-armv8,+fp16fml,+fullfp16,+ls64,+neon,+rand" }
// CHECK: attributes #1 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+altnzcv,+bf16,+flagm,+fullfp16,+ls64,+sme,+sme-i16i64" }
// CHECK: attributes #2 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+ls64,+lse,+neon,+sha2" }
// CHECK: attributes #3 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+dotprod,+fp-armv8,+fullfp16,+ls64,+neon" }
// CHECK: attributes #4 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fp16fml,+fullfp16,+ls64,+neon" }
// CHECK: attributes #5 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+ls64,+neon" }
// CHECK: attributes #6 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+crc,+fullfp16,+ls64" }
// CHECK: attributes #7 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bti,+fullfp16,+ls64" }
// CHECK: attributes #8 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+fullfp16,+ls64,+sme,+sme2" }
// CHECK: attributes #9 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+ls64" }
// CHECK: attributes #10 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ccpp,+fullfp16,+ls64" }
// CHECK: attributes #11 = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+ls64" }
// CHECK: attributes #12 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+aes,+f64mm,+fp-armv8,+fullfp16,+ls64,+neon,+sve" }
// CHECK: attributes #13 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+complxnum,+fp-armv8,+fullfp16,+ls64,+neon,+sme" }
// CHECK: attributes #14 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+f32mm,+fp-armv8,+fullfp16,+i8mm,+ls64,+neon,+sha2,+sha3,+sve" }
// CHECK: attributes #15 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+dit,+fp-armv8,+fullfp16,+ls64,+neon,+sve" }
// CHECK: attributes #16 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ccpp,+fullfp16,+ls64,+rcpc" }
// CHECK: attributes #17 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ccdp,+ccpp,+fp-armv8,+fullfp16,+jsconv,+ls64,+neon" }
// CHECK: attributes #18 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fptoint,+fullfp16,+ls64,+rcpc" }
// CHECK: attributes #19 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+fp-armv8,+fullfp16,+ls64,+neon,+sve" }
// CHECK: attributes #20 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+ls64,+neon,+sve,+sve2,+sve2-aes,+sve2-sha3" }
// CHECK: attributes #21 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+ls64,+neon,+sve,+sve2,+sve2-aes,+sve2-bitperm" }
// CHECK: attributes #22 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+ls64,+mte,+neon,+sve,+sve2,+sve2-sm4" }
// CHECK: attributes #23 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+ls64,+mte" }
// CHECK: attributes #24 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+ls64,+sb" }

// CHECK-NOFMV: attributes #0 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-fmv" }
// CHECK-NOFMV: attributes #1 = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-fmv" }
