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