1 ; RUN: llc -march=mips -mcpu=mips32 < %s | FileCheck %s -check-prefix=ALL -check-prefix=32 2 ; RUN: llc -march=mips -mcpu=mips32r2 < %s | FileCheck %s -check-prefix=ALL -check-prefix=32 3 ; RUN: llc -march=mips -mcpu=mips32r6 < %s | FileCheck %s -check-prefix=ALL -check-prefix=32R6 4 ; RUN: llc -march=mips -mcpu=mips32 -mattr=dsp < %s | FileCheck %s -check-prefix=DSP 5 ; RUN: llc -march=mips -mcpu=mips64 < %s | FileCheck %s -check-prefix=ALL -check-prefix=64 6 ; RUN: llc -march=mips -mcpu=mips64r2 < %s | FileCheck %s -check-prefix=ALL -check-prefix=64 7 ; RUN: llc -march=mips -mcpu=mips64r6 < %s | FileCheck %s -check-prefix=ALL -check-prefix=64R6 8 9 ; FIXME: The MIPS16 test should check its output 10 ; RUN: llc -march=mips -mcpu=mips16 < %s 11 12 ; ALL-LABEL: madd1: 13 14 ; 32-DAG: sra $[[T0:[0-9]+]], $6, 31 15 ; 32-DAG: mtlo $6 16 ; 32-DAG: [[m:m]]add ${{[45]}}, ${{[45]}} 17 ; 32-DAG: [[m]]fhi $2 18 ; 32-DAG: [[m]]flo $3 19 20 ; DSP-DAG: sra $[[T0:[0-9]+]], $6, 31 21 ; DSP-DAG: mtlo $[[AC:ac[0-3]+]], $6 22 ; DSP-DAG: madd $[[AC]], ${{[45]}}, ${{[45]}} 23 ; DSP-DAG: mfhi $2, $[[AC]] 24 ; DSP-DAG: mflo $3, $[[AC]] 25 26 ; 32R6-DAG: mul $[[T0:[0-9]+]], ${{[45]}}, ${{[45]}} 27 ; 32R6-DAG: addu $[[T1:[0-9]+]], $[[T0]], $6 28 ; 32R6-DAG: sltu $[[T2:[0-9]+]], $[[T1]], $6 29 ; 32R6-DAG: sra $[[T3:[0-9]+]], $6, 31 30 ; 32R6-DAG: addu $[[T4:[0-9]+]], $[[T2]], $[[T3]] 31 ; 32R6-DAG: muh $[[T5:[0-9]+]], ${{[45]}}, ${{[45]}} 32 ; 32R6-DAG: addu $2, $[[T5]], $[[T4]] 33 34 ; 64-DAG: sll $[[T0:[0-9]+]], $4, 0 35 ; 64-DAG: sll $[[T1:[0-9]+]], $5, 0 36 ; 64-DAG: d[[m:m]]ult $[[T1]], $[[T0]] 37 ; 64-DAG: [[m]]flo $[[T2:[0-9]+]] 38 ; 64-DAG: sll $[[T3:[0-9]+]], $6, 0 39 ; 64-DAG: daddu $2, $[[T2]], $[[T3]] 40 41 ; 64R6-DAG: sll $[[T0:[0-9]+]], $4, 0 42 ; 64R6-DAG: sll $[[T1:[0-9]+]], $5, 0 43 ; 64R6-DAG: dmul $[[T2:[0-9]+]], $[[T1]], $[[T0]] 44 ; 64R6-DAG: sll $[[T3:[0-9]+]], $6, 0 45 ; 64R6-DAG: daddu $2, $[[T2]], $[[T3]] 46 47 define i64 @madd1(i32 %a, i32 %b, i32 %c) nounwind readnone { 48 entry: 49 %conv = sext i32 %a to i64 50 %conv2 = sext i32 %b to i64 51 %mul = mul nsw i64 %conv2, %conv 52 %conv4 = sext i32 %c to i64 53 %add = add nsw i64 %mul, %conv4 54 ret i64 %add 55 } 56 57 ; ALL-LABEL: madd2: 58 59 ; FIXME: We don't really need this instruction 60 ; 32-DAG: addiu $[[T0:[0-9]+]], $zero, 0 61 ; 32-DAG: mtlo $6 62 ; 32-DAG: [[m:m]]addu ${{[45]}}, ${{[45]}} 63 ; 32-DAG: [[m]]fhi $2 64 ; 32-DAG: [[m]]flo $3 65 66 ; DSP-DAG: addiu $[[T0:[0-9]+]], $zero, 0 67 ; DSP-DAG: mtlo $[[AC:ac[0-3]+]], $6 68 ; DSP-DAG: maddu $[[AC]], ${{[45]}}, ${{[45]}} 69 ; DSP-DAG: mfhi $2, $[[AC]] 70 ; DSP-DAG: mflo $3, $[[AC]] 71 72 ; 32R6-DAG: mul $[[T0:[0-9]+]], ${{[45]}}, ${{[45]}} 73 ; 32R6-DAG: addu $[[T1:[0-9]+]], $[[T0]], $6 74 ; 32R6-DAG: sltu $[[T2:[0-9]+]], $[[T1]], $6 75 ; FIXME: There's a redundant move here. We should remove it 76 ; 32R6-DAG: muhu $[[T3:[0-9]+]], ${{[45]}}, ${{[45]}} 77 ; 32R6-DAG: addu $2, $[[T3]], $[[T2]] 78 79 ; 64-DAG: dsll $[[T0:[0-9]+]], $4, 32 80 ; 64-DAG: dsrl $[[T1:[0-9]+]], $[[T0]], 32 81 ; 64-DAG: dsll $[[T2:[0-9]+]], $5, 32 82 ; 64-DAG: dsrl $[[T3:[0-9]+]], $[[T2]], 32 83 ; 64-DAG: d[[m:m]]ult $[[T3]], $[[T1]] 84 ; 64-DAG: [[m]]flo $[[T4:[0-9]+]] 85 ; 64-DAG: dsll $[[T5:[0-9]+]], $6, 32 86 ; 64-DAG: dsrl $[[T6:[0-9]+]], $[[T5]], 32 87 ; 64-DAG: daddu $2, $[[T4]], $[[T6]] 88 89 ; 64R6-DAG: dsll $[[T0:[0-9]+]], $4, 32 90 ; 64R6-DAG: dsrl $[[T1:[0-9]+]], $[[T0]], 32 91 ; 64R6-DAG: dsll $[[T2:[0-9]+]], $5, 32 92 ; 64R6-DAG: dsrl $[[T3:[0-9]+]], $[[T2]], 32 93 ; 64R6-DAG: dmul $[[T4:[0-9]+]], $[[T3]], $[[T1]] 94 ; 64R6-DAG: dsll $[[T5:[0-9]+]], $6, 32 95 ; 64R6-DAG: dsrl $[[T6:[0-9]+]], $[[T5]], 32 96 ; 64R6-DAG: daddu $2, $[[T4]], $[[T6]] 97 98 define i64 @madd2(i32 %a, i32 %b, i32 %c) nounwind readnone { 99 entry: 100 %conv = zext i32 %a to i64 101 %conv2 = zext i32 %b to i64 102 %mul = mul nsw i64 %conv2, %conv 103 %conv4 = zext i32 %c to i64 104 %add = add nsw i64 %mul, %conv4 105 ret i64 %add 106 } 107 108 ; ALL-LABEL: madd3: 109 110 ; 32-DAG: mthi $6 111 ; 32-DAG: mtlo $7 112 ; 32-DAG: [[m:m]]add ${{[45]}}, ${{[45]}} 113 ; 32-DAG: [[m]]fhi $2 114 ; 32-DAG: [[m]]flo $3 115 116 ; DSP-DAG: mthi $[[AC:ac[0-3]+]], $6 117 ; DSP-DAG: mtlo $[[AC]], $7 118 ; DSP-DAG: madd $[[AC]], ${{[45]}}, ${{[45]}} 119 ; DSP-DAG: mfhi $2, $[[AC]] 120 ; DSP-DAG: mflo $3, $[[AC]] 121 122 ; 32R6-DAG: mul $[[T0:[0-9]+]], ${{[45]}}, ${{[45]}} 123 ; 32R6-DAG: addu $[[T1:[0-9]+]], $[[T0]], $7 124 ; 32R6-DAG: sltu $[[T2:[0-9]+]], $[[T1]], $7 125 ; 32R6-DAG: addu $[[T4:[0-9]+]], $[[T2]], $6 126 ; 32R6-DAG: muh $[[T5:[0-9]+]], ${{[45]}}, ${{[45]}} 127 ; 32R6-DAG: addu $2, $[[T5]], $[[T4]] 128 129 ; 64-DAG: sll $[[T0:[0-9]+]], $4, 0 130 ; 64-DAG: sll $[[T1:[0-9]+]], $5, 0 131 ; 64-DAG: d[[m:m]]ult $[[T1]], $[[T0]] 132 ; 64-DAG: [[m]]flo $[[T2:[0-9]+]] 133 ; 64-DAG: daddu $2, $[[T2]], $6 134 135 ; 64R6-DAG: sll $[[T0:[0-9]+]], $4, 0 136 ; 64R6-DAG: sll $[[T1:[0-9]+]], $5, 0 137 ; 64R6-DAG: dmul $[[T2:[0-9]+]], $[[T1]], $[[T0]] 138 ; 64R6-DAG: daddu $2, $[[T2]], $6 139 140 define i64 @madd3(i32 %a, i32 %b, i64 %c) nounwind readnone { 141 entry: 142 %conv = sext i32 %a to i64 143 %conv2 = sext i32 %b to i64 144 %mul = mul nsw i64 %conv2, %conv 145 %add = add nsw i64 %mul, %c 146 ret i64 %add 147 } 148 149 ; ALL-LABEL: msub1: 150 151 ; 32-DAG: sra $[[T0:[0-9]+]], $6, 31 152 ; 32-DAG: mtlo $6 153 ; 32-DAG: [[m:m]]sub ${{[45]}}, ${{[45]}} 154 ; 32-DAG: [[m]]fhi $2 155 ; 32-DAG: [[m]]flo $3 156 157 ; DSP-DAG: sra $[[T0:[0-9]+]], $6, 31 158 ; DSP-DAG: mtlo $[[AC:ac[0-3]+]], $6 159 ; DSP-DAG: msub $[[AC]], ${{[45]}}, ${{[45]}} 160 ; DSP-DAG: mfhi $2, $[[AC]] 161 ; DSP-DAG: mflo $3, $[[AC]] 162 163 ; 32R6-DAG: muh $[[T0:[0-9]+]], ${{[45]}}, ${{[45]}} 164 ; 32R6-DAG: mul $[[T1:[0-9]+]], ${{[45]}}, ${{[45]}} 165 ; 32R6-DAG: sltu $[[T3:[0-9]+]], $6, $[[T1]] 166 ; 32R6-DAG: addu $[[T4:[0-9]+]], $[[T3]], $[[T0]] 167 ; 32R6-DAG: sra $[[T5:[0-9]+]], $6, 31 168 ; 32R6-DAG: subu $2, $[[T5]], $[[T4]] 169 ; 32R6-DAG: subu $3, $6, $[[T1]] 170 171 ; 64-DAG: sll $[[T0:[0-9]+]], $4, 0 172 ; 64-DAG: sll $[[T1:[0-9]+]], $5, 0 173 ; 64-DAG: d[[m:m]]ult $[[T1]], $[[T0]] 174 ; 64-DAG: [[m]]flo $[[T2:[0-9]+]] 175 ; 64-DAG: sll $[[T3:[0-9]+]], $6, 0 176 ; 64-DAG: dsubu $2, $[[T3]], $[[T2]] 177 178 ; 64R6-DAG: sll $[[T0:[0-9]+]], $4, 0 179 ; 64R6-DAG: sll $[[T1:[0-9]+]], $5, 0 180 ; 64R6-DAG: dmul $[[T2:[0-9]+]], $[[T1]], $[[T0]] 181 ; 64R6-DAG: sll $[[T3:[0-9]+]], $6, 0 182 ; 64R6-DAG: dsubu $2, $[[T3]], $[[T2]] 183 184 define i64 @msub1(i32 %a, i32 %b, i32 %c) nounwind readnone { 185 entry: 186 %conv = sext i32 %c to i64 187 %conv2 = sext i32 %a to i64 188 %conv4 = sext i32 %b to i64 189 %mul = mul nsw i64 %conv4, %conv2 190 %sub = sub nsw i64 %conv, %mul 191 ret i64 %sub 192 } 193 194 ; ALL-LABEL: msub2: 195 196 ; FIXME: We don't really need this instruction 197 ; 32-DAG: addiu $[[T0:[0-9]+]], $zero, 0 198 ; 32-DAG: mtlo $6 199 ; 32-DAG: [[m:m]]subu ${{[45]}}, ${{[45]}} 200 ; 32-DAG: [[m]]fhi $2 201 ; 32-DAG: [[m]]flo $3 202 203 ; DSP-DAG: addiu $[[T0:[0-9]+]], $zero, 0 204 ; DSP-DAG: mtlo $[[AC:ac[0-3]+]], $6 205 ; DSP-DAG: msubu $[[AC]], ${{[45]}}, ${{[45]}} 206 ; DSP-DAG: mfhi $2, $[[AC]] 207 ; DSP-DAG: mflo $3, $[[AC]] 208 209 ; 32R6-DAG: muhu $[[T0:[0-9]+]], ${{[45]}}, ${{[45]}} 210 ; 32R6-DAG: mul $[[T1:[0-9]+]], ${{[45]}}, ${{[45]}} 211 212 ; 32R6-DAG: sltu $[[T2:[0-9]+]], $6, $[[T1]] 213 ; 32R6-DAG: addu $[[T3:[0-9]+]], $[[T2]], $[[T0]] 214 ; 32R6-DAG: negu $2, $[[T3]] 215 ; 32R6-DAG: subu $3, $6, $[[T1]] 216 217 ; 64-DAG: dsll $[[T0:[0-9]+]], $4, 32 218 ; 64-DAG: dsrl $[[T1:[0-9]+]], $[[T0]], 32 219 ; 64-DAG: dsll $[[T2:[0-9]+]], $5, 32 220 ; 64-DAG: dsrl $[[T3:[0-9]+]], $[[T2]], 32 221 ; 64-DAG: d[[m:m]]ult $[[T3]], $[[T1]] 222 ; 64-DAG: [[m]]flo $[[T4:[0-9]+]] 223 ; 64-DAG: dsll $[[T5:[0-9]+]], $6, 32 224 ; 64-DAG: dsrl $[[T6:[0-9]+]], $[[T5]], 32 225 ; 64-DAG: dsubu $2, $[[T6]], $[[T4]] 226 227 ; 64R6-DAG: dsll $[[T0:[0-9]+]], $4, 32 228 ; 64R6-DAG: dsrl $[[T1:[0-9]+]], $[[T0]], 32 229 ; 64R6-DAG: dsll $[[T2:[0-9]+]], $5, 32 230 ; 64R6-DAG: dsrl $[[T3:[0-9]+]], $[[T2]], 32 231 ; 64R6-DAG: dmul $[[T4:[0-9]+]], $[[T3]], $[[T1]] 232 ; 64R6-DAG: dsll $[[T5:[0-9]+]], $6, 32 233 ; 64R6-DAG: dsrl $[[T6:[0-9]+]], $[[T5]], 32 234 ; 64R6-DAG: dsubu $2, $[[T6]], $[[T4]] 235 236 define i64 @msub2(i32 %a, i32 %b, i32 %c) nounwind readnone { 237 entry: 238 %conv = zext i32 %c to i64 239 %conv2 = zext i32 %a to i64 240 %conv4 = zext i32 %b to i64 241 %mul = mul nsw i64 %conv4, %conv2 242 %sub = sub nsw i64 %conv, %mul 243 ret i64 %sub 244 } 245 246 ; ALL-LABEL: msub3: 247 248 ; FIXME: We don't really need this instruction 249 ; 32-DAG: mthi $6 250 ; 32-DAG: mtlo $7 251 ; 32-DAG: [[m:m]]sub ${{[45]}}, ${{[45]}} 252 ; 32-DAG: [[m]]fhi $2 253 ; 32-DAG: [[m]]flo $3 254 255 ; DSP-DAG: addiu $[[T0:[0-9]+]], $zero, 0 256 ; DSP-DAG: mtlo $[[AC:ac[0-3]+]], $6 257 ; DSP-DAG: msub $[[AC]], ${{[45]}}, ${{[45]}} 258 ; DSP-DAG: mfhi $2, $[[AC]] 259 ; DSP-DAG: mflo $3, $[[AC]] 260 261 ; 32R6-DAG: muh $[[T0:[0-9]+]], ${{[45]}}, ${{[45]}} 262 ; 32R6-DAG: mul $[[T1:[0-9]+]], ${{[45]}}, ${{[45]}} 263 ; 32R6-DAG: sltu $[[T2:[0-9]+]], $7, $[[T1]] 264 ; 32R6-DAG: addu $[[T3:[0-9]+]], $[[T2]], $[[T0]] 265 ; 32R6-DAG: subu $2, $6, $[[T3]] 266 ; 32R6-DAG: subu $3, $7, $[[T1]] 267 268 ; 64-DAG: sll $[[T0:[0-9]+]], $4, 0 269 ; 64-DAG: sll $[[T1:[0-9]+]], $5, 0 270 ; 64-DAG: d[[m:m]]ult $[[T1]], $[[T0]] 271 ; 64-DAG: [[m]]flo $[[T2:[0-9]+]] 272 ; 64-DAG: dsubu $2, $6, $[[T2]] 273 274 ; 64R6-DAG: sll $[[T0:[0-9]+]], $4, 0 275 ; 64R6-DAG: sll $[[T1:[0-9]+]], $5, 0 276 ; 64R6-DAG: dmul $[[T2:[0-9]+]], $[[T1]], $[[T0]] 277 ; 64R6-DAG: dsubu $2, $6, $[[T2]] 278 279 define i64 @msub3(i32 %a, i32 %b, i64 %c) nounwind readnone { 280 entry: 281 %conv = sext i32 %a to i64 282 %conv3 = sext i32 %b to i64 283 %mul = mul nsw i64 %conv3, %conv 284 %sub = sub nsw i64 %c, %mul 285 ret i64 %sub 286 } 287