1; RUN: llc -mtriple=arm64-linux-gnu -verify-machineinstrs -mcpu=cyclone -aarch64-enable-atomic-cfg-tidy=0 < %s | FileCheck -enable-var-scope %s 2 3@lhs = global fp128 zeroinitializer, align 16 4@rhs = global fp128 zeroinitializer, align 16 5 6define fp128 @test_add() { 7; CHECK-LABEL: test_add: 8 9 %lhs = load fp128, fp128* @lhs, align 16 10 %rhs = load fp128, 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 19define fp128 @test_sub() { 20; CHECK-LABEL: test_sub: 21 22 %lhs = load fp128, fp128* @lhs, align 16 23 %rhs = load fp128, 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 32define fp128 @test_mul() { 33; CHECK-LABEL: test_mul: 34 35 %lhs = load fp128, fp128* @lhs, align 16 36 %rhs = load fp128, 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 45define fp128 @test_div() { 46; CHECK-LABEL: test_div: 47 48 %lhs = load fp128, fp128* @lhs, align 16 49 %rhs = load fp128, 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 61define void @test_fptosi() { 62; CHECK-LABEL: test_fptosi: 63 %val = load fp128, 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 76define void @test_fptoui() { 77; CHECK-LABEL: test_fptoui: 78 %val = load fp128, 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 91define void @test_sitofp() { 92; CHECK-LABEL: test_sitofp: 93 94 %src32 = load i32, 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, 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 107define void @test_uitofp() { 108; CHECK-LABEL: test_uitofp: 109 110 %src32 = load i32, 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, 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 123define i1 @test_setcc1() { 124; CHECK-LABEL: test_setcc1: 125 126 %lhs = load fp128, fp128* @lhs, align 16 127 %rhs = load fp128, 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 142define i1 @test_setcc2() { 143; CHECK-LABEL: test_setcc2: 144 145 %lhs = load fp128, fp128* @lhs, align 16 146 %rhs = load fp128, 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 __letf2 152; CHECK: cmp w0, #0 153; CHECK: cset w0, gt 154 155 ret i1 %val 156; CHECK: ret 157} 158 159define i1 @test_setcc3() { 160; CHECK-LABEL: test_setcc3: 161 162 %lhs = load fp128, fp128* @lhs, align 16 163 %rhs = load fp128, fp128* @rhs, align 16 164; CHECK: ldr q0, [{{x[0-9]+}}, :lo12:lhs] 165; CHECK: ldr q1, [{{x[0-9]+}}, :lo12:rhs] 166 167 %val = fcmp ueq fp128 %lhs, %rhs 168; CHECK: bl __eqtf2 169; CHECK: cmp w0, #0 170; CHECK: cset w19, eq 171; CHECK: bl __unordtf2 172; CHECK: cmp w0, #0 173; CHECK: cset w8, ne 174; CHECK: orr w0, w8, w19 175 176 ret i1 %val 177; CHECK: ret 178} 179 180 181define i32 @test_br_cc() { 182; CHECK-LABEL: test_br_cc: 183 184 %lhs = load fp128, fp128* @lhs, align 16 185 %rhs = load fp128, fp128* @rhs, align 16 186; CHECK: ldr q0, [{{x[0-9]+}}, :lo12:lhs] 187; CHECK: ldr q1, [{{x[0-9]+}}, :lo12:rhs] 188 189 ; olt == !uge, which LLVM optimizes this to. 190 %cond = fcmp olt fp128 %lhs, %rhs 191; CHECK: bl __lttf2 192; CHECK-NEXT: cmp w0, #0 193; CHECK-NEXT: b.ge {{.LBB[0-9]+_[0-9]+}} 194 br i1 %cond, label %iftrue, label %iffalse 195 196iftrue: 197 ret i32 42 198; CHECK-NEXT: %bb. 199; CHECK-NEXT: mov w0, #42 200; CHECK: ret 201iffalse: 202 ret i32 29 203; CHECK: mov w0, #29 204; CHECK: ret 205} 206 207define void @test_select(i1 %cond, fp128 %lhs, fp128 %rhs) { 208; CHECK-LABEL: test_select: 209 210 %val = select i1 %cond, fp128 %lhs, fp128 %rhs 211 store fp128 %val, fp128* @lhs, align 16 212; CHECK: tst w0, #0x1 213; CHECK-NEXT: b.eq [[IFFALSE:.LBB[0-9]+_[0-9]+]] 214; CHECK-NEXT: %bb. 215; CHECK-NEXT: mov v[[VAL:[0-9]+]].16b, v0.16b 216; CHECK-NEXT: [[IFFALSE]]: 217; CHECK: str q[[VAL]], [{{x[0-9]+}}, :lo12:lhs] 218 ret void 219; CHECK: ret 220} 221 222@varfloat = global float 0.0, align 4 223@vardouble = global double 0.0, align 8 224 225define void @test_round() { 226; CHECK-LABEL: test_round: 227 228 %val = load fp128, fp128* @lhs, align 16 229 230 %float = fptrunc fp128 %val to float 231 store float %float, float* @varfloat, align 4 232; CHECK: bl __trunctfsf2 233; CHECK: str s0, [{{x[0-9]+}}, :lo12:varfloat] 234 235 %double = fptrunc fp128 %val to double 236 store double %double, double* @vardouble, align 8 237; CHECK: bl __trunctfdf2 238; CHECK: str d0, [{{x[0-9]+}}, :lo12:vardouble] 239 240 ret void 241} 242 243define void @test_extend() { 244; CHECK-LABEL: test_extend: 245 246 %val = load fp128, fp128* @lhs, align 16 247 248 %float = load float, float* @varfloat 249 %fromfloat = fpext float %float to fp128 250 store volatile fp128 %fromfloat, fp128* @lhs, align 16 251; CHECK: bl __extendsftf2 252; CHECK: str q0, [{{x[0-9]+}}, :lo12:lhs] 253 254 %double = load double, double* @vardouble 255 %fromdouble = fpext double %double to fp128 256 store volatile fp128 %fromdouble, fp128* @lhs, align 16 257; CHECK: bl __extenddftf2 258; CHECK: str q0, [{{x[0-9]+}}, :lo12:lhs] 259 260 ret void 261; CHECK: ret 262} 263 264define fp128 @test_neg(fp128 %in) { 265; CHECK: [[$MINUS0:.LCPI[0-9]+_0]]: 266; Make sure the weird hex constant below *is* -0.0 267; CHECK-NEXT: fp128 -0 268 269; CHECK-LABEL: test_neg: 270 271 ; Could in principle be optimized to fneg which we can't select, this makes 272 ; sure that doesn't happen. 273 %ret = fsub fp128 0xL00000000000000008000000000000000, %in 274; CHECK: mov v1.16b, v0.16b 275; CHECK: ldr q0, [{{x[0-9]+}}, :lo12:[[$MINUS0]]] 276; CHECK: bl __subtf3 277 278 ret fp128 %ret 279; CHECK: ret 280} 281