Home | History | Annotate | Download | only in AArch64
      1 ; RUN: llc < %s -verify-machineinstrs -mtriple=arm64-none-linux-gnu -mattr=+neon -fp-contract=fast | FileCheck %s
      2 
      3 ; FIXME: We should not generate ld/st for such register spill/fill, because the
      4 ; test case seems very simple and the register pressure is not high. If the
      5 ; spill/fill algorithm is optimized, this test case may not be triggered. And
      6 ; then we can delete it.
      7 define i32 @spill.DPairReg(i32* %arg1, i32 %arg2) {
      8 ; CHECK-LABEL: spill.DPairReg:
      9 ; CHECK: ld2 { v{{[0-9]+}}.2s, v{{[0-9]+}}.2s }, [{{x[0-9]+|sp}}]
     10 ; CHECK: st1 { v{{[0-9]+}}.2d, v{{[0-9]+}}.2d }, [{{x[0-9]+|sp}}]
     11 ; CHECK: ld1 { v{{[0-9]+}}.2d, v{{[0-9]+}}.2d }, [{{x[0-9]+|sp}}]
     12 entry:
     13   %vld = tail call { <2 x i32>, <2 x i32> } @llvm.aarch64.neon.ld2.v2i32.p0i32(i32* %arg1)
     14   %cmp = icmp eq i32 %arg2, 0
     15   br i1 %cmp, label %if.then, label %if.end
     16 
     17 if.then:
     18   tail call void @foo()
     19   br label %if.end
     20 
     21 if.end:
     22   %vld.extract = extractvalue { <2 x i32>, <2 x i32> } %vld, 0
     23   %res = extractelement <2 x i32> %vld.extract, i32 1
     24   ret i32 %res
     25 }
     26 
     27 define i16 @spill.DTripleReg(i16* %arg1, i32 %arg2) {
     28 ; CHECK-LABEL: spill.DTripleReg:
     29 ; CHECK: ld3 { v{{[0-9]+}}.4h, v{{[0-9]+}}.4h, v{{[0-9]+}}.4h }, [{{x[0-9]+|sp}}]
     30 ; CHECK: st1 { v{{[0-9]+}}.2d, v{{[0-9]+}}.2d, v{{[0-9]+}}.2d }, [{{x[0-9]+|sp}}]
     31 ; CHECK: ld1 { v{{[0-9]+}}.2d, v{{[0-9]+}}.2d, v{{[0-9]+}}.2d }, [{{x[0-9]+|sp}}]
     32 entry:
     33   %vld = tail call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld3.v4i16.p0i16(i16* %arg1)
     34   %cmp = icmp eq i32 %arg2, 0
     35   br i1 %cmp, label %if.then, label %if.end
     36 
     37 if.then:
     38   tail call void @foo()
     39   br label %if.end
     40 
     41 if.end:
     42   %vld.extract = extractvalue { <4 x i16>, <4 x i16>, <4 x i16> } %vld, 0
     43   %res = extractelement <4 x i16> %vld.extract, i32 1
     44   ret i16 %res
     45 }
     46 
     47 define i16 @spill.DQuadReg(i16* %arg1, i32 %arg2) {
     48 ; CHECK-LABEL: spill.DQuadReg:
     49 ; CHECK: ld4 { v{{[0-9]+}}.4h, v{{[0-9]+}}.4h, v{{[0-9]+}}.4h, v{{[0-9]+}}.4h }, [{{x[0-9]+|sp}}]
     50 ; CHECK: st1 { v{{[0-9]+}}.2d, v{{[0-9]+}}.2d, v{{[0-9]+}}.2d, v{{[0-9]+}}.2d }, [{{x[0-9]+|sp}}]
     51 ; CHECK: ld1 { v{{[0-9]+}}.2d, v{{[0-9]+}}.2d, v{{[0-9]+}}.2d, v{{[0-9]+}}.2d }, [{{x[0-9]+|sp}}]
     52 entry:
     53   %vld = tail call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld4.v4i16.p0i16(i16* %arg1)
     54   %cmp = icmp eq i32 %arg2, 0
     55   br i1 %cmp, label %if.then, label %if.end
     56 
     57 if.then:
     58   tail call void @foo()
     59   br label %if.end
     60 
     61 if.end:
     62   %vld.extract = extractvalue { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } %vld, 0
     63   %res = extractelement <4 x i16> %vld.extract, i32 0
     64   ret i16 %res
     65 }
     66 
     67 define i32 @spill.QPairReg(i32* %arg1, i32 %arg2) {
     68 ; CHECK-LABEL: spill.QPairReg:
     69 ; CHECK: ld2 { v{{[0-9]+}}.4s, v{{[0-9]+}}.4s }, [{{x[0-9]+|sp}}]
     70 ; CHECK: st1 { v{{[0-9]+}}.2d, v{{[0-9]+}}.2d }, [{{x[0-9]+|sp}}]
     71 ; CHECK: ld1 { v{{[0-9]+}}.2d, v{{[0-9]+}}.2d }, [{{x[0-9]+|sp}}]
     72 entry:
     73   %vld = tail call { <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld2.v4i32.p0i32(i32* %arg1)
     74   %cmp = icmp eq i32 %arg2, 0
     75   br i1 %cmp, label %if.then, label %if.end
     76 
     77 if.then:
     78   tail call void @foo()
     79   br label %if.end
     80 
     81 if.end:
     82   %vld.extract = extractvalue { <4 x i32>, <4 x i32> } %vld, 0
     83   %res = extractelement <4 x i32> %vld.extract, i32 1
     84   ret i32 %res
     85 }
     86 
     87 define float @spill.QTripleReg(float* %arg1, i32 %arg2) {
     88 ; CHECK-LABEL: spill.QTripleReg:
     89 ; CHECK: ld3 { v{{[0-9]+}}.4s, v{{[0-9]+}}.4s, v{{[0-9]+}}.4s }, [{{x[0-9]+|sp}}]
     90 ; CHECK: st1 { v{{[0-9]+}}.2d, v{{[0-9]+}}.2d, v{{[0-9]+}}.2d }, [{{x[0-9]+|sp}}]
     91 ; CHECK: ld1 { v{{[0-9]+}}.2d, v{{[0-9]+}}.2d, v{{[0-9]+}}.2d }, [{{x[0-9]+|sp}}]
     92 entry:
     93   %vld3 = tail call { <4 x float>, <4 x float>, <4 x float> } @llvm.aarch64.neon.ld3.v4f32.p0f32(float* %arg1)
     94   %cmp = icmp eq i32 %arg2, 0
     95   br i1 %cmp, label %if.then, label %if.end
     96 
     97 if.then:
     98   tail call void @foo()
     99   br label %if.end
    100 
    101 if.end:
    102   %vld3.extract = extractvalue { <4 x float>, <4 x float>, <4 x float> } %vld3, 0
    103   %res = extractelement <4 x float> %vld3.extract, i32 1
    104   ret float %res
    105 }
    106 
    107 define i8 @spill.QQuadReg(i8* %arg1, i32 %arg2) {
    108 ; CHECK-LABEL: spill.QQuadReg:
    109 ; CHECK: ld4 { v{{[0-9]+}}.16b, v{{[0-9]+}}.16b, v{{[0-9]+}}.16b, v{{[0-9]+}}.16b }, [{{x[0-9]+|sp}}]
    110 ; CHECK: st1 { v{{[0-9]+}}.2d, v{{[0-9]+}}.2d, v{{[0-9]+}}.2d, v{{[0-9]+}}.2d }, [{{x[0-9]+|sp}}]
    111 ; CHECK: ld1 { v{{[0-9]+}}.2d, v{{[0-9]+}}.2d, v{{[0-9]+}}.2d, v{{[0-9]+}}.2d }, [{{x[0-9]+|sp}}]
    112 entry:
    113   %vld = tail call { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld4.v16i8.p0i8(i8* %arg1)
    114   %cmp = icmp eq i32 %arg2, 0
    115   br i1 %cmp, label %if.then, label %if.end
    116 
    117 if.then:
    118   tail call void @foo()
    119   br label %if.end
    120 
    121 if.end:
    122   %vld.extract = extractvalue { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } %vld, 0
    123   %res = extractelement <16 x i8> %vld.extract, i32 1
    124   ret i8 %res
    125 }
    126 
    127 declare { <2 x i32>, <2 x i32> } @llvm.aarch64.neon.ld2.v2i32.p0i32(i32*)
    128 declare { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld3.v4i16.p0i16(i16*)
    129 declare { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld4.v4i16.p0i16(i16*)
    130 declare { <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld2.v4i32.p0i32(i32*)
    131 declare { <4 x float>, <4 x float>, <4 x float> } @llvm.aarch64.neon.ld3.v4f32.p0f32(float*)
    132 declare { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld4.v16i8.p0i8(i8*)
    133 
    134 declare void @foo()
    135 
    136 ; FIXME: We should not generate ld/st for such register spill/fill, because the
    137 ; test case seems very simple and the register pressure is not high. If the
    138 ; spill/fill algorithm is optimized, this test case may not be triggered. And
    139 ; then we can delete it.
    140 ; check the spill for Register Class QPair_with_qsub_0_in_FPR128Lo
    141 define <8 x i16> @test_2xFPR128Lo(i64 %got, i64* %ptr, <1 x i64> %a) {
    142   tail call void @llvm.aarch64.neon.st2lane.v1i64.p0i64(<1 x i64> zeroinitializer, <1 x i64> zeroinitializer, i64 0, i64* %ptr)
    143   tail call void @foo()
    144   %sv = shufflevector <1 x i64> zeroinitializer, <1 x i64> %a, <2 x i32> <i32 0, i32 1>
    145   %1 = bitcast <2 x i64> %sv to <8 x i16>
    146   %2 = shufflevector <8 x i16> %1, <8 x i16> undef, <8 x i32> <i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2>
    147   %3 = mul <8 x i16> %2, %2
    148   ret <8 x i16> %3
    149 }
    150 
    151 ; check the spill for Register Class QTriple_with_qsub_0_in_FPR128Lo
    152 define <8 x i16> @test_3xFPR128Lo(i64 %got, i64* %ptr, <1 x i64> %a) {
    153   tail call void @llvm.aarch64.neon.st3lane.v1i64.p0i64(<1 x i64> zeroinitializer, <1 x i64> zeroinitializer, <1 x i64> zeroinitializer, i64 0, i64* %ptr)
    154   tail call void @foo()
    155   %sv = shufflevector <1 x i64> zeroinitializer, <1 x i64> %a, <2 x i32> <i32 0, i32 1>
    156   %1 = bitcast <2 x i64> %sv to <8 x i16>
    157   %2 = shufflevector <8 x i16> %1, <8 x i16> undef, <8 x i32> <i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2>
    158   %3 = mul <8 x i16> %2, %2
    159   ret <8 x i16> %3
    160 }
    161 
    162 ; check the spill for Register Class QQuad_with_qsub_0_in_FPR128Lo
    163 define <8 x i16> @test_4xFPR128Lo(i64 %got, i64* %ptr, <1 x i64> %a) {
    164   tail call void @llvm.aarch64.neon.st4lane.v1i64.p0i64(<1 x i64> zeroinitializer, <1 x i64> zeroinitializer, <1 x i64> zeroinitializer, <1 x i64> zeroinitializer, i64 0, i64* %ptr)
    165   tail call void @foo()
    166   %sv = shufflevector <1 x i64> zeroinitializer, <1 x i64> %a, <2 x i32> <i32 0, i32 1>
    167   %1 = bitcast <2 x i64> %sv to <8 x i16>
    168   %2 = shufflevector <8 x i16> %1, <8 x i16> undef, <8 x i32> <i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2>
    169   %3 = mul <8 x i16> %2, %2
    170   ret <8 x i16> %3
    171 }
    172 
    173 declare void @llvm.aarch64.neon.st2lane.v1i64.p0i64(<1 x i64>, <1 x i64>, i64, i64*)
    174 declare void @llvm.aarch64.neon.st3lane.v1i64.p0i64(<1 x i64>, <1 x i64>, <1 x i64>, i64, i64*)
    175 declare void @llvm.aarch64.neon.st4lane.v1i64.p0i64(<1 x i64>, <1 x i64>, <1 x i64>, <1 x i64>, i64, i64*)
    176