Home | History | Annotate | Download | only in AArch64
      1 ; RUN: llc -mtriple=arm64-linux-gnu -verify-machineinstrs -mcpu=cyclone -aarch64-atomic-cfg-tidy=0 < %s | FileCheck %s
      2 
      3 @lhs = global fp128 zeroinitializer, align 16
      4 @rhs = global fp128 zeroinitializer, align 16
      5 
      6 define fp128 @test_add() {
      7 ; CHECK-LABEL: test_add:
      8 
      9   %lhs = load fp128* @lhs, align 16
     10   %rhs = load fp128* @rhs, align 16
     11 ; CHECK: ldr q0, [{{x[0-9]+}}, :lo12:lhs]
     12 ; CHECK: ldr q1, [{{x[0-9]+}}, :lo12:rhs]
     13 
     14   %val = fadd fp128 %lhs, %rhs
     15 ; CHECK: bl __addtf3
     16   ret fp128 %val
     17 }
     18 
     19 define fp128 @test_sub() {
     20 ; CHECK-LABEL: test_sub:
     21 
     22   %lhs = load fp128* @lhs, align 16
     23   %rhs = load fp128* @rhs, align 16
     24 ; CHECK: ldr q0, [{{x[0-9]+}}, :lo12:lhs]
     25 ; CHECK: ldr q1, [{{x[0-9]+}}, :lo12:rhs]
     26 
     27   %val = fsub fp128 %lhs, %rhs
     28 ; CHECK: bl __subtf3
     29   ret fp128 %val
     30 }
     31 
     32 define fp128 @test_mul() {
     33 ; CHECK-LABEL: test_mul:
     34 
     35   %lhs = load fp128* @lhs, align 16
     36   %rhs = load fp128* @rhs, align 16
     37 ; CHECK: ldr q0, [{{x[0-9]+}}, :lo12:lhs]
     38 ; CHECK: ldr q1, [{{x[0-9]+}}, :lo12:rhs]
     39 
     40   %val = fmul fp128 %lhs, %rhs
     41 ; CHECK: bl __multf3
     42   ret fp128 %val
     43 }
     44 
     45 define fp128 @test_div() {
     46 ; CHECK-LABEL: test_div:
     47 
     48   %lhs = load fp128* @lhs, align 16
     49   %rhs = load fp128* @rhs, align 16
     50 ; CHECK: ldr q0, [{{x[0-9]+}}, :lo12:lhs]
     51 ; CHECK: ldr q1, [{{x[0-9]+}}, :lo12:rhs]
     52 
     53   %val = fdiv fp128 %lhs, %rhs
     54 ; CHECK: bl __divtf3
     55   ret fp128 %val
     56 }
     57 
     58 @var32 = global i32 0
     59 @var64 = global i64 0
     60 
     61 define void @test_fptosi() {
     62 ; CHECK-LABEL: test_fptosi:
     63   %val = load fp128* @lhs, align 16
     64 
     65   %val32 = fptosi fp128 %val to i32
     66   store i32 %val32, i32* @var32
     67 ; CHECK: bl __fixtfsi
     68 
     69   %val64 = fptosi fp128 %val to i64
     70   store i64 %val64, i64* @var64
     71 ; CHECK: bl __fixtfdi
     72 
     73   ret void
     74 }
     75 
     76 define void @test_fptoui() {
     77 ; CHECK-LABEL: test_fptoui:
     78   %val = load fp128* @lhs, align 16
     79 
     80   %val32 = fptoui fp128 %val to i32
     81   store i32 %val32, i32* @var32
     82 ; CHECK: bl __fixunstfsi
     83 
     84   %val64 = fptoui fp128 %val to i64
     85   store i64 %val64, i64* @var64
     86 ; CHECK: bl __fixunstfdi
     87 
     88   ret void
     89 }
     90 
     91 define void @test_sitofp() {
     92 ; CHECK-LABEL: test_sitofp:
     93 
     94   %src32 = load i32* @var32
     95   %val32 = sitofp i32 %src32 to fp128
     96   store volatile fp128 %val32, fp128* @lhs
     97 ; CHECK: bl __floatsitf
     98 
     99   %src64 = load i64* @var64
    100   %val64 = sitofp i64 %src64 to fp128
    101   store volatile fp128 %val64, fp128* @lhs
    102 ; CHECK: bl __floatditf
    103 
    104   ret void
    105 }
    106 
    107 define void @test_uitofp() {
    108 ; CHECK-LABEL: test_uitofp:
    109 
    110   %src32 = load i32* @var32
    111   %val32 = uitofp i32 %src32 to fp128
    112   store volatile fp128 %val32, fp128* @lhs
    113 ; CHECK: bl __floatunsitf
    114 
    115   %src64 = load i64* @var64
    116   %val64 = uitofp i64 %src64 to fp128
    117   store volatile fp128 %val64, fp128* @lhs
    118 ; CHECK: bl __floatunditf
    119 
    120   ret void
    121 }
    122 
    123 define i1 @test_setcc1() {
    124 ; CHECK-LABEL: test_setcc1:
    125 
    126   %lhs = load fp128* @lhs, align 16
    127   %rhs = load fp128* @rhs, align 16
    128 ; CHECK: ldr q0, [{{x[0-9]+}}, :lo12:lhs]
    129 ; CHECK: ldr q1, [{{x[0-9]+}}, :lo12:rhs]
    130 
    131 ; Technically, everything after the call to __letf2 is redundant, but we'll let
    132 ; LLVM have its fun for now.
    133   %val = fcmp ole fp128 %lhs, %rhs
    134 ; CHECK: bl __letf2
    135 ; CHECK: cmp w0, #0
    136 ; CHECK: cset w0, le
    137 
    138   ret i1 %val
    139 ; CHECK: ret
    140 }
    141 
    142 define i1 @test_setcc2() {
    143 ; CHECK-LABEL: test_setcc2:
    144 
    145   %lhs = load fp128* @lhs, align 16
    146   %rhs = load fp128* @rhs, align 16
    147 ; CHECK: ldr q0, [{{x[0-9]+}}, :lo12:lhs]
    148 ; CHECK: ldr q1, [{{x[0-9]+}}, :lo12:rhs]
    149 
    150   %val = fcmp ugt fp128 %lhs, %rhs
    151 ; CHECK: bl      __gttf2
    152 ; CHECK: cmp     w0, #0
    153 ; CHECK: cset   [[GT:w[0-9]+]], gt
    154 
    155 ; CHECK: bl      __unordtf2
    156 ; CHECK: cmp     w0, #0
    157 ; CHECK: cset   [[UNORDERED:w[0-9]+]], ne
    158 ; CHECK: orr     w0, [[UNORDERED]], [[GT]]
    159 
    160   ret i1 %val
    161 ; CHECK: ret
    162 }
    163 
    164 define i32 @test_br_cc() {
    165 ; CHECK-LABEL: test_br_cc:
    166 
    167   %lhs = load fp128* @lhs, align 16
    168   %rhs = load fp128* @rhs, align 16
    169 ; CHECK: ldr q0, [{{x[0-9]+}}, :lo12:lhs]
    170 ; CHECK: ldr q1, [{{x[0-9]+}}, :lo12:rhs]
    171 
    172   ; olt == !uge, which LLVM unfortunately "optimizes" this to.
    173   %cond = fcmp olt fp128 %lhs, %rhs
    174 ; CHECK: bl      __getf2
    175 ; CHECK: cmp     w0, #0
    176 ; CHECK: cset   [[OGE:w[0-9]+]], ge
    177 
    178 ; CHECK: bl      __unordtf2
    179 ; CHECK: cmp     w0, #0
    180 ; CHECK: cset   [[UNORDERED:w[0-9]+]], ne
    181 
    182 ; CHECK: orr     [[UGE:w[0-9]+]], [[UNORDERED]], [[OGE]]
    183 ; CHECK: cbnz [[UGE]], [[RET29:.LBB[0-9]+_[0-9]+]]
    184   br i1 %cond, label %iftrue, label %iffalse
    185 
    186 iftrue:
    187   ret i32 42
    188 ; CHECK-NEXT: BB#
    189 ; CHECK-NEXT: movz w0, #0x2a
    190 ; CHECK-NEXT: b [[REALRET:.LBB[0-9]+_[0-9]+]]
    191 
    192 iffalse:
    193   ret i32 29
    194 ; CHECK: [[RET29]]:
    195 ; CHECK-NEXT: movz w0, #0x1d
    196 ; CHECK-NEXT: [[REALRET]]:
    197 ; CHECK: ret
    198 }
    199 
    200 define void @test_select(i1 %cond, fp128 %lhs, fp128 %rhs) {
    201 ; CHECK-LABEL: test_select:
    202 
    203   %val = select i1 %cond, fp128 %lhs, fp128 %rhs
    204   store fp128 %val, fp128* @lhs, align 16
    205 ; CHECK: tst w0, #0x1
    206 ; CHECK-NEXT: b.eq [[IFFALSE:.LBB[0-9]+_[0-9]+]]
    207 ; CHECK-NEXT: BB#
    208 ; CHECK-NEXT: mov v[[VAL:[0-9]+]].16b, v0.16b
    209 ; CHECK-NEXT: [[IFFALSE]]:
    210 ; CHECK: str q[[VAL]], [{{x[0-9]+}}, :lo12:lhs]
    211   ret void
    212 ; CHECK: ret
    213 }
    214 
    215 @varfloat = global float 0.0, align 4
    216 @vardouble = global double 0.0, align 8
    217 
    218 define void @test_round() {
    219 ; CHECK-LABEL: test_round:
    220 
    221   %val = load fp128* @lhs, align 16
    222 
    223   %float = fptrunc fp128 %val to float
    224   store float %float, float* @varfloat, align 4
    225 ; CHECK: bl __trunctfsf2
    226 ; CHECK: str s0, [{{x[0-9]+}}, :lo12:varfloat]
    227 
    228   %double = fptrunc fp128 %val to double
    229   store double %double, double* @vardouble, align 8
    230 ; CHECK: bl __trunctfdf2
    231 ; CHECK: str d0, [{{x[0-9]+}}, :lo12:vardouble]
    232 
    233   ret void
    234 }
    235 
    236 define void @test_extend() {
    237 ; CHECK-LABEL: test_extend:
    238 
    239   %val = load fp128* @lhs, align 16
    240 
    241   %float = load float* @varfloat
    242   %fromfloat = fpext float %float to fp128
    243   store volatile fp128 %fromfloat, fp128* @lhs, align 16
    244 ; CHECK: bl __extendsftf2
    245 ; CHECK: str q0, [{{x[0-9]+}}, :lo12:lhs]
    246 
    247   %double = load double* @vardouble
    248   %fromdouble = fpext double %double to fp128
    249   store volatile fp128 %fromdouble, fp128* @lhs, align 16
    250 ; CHECK: bl __extenddftf2
    251 ; CHECK: str q0, [{{x[0-9]+}}, :lo12:lhs]
    252 
    253   ret void
    254 ; CHECK: ret
    255 }
    256 
    257 define fp128 @test_neg(fp128 %in) {
    258 ; CHECK: [[MINUS0:.LCPI[0-9]+_0]]:
    259 ; Make sure the weird hex constant below *is* -0.0
    260 ; CHECK-NEXT: fp128 -0
    261 
    262 ; CHECK-LABEL: test_neg:
    263 
    264   ; Could in principle be optimized to fneg which we can't select, this makes
    265   ; sure that doesn't happen.
    266   %ret = fsub fp128 0xL00000000000000008000000000000000, %in
    267 ; CHECK: mov v1.16b, v0.16b
    268 ; CHECK: ldr q0, [{{x[0-9]+}}, :lo12:[[MINUS0]]]
    269 ; CHECK: bl __subtf3
    270 
    271   ret fp128 %ret
    272 ; CHECK: ret
    273 }
    274