1 ; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \ 2 ; RUN: -mcpu=pwr8 < %s | FileCheck %s -check-prefix=CHECK-LE \ 3 ; RUN: --implicit-check-not xxswapd 4 5 ; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu \ 6 ; RUN: -mcpu=pwr8 < %s | FileCheck %s -check-prefix=CHECK-BE 7 8 ; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu \ 9 ; RUN: -mcpu=pwr8 -mattr=-vsx < %s | FileCheck %s -check-prefix=CHECK-NOVSX 10 11 ; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \ 12 ; RUN: -mcpu=pwr8 -mattr=-vsx < %s | FileCheck %s -check-prefix=CHECK-NOVSX \ 13 ; RUN: --implicit-check-not xxswapd 14 15 ; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu \ 16 ; RUN: -mcpu=pwr8 -mattr=-vsx < %s | FileCheck %s -check-prefix=CHECK-BE-NOVSX 17 18 ; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \ 19 ; RUN: -mcpu=pwr8 -mattr=-vsx < %s | \ 20 ; RUN: FileCheck %s -check-prefix=CHECK-LE-NOVSX --implicit-check-not xxswapd 21 22 ; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \ 23 ; RUN: -mcpu=pwr9 -ppc-asm-full-reg-names -ppc-vsr-nums-as-vr < %s | \ 24 ; RUN: FileCheck %s -check-prefix=CHECK-P9 --implicit-check-not xxswapd 25 26 ; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \ 27 ; RUN: -mcpu=pwr9 -mattr=-vsx < %s | FileCheck %s -check-prefix=CHECK-NOVSX \ 28 ; RUN: --implicit-check-not xxswapd 29 30 ; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \ 31 ; RUN: -mcpu=pwr9 -mattr=-power9-vector -mattr=-direct-move < %s | \ 32 ; RUN: FileCheck %s -check-prefix=CHECK-LE --implicit-check-not xxswapd 33 34 @x = common global <1 x i128> zeroinitializer, align 16 35 @y = common global <1 x i128> zeroinitializer, align 16 36 @a = common global i128 zeroinitializer, align 16 37 @b = common global i128 zeroinitializer, align 16 38 39 ; VSX: 40 ; %a is passed in register 34 41 ; The value of 1 is stored in the TOC. 42 ; On LE, ensure the value of 1 is swapped before being used (using xxswapd). 43 ; VMX (no VSX): 44 ; %a is passed in register 2 45 ; The value of 1 is stored in the TOC. 46 ; No swaps are necessary when using P8 Vector instructions on LE 47 define <1 x i128> @v1i128_increment_by_one(<1 x i128> %a) nounwind { 48 %tmp = add <1 x i128> %a, <i128 1> 49 ret <1 x i128> %tmp 50 51 ; FIXME: Seems a 128-bit literal is materialized by loading from the TOC. There 52 ; should be a better way of doing this. 53 54 ; CHECK-LE-LABEL: @v1i128_increment_by_one 55 ; CHECK-LE: lxvd2x [[VAL:[0-9]+]], {{[0-9]+}}, {{[0-9]+}} 56 ; CHECK-LE: xxswapd 35, [[VAL]] 57 ; CHECK-LE: vadduqm 2, 2, 3 58 ; CHECK-LE: blr 59 60 ; CHECK-P9-LABEL: @v1i128_increment_by_one 61 ; The below FIXME is due to the lowering for BUILD_VECTOR that will be fixed 62 ; in a subsequent patch. 63 ; FIXME: li [[R1:r[0-9]+]], 1 64 ; FIXME: li [[R2:r[0-9]+]], 0 65 ; FIXME: mtvsrdd [[V1:v[0-9]+]], [[R2]], [[R1]] 66 ; CHECK-P9: lxvx [[V1:v[0-9]+]] 67 ; CHECK-P9: vadduqm v2, v2, [[V1]] 68 ; CHECK-P9: blr 69 70 ; CHECK-BE-LABEL: @v1i128_increment_by_one 71 ; CHECK-BE: lxvd2x 35, {{[0-9]+}}, {{[0-9]+}} 72 ; CHECK-BE-NOT: xxswapd 73 ; CHECK-BE: vadduqm 2, 2, 3 74 ; CHECK-BE-NOT: xxswapd 34, {{[0-9]+}} 75 ; CHECK-BE: blr 76 77 ; CHECK-NOVSX-LABEL: @v1i128_increment_by_one 78 ; CHECK-NOVSX-NOT: xxswapd {{[0-9]+}}, {{[0-9]+}} 79 ; CHECK-NOVSX-NOT: stxvd2x {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}} 80 ; CHECK-NOVSX: lvx [[VAL:[0-9]+]], {{[0-9]+}}, {{[0-9]+}} 81 ; CHECK-NOVSX-NOT: lxvd2x {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}} 82 ; CHECK-NOVSX-NOT: xxswapd {{[0-9]+}}, {{[0-9]+}} 83 ; CHECK-NOVSX: vadduqm 2, 2, [[VAL]] 84 ; CHECK-NOVSX: blr 85 } 86 87 ; VSX: 88 ; %a is passed in register 34 89 ; %b is passed in register 35 90 ; No swaps are necessary when using P8 Vector instructions on LE 91 ; VMX (no VSX): 92 ; %a is passewd in register 2 93 ; %b is passed in register 3 94 ; On LE, do not need to swap contents of 2 and 3 because the lvx/stvx 95 ; instructions no not swap elements 96 define <1 x i128> @v1i128_increment_by_val(<1 x i128> %a, <1 x i128> %b) nounwind { 97 %tmp = add <1 x i128> %a, %b 98 ret <1 x i128> %tmp 99 100 ; CHECK-LE-LABEL: @v1i128_increment_by_val 101 ; CHECK-LE-NOT: xxswapd 102 ; CHECK-LE: adduqm 2, 2, 3 103 ; CHECK-LE: blr 104 105 ; CHECK-BE-LABEL: @v1i128_increment_by_val 106 ; CHECK-BE-NOT: xxswapd {{[0-9]+}}, 34 107 ; CHECK-BE-NOT: xxswapd {{[0-9]+}}, 35 108 ; CHECK-BE-NOT: xxswapd 34, [[RESULT]] 109 ; CHECK-BE: adduqm 2, 2, 3 110 ; CHECK-BE: blr 111 112 ; CHECK-NOVSX-LABEL: @v1i128_increment_by_val 113 ; CHECK-NOVSX-NOT: xxswapd 34, [[RESULT]] 114 ; CHECK-NOVSX: adduqm 2, 2, 3 115 ; CHECK-NOVSX: blr 116 } 117 118 ; Little Endian (VSX and VMX): 119 ; Lower 64-bits of %a are passed in register 3 120 ; Upper 64-bits of %a are passed in register 4 121 ; Increment lower 64-bits using addic (immediate value of 1) 122 ; Increment upper 64-bits using add zero extended 123 ; Results are placed in registers 3 and 4 124 ; Big Endian (VSX and VMX) 125 ; Lower 64-bits of %a are passed in register 4 126 ; Upper 64-bits of %a are passed in register 3 127 ; Increment lower 64-bits using addic (immediate value of 1) 128 ; Increment upper 64-bits using add zero extended 129 ; Results are placed in registers 3 and 4 130 define i128 @i128_increment_by_one(i128 %a) nounwind { 131 %tmp = add i128 %a, 1 132 ret i128 %tmp 133 ; CHECK-LE-LABEL: @i128_increment_by_one 134 ; CHECK-LE: addic 3, 3, 1 135 ; CHECK-LE-NEXT: addze 4, 4 136 ; CHECK-LE: blr 137 138 ; CHECK-BE-LABEL: @i128_increment_by_one 139 ; CHECK-BE: addic 4, 4, 1 140 ; CHECK-BE-NEXT: addze 3, 3 141 ; CHECK-BE: blr 142 143 ; CHECK-LE-NOVSX-LABEL: @i128_increment_by_one 144 ; CHECK-LE-NOVSX: addic 3, 3, 1 145 ; CHECK-LE-NOVSX-NEXT: addze 4, 4 146 ; CHECK-LE-NOVSX: blr 147 148 ; CHECK-BE-NOVSX-LABEL: @i128_increment_by_one 149 ; CHECK-BE-NOVSX: addic 4, 4, 1 150 ; CHECK-BE-NOVSX-NEXT: addze 3, 3 151 ; CHECK-BE-NOVSX: blr 152 } 153 154 ; Little Endian (VSX and VMX): 155 ; Lower 64-bits of %a are passed in register 3 156 ; Upper 64-bits of %a are passed in register 4 157 ; Lower 64-bits of %b are passed in register 5 158 ; Upper 64-bits of %b are passed in register 6 159 ; Add the lower 64-bits using addc on registers 3 and 5 160 ; Add the upper 64-bits using adde on registers 4 and 6 161 ; Registers 3 and 4 should hold the result 162 ; Big Endian (VSX and VMX): 163 ; Upper 64-bits of %a are passed in register 3 164 ; Lower 64-bits of %a are passed in register 4 165 ; Upper 64-bits of %b are passed in register 5 166 ; Lower 64-bits of %b are passed in register 6 167 ; Add the lower 64-bits using addc on registers 4 and 6 168 ; Add the upper 64-bits using adde on registers 3 and 5 169 ; Registers 3 and 4 should hold the result 170 define i128 @i128_increment_by_val(i128 %a, i128 %b) nounwind { 171 %tmp = add i128 %a, %b 172 ret i128 %tmp 173 ; CHECK-LE-LABEL: @i128_increment_by_val 174 ; CHECK-LE: addc 3, 3, 5 175 ; CHECK-LE-NEXT: adde 4, 4, 6 176 ; CHECK-LE: blr 177 178 ; CHECK-BE-LABEL: @i128_increment_by_val 179 ; CHECK-BE: addc 4, 4, 6 180 ; CHECK-BE-NEXT: adde 3, 3, 5 181 ; CHECK-BE: blr 182 183 ; CHECK-LE-NOVSX-LABEL: @i128_increment_by_val 184 ; CHECK-LE-NOVSX: addc 3, 3, 5 185 ; CHECK-LE-NOVSX-NEXT: adde 4, 4, 6 186 ; CHECK-LE-NOVSX: blr 187 188 ; CHECK-BE-NOVSX-LABEL: @i128_increment_by_val 189 ; CHECK-BE-NOVSX: addc 4, 4, 6 190 ; CHECK-BE-NOVSX-NEXT: adde 3, 3, 5 191 ; CHECK-BE-NOVSX: blr 192 } 193 194 195 ; Callsites for the routines defined above. 196 ; Ensure the parameters are loaded in the same order that is expected by the 197 ; callee. See comments for individual functions above for details on registers 198 ; used for parameters. 199 define <1 x i128> @call_v1i128_increment_by_one() nounwind { 200 %tmp = load <1 x i128>, <1 x i128>* @x, align 16 201 %ret = call <1 x i128> @v1i128_increment_by_one(<1 x i128> %tmp) 202 ret <1 x i128> %ret 203 204 ; CHECK-LE-LABEL: @call_v1i128_increment_by_one 205 ; CHECK-LE: lvx 2, {{[0-9]+}}, {{[0-9]+}} 206 ; CHECK-LE: bl v1i128_increment_by_one 207 ; CHECK-LE: blr 208 209 ; CHECK-P9-LABEL: @call_v1i128_increment_by_one 210 ; CHECK-P9: lxv 211 ; CHECK-P9: bl v1i128_increment_by_one 212 ; CHECK-P9: blr 213 214 ; CHECK-BE-LABEL: @call_v1i128_increment_by_one 215 ; CHECK-BE: lxvw4x 34, {{[0-9]+}}, {{[0-9]+}} 216 ; CHECK-BE-NOT: xxswapd 34, {{[0-9]+}} 217 ; CHECK-BE: bl v1i128_increment_by_one 218 ; CHECK-BE: blr 219 220 ; CHECK-NOVSX-LABEL: @call_v1i128_increment_by_one 221 ; CHECK-NOVSX: lvx 2, {{[0-9]+}}, {{[0-9]+}} 222 ; CHECK-NOVSX-NOT: xxswapd {{[0-9]+}}, {{[0-9]+}} 223 ; CHECK-NOVSX: bl v1i128_increment_by_one 224 ; CHECK-NOVSX: blr 225 } 226 227 define <1 x i128> @call_v1i128_increment_by_val() nounwind { 228 %tmp = load <1 x i128>, <1 x i128>* @x, align 16 229 %tmp2 = load <1 x i128>, <1 x i128>* @y, align 16 230 %ret = call <1 x i128> @v1i128_increment_by_val(<1 x i128> %tmp, <1 x i128> %tmp2) 231 ret <1 x i128> %ret 232 233 ; CHECK-LE-LABEL: @call_v1i128_increment_by_val 234 ; CHECK-LE: lvx 2, {{[0-9]+}}, {{[0-9]+}} 235 ; CHECK-LE: lvx 3, {{[0-9]+}}, {{[0-9]+}} 236 ; CHECK-LE: bl v1i128_increment_by_val 237 ; CHECK-LE: blr 238 239 ; CHECK-P9-LABEL: @call_v1i128_increment_by_val 240 ; CHECK-P9-DAG: lxvx v2 241 ; CHECK-P9-DAG: lxvx v3 242 ; CHECK-P9: bl v1i128_increment_by_val 243 ; CHECK-P9: blr 244 245 ; CHECK-BE-LABEL: @call_v1i128_increment_by_val 246 247 248 ; CHECK-BE-DAG: lxvw4x 35, {{[0-9]+}}, {{[0-9]+}} 249 ; CHECK-BE-NOT: xxswapd 34, {{[0-9]+}} 250 ; CHECK-BE-NOT: xxswapd 35, {{[0-9]+}} 251 ; CHECK-BE: bl v1i128_increment_by_val 252 ; CHECK-BE: blr 253 254 ; CHECK-NOVSX-LABEL: @call_v1i128_increment_by_val 255 ; CHECK-NOVSX-DAG: lvx 2, {{[0-9]+}}, {{[0-9]+}} 256 ; CHECK-NOVSX-DAG: lvx 3, {{[0-9]+}}, {{[0-9]+}} 257 ; CHECK-NOVSX-NOT: xxswapd 34, {{[0-9]+}} 258 ; CHECK-NOVSX-NOT: xxswapd 35, {{[0-9]+}} 259 ; CHECK-NOVSX: bl v1i128_increment_by_val 260 ; CHECK-NOVSX: blr 261 262 } 263 264 define i128 @call_i128_increment_by_one() nounwind { 265 %tmp = load i128, i128* @a, align 16 266 %ret = call i128 @i128_increment_by_one(i128 %tmp) 267 ret i128 %ret 268 ; %ret4 = call i128 @i128_increment_by_val(i128 %tmp2, i128 %tmp2) 269 ; CHECK-LE-LABEL: @call_i128_increment_by_one 270 ; CHECK-LE-DAG: ld 3, 0([[BASEREG:[0-9]+]]) 271 ; CHECK-LE-DAG: ld 4, 8([[BASEREG]]) 272 ; CHECK-LE: bl i128_increment_by_one 273 ; CHECK-LE: blr 274 275 ; CHECK-BE-LABEL: @call_i128_increment_by_one 276 ; CHECK-BE-DAG: ld 3, 0([[BASEREG:[0-9]+]]) 277 ; CHECK-BE-DAG: ld 4, 8([[BASEREG]]) 278 ; CHECK-BE: bl i128_increment_by_one 279 ; CHECK-BE: blr 280 281 ; CHECK-NOVSX-LABEL: @call_i128_increment_by_one 282 ; CHECK-NOVSX-DAG: ld 3, 0([[BASEREG:[0-9]+]]) 283 ; CHECK-NOVSX-DAG: ld 4, 8([[BASEREG]]) 284 ; CHECK-NOVSX: bl i128_increment_by_one 285 ; CHECK-NOVSX: blr 286 } 287 288 define i128 @call_i128_increment_by_val() nounwind { 289 %tmp = load i128, i128* @a, align 16 290 %tmp2 = load i128, i128* @b, align 16 291 %ret = call i128 @i128_increment_by_val(i128 %tmp, i128 %tmp2) 292 ret i128 %ret 293 ; CHECK-LE-LABEL: @call_i128_increment_by_val 294 ; CHECK-LE-DAG: ld 3, 0([[P1BASEREG:[0-9]+]]) 295 ; CHECK-LE-DAG: ld 4, 8([[P1BASEREG]]) 296 ; CHECK-LE-DAG: ld 5, 0([[P2BASEREG:[0-9]+]]) 297 ; CHECK-LE-DAG: ld 6, 8([[P2BASEREG]]) 298 ; CHECK-LE: bl i128_increment_by_val 299 ; CHECK-LE: blr 300 301 ; CHECK-BE-LABEL: @call_i128_increment_by_val 302 ; CHECK-BE-DAG: ld 3, 0([[P1BASEREG:[0-9]+]]) 303 ; CHECK-BE-DAG: ld 4, 8([[P1BASEREG]]) 304 ; CHECK-BE-DAG: ld 5, 0([[P2BASEREG:[0-9]+]]) 305 ; CHECK-BE-DAG: ld 6, 8([[P2BASEREG]]) 306 ; CHECK-BE: bl i128_increment_by_val 307 ; CHECK-BE: blr 308 309 ; CHECK-NOVSX-LABEL: @call_i128_increment_by_val 310 ; CHECK-NOVSX-DAG: ld 3, 0([[P1BASEREG:[0-9]+]]) 311 ; CHECK-NOVSX-DAG: ld 4, 8([[P1BASEREG]]) 312 ; CHECK-NOVSX-DAG: ld 5, 0([[P2BASEREG:[0-9]+]]) 313 ; CHECK-NOVSX-DAG: ld 6, 8([[P2BASEREG]]) 314 ; CHECK-NOVSX: bl i128_increment_by_val 315 ; CHECK-NOVSX: blr 316 } 317 318 319