1 ; RUN: llc < %s -mtriple=powerpc64le-unknown-linux-gnu -mcpu=pwr9 -verify-machineinstrs | FileCheck %s 2 ; RUN: llc < %s -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr9 -verify-machineinstrs | FileCheck %s 3 ; RUN: llc < %s -mtriple=powerpc64le-unknown-linux-gnu -mcpu=pwr8 | FileCheck %s -check-prefix=CHECK-PWR8 -implicit-check-not mod[us][wd] 4 5 @mod_resultsw = common local_unnamed_addr global i32 0, align 4 6 @mod_resultud = common local_unnamed_addr global i64 0, align 8 7 @div_resultsw = common local_unnamed_addr global i32 0, align 4 8 @mod_resultuw = common local_unnamed_addr global i32 0, align 4 9 @div_resultuw = common local_unnamed_addr global i32 0, align 4 10 @div_resultsd = common local_unnamed_addr global i64 0, align 8 11 @mod_resultsd = common local_unnamed_addr global i64 0, align 8 12 @div_resultud = common local_unnamed_addr global i64 0, align 8 13 14 ; Function Attrs: norecurse nounwind 15 define void @modulo_sw(i32 signext %a, i32 signext %b) local_unnamed_addr { 16 entry: 17 %rem = srem i32 %a, %b 18 store i32 %rem, i32* @mod_resultsw, align 4 19 ret void 20 ; CHECK-LABEL: modulo_sw 21 ; CHECK: modsw {{[0-9]+}}, 3, 4 22 ; CHECK: blr 23 ; CHECK-PWR8-LABEL: modulo_sw 24 ; CHECK-PWR8: div 25 ; CHECK-PWR8: mull 26 ; CHECK-PWR8: sub 27 ; CHECK-PWR8: blr 28 } 29 30 ; Function Attrs: norecurse nounwind readnone 31 define zeroext i32 @modulo_uw(i32 zeroext %a, i32 zeroext %b) local_unnamed_addr { 32 entry: 33 %rem = urem i32 %a, %b 34 ret i32 %rem 35 ; CHECK-LABEL: modulo_uw 36 ; CHECK: moduw {{[0-9]+}}, 3, 4 37 ; CHECK: blr 38 ; CHECK-PWR8-LABEL: modulo_uw 39 ; CHECK-PWR8: div 40 ; CHECK-PWR8: mull 41 ; CHECK-PWR8: sub 42 ; CHECK-PWR8: blr 43 } 44 45 ; Function Attrs: norecurse nounwind readnone 46 define i64 @modulo_sd(i64 %a, i64 %b) local_unnamed_addr { 47 entry: 48 %rem = srem i64 %a, %b 49 ret i64 %rem 50 ; CHECK-LABEL: modulo_sd 51 ; CHECK: modsd {{[0-9]+}}, 3, 4 52 ; CHECK: blr 53 ; CHECK-PWR8-LABEL: modulo_sd 54 ; CHECK-PWR8: div 55 ; CHECK-PWR8: mull 56 ; CHECK-PWR8: sub 57 ; CHECK-PWR8: blr 58 } 59 60 ; Function Attrs: norecurse nounwind 61 define void @modulo_ud(i64 %a, i64 %b) local_unnamed_addr { 62 entry: 63 %rem = urem i64 %a, %b 64 store i64 %rem, i64* @mod_resultud, align 8 65 ret void 66 ; CHECK-LABEL: modulo_ud 67 ; CHECK: modud {{[0-9]+}}, 3, 4 68 ; CHECK: blr 69 ; CHECK-PWR8-LABEL: modulo_ud 70 ; CHECK-PWR8: div 71 ; CHECK-PWR8: mull 72 ; CHECK-PWR8: sub 73 ; CHECK-PWR8: blr 74 } 75 76 ; Function Attrs: norecurse nounwind 77 define void @modulo_div_sw(i32 signext %a, i32 signext %b) local_unnamed_addr { 78 entry: 79 %rem = srem i32 %a, %b 80 store i32 %rem, i32* @mod_resultsw, align 4 81 %div = sdiv i32 %a, %b 82 store i32 %div, i32* @div_resultsw, align 4 83 ret void 84 ; CHECK-LABEL: modulo_div_sw 85 ; CHECK-NOT: modsw 86 ; CHECK: div 87 ; CHECK-NOT: modsw 88 ; CHECK: mull 89 ; CHECK-NOT: modsw 90 ; CHECK: sub 91 ; CHECK: blr 92 ; CHECK-PWR8-LABEL: modulo_div_sw 93 ; CHECK-PWR8: div 94 ; CHECK-PWR8: mull 95 ; CHECK-PWR8: sub 96 ; CHECK-PWR8: blr 97 } 98 99 ; Function Attrs: norecurse nounwind 100 define void @modulo_div_abc_sw(i32 signext %a, i32 signext %b, i32 signext %c) local_unnamed_addr { 101 entry: 102 %rem = srem i32 %a, %c 103 store i32 %rem, i32* @mod_resultsw, align 4 104 %div = sdiv i32 %b, %c 105 store i32 %div, i32* @div_resultsw, align 4 106 ret void 107 ; CHECK-LABEL: modulo_div_abc_sw 108 ; CHECK: modsw {{[0-9]+}}, 3, 5 109 ; CHECK: blr 110 ; CHECK-PWR8-LABEL: modulo_div_abc_sw 111 ; CHECK-PWR8: div 112 ; CHECK-PWR8: mull 113 ; CHECK-PWR8: sub 114 ; CHECK-PWR8: blr 115 } 116 117 ; Function Attrs: norecurse nounwind 118 define void @modulo_div_uw(i32 zeroext %a, i32 zeroext %b) local_unnamed_addr { 119 entry: 120 %rem = urem i32 %a, %b 121 store i32 %rem, i32* @mod_resultuw, align 4 122 %div = udiv i32 %a, %b 123 store i32 %div, i32* @div_resultuw, align 4 124 ret void 125 ; CHECK-LABEL: modulo_div_uw 126 ; CHECK-NOT: modsw 127 ; CHECK: div 128 ; CHECK-NOT: modsw 129 ; CHECK: mull 130 ; CHECK-NOT: modsw 131 ; CHECK: sub 132 ; CHECK: blr 133 ; CHECK-PWR8-LABEL: modulo_div_uw 134 ; CHECK-PWR8: div 135 ; CHECK-PWR8: mull 136 ; CHECK-PWR8: sub 137 ; CHECK-PWR8: blr 138 } 139 140 ; Function Attrs: norecurse nounwind 141 define void @modulo_div_swuw(i32 signext %a, i32 signext %b) local_unnamed_addr { 142 entry: 143 %rem = srem i32 %a, %b 144 store i32 %rem, i32* @mod_resultsw, align 4 145 %div = udiv i32 %a, %b 146 store i32 %div, i32* @div_resultsw, align 4 147 ret void 148 ; CHECK-LABEL: modulo_div_swuw 149 ; CHECK: modsw {{[0-9]+}}, 3, 4 150 ; CHECK: blr 151 ; CHECK-PWR8-LABEL: modulo_div_swuw 152 ; CHECK-PWR8: div 153 ; CHECK-PWR8: mull 154 ; CHECK-PWR8: sub 155 ; CHECK-PWR8: blr 156 } 157 158 ; Function Attrs: norecurse nounwind 159 define void @modulo_div_udsd(i64 %a, i64 %b) local_unnamed_addr { 160 entry: 161 %rem = urem i64 %a, %b 162 store i64 %rem, i64* @mod_resultud, align 8 163 %div = sdiv i64 %a, %b 164 store i64 %div, i64* @div_resultsd, align 8 165 ret void 166 ; CHECK-LABEL: modulo_div_udsd 167 ; CHECK: modud {{[0-9]+}}, 3, 4 168 ; CHECK: blr 169 ; CHECK-PWR8-LABEL: modulo_div_udsd 170 ; CHECK-PWR8: div 171 ; CHECK-PWR8: mull 172 ; CHECK-PWR8: sub 173 ; CHECK-PWR8: blr 174 } 175 176 ; Function Attrs: norecurse nounwind 177 define void @modulo_const32_sw(i32 signext %a) local_unnamed_addr { 178 entry: 179 %rem = srem i32 %a, 32 180 store i32 %rem, i32* @mod_resultsw, align 4 181 ret void 182 ; CHECK-LABEL: modulo_const32_sw 183 ; CHECK-NOT: modsw 184 ; CHECK: srawi 185 ; CHECK-NOT: modsw 186 ; CHECK: addze 187 ; CHECK-NOT: modsw 188 ; CHECK: slwi 189 ; CHECK-NOT: modsw 190 ; CHECK: subf 191 ; CHECK-NOT: modsw 192 ; CHECK: blr 193 ; CHECK-PWR8-LABEL: modulo_const32_sw 194 ; CHECK-PWR8: srawi 195 ; CHECK-PWR8: addze 196 ; CHECK-PWR8: slwi 197 ; CHECK-PWR8: subf 198 ; CHECK-PWR8: blr 199 } 200 201 ; Function Attrs: norecurse nounwind readnone 202 define signext i32 @modulo_const3_sw(i32 signext %a) local_unnamed_addr { 203 entry: 204 %rem = srem i32 %a, 3 205 ret i32 %rem 206 ; CHECK-LABEL: modulo_const3_sw 207 ; CHECK-NOT: modsw 208 ; CHECK: mull 209 ; CHECK-NOT: modsw 210 ; CHECK: sub 211 ; CHECK-NOT: modsw 212 ; CHECK: blr 213 ; CHECK-PWR8-LABEL: modulo_const3_sw 214 ; CHECK-PWR8: mull 215 ; CHECK-PWR8: sub 216 ; CHECK-PWR8: blr 217 } 218 219 ; Function Attrs: norecurse nounwind readnone 220 define signext i32 @const2_modulo_sw(i32 signext %a) local_unnamed_addr { 221 entry: 222 %rem = srem i32 2, %a 223 ret i32 %rem 224 ; CHECK-LABEL: const2_modulo_sw 225 ; CHECK: modsw {{[0-9]+}}, {{[0-9]+}}, 3 226 ; CHECK: blr 227 ; CHECK-PWR8-LABEL: const2_modulo_sw 228 ; CHECK-PWR8: div 229 ; CHECK-PWR8: mull 230 ; CHECK-PWR8: sub 231 ; CHECK-PWR8: blr 232 } 233 234 ; Function Attrs: norecurse nounwind 235 ; FIXME On power 9 this test will still produce modsw because the divide is in 236 ; a different block than the remainder. Due to the nature of the SDAG we cannot 237 ; see the div in the other block. 238 define void @blocks_modulo_div_sw(i32 signext %a, i32 signext %b, i32 signext %c) local_unnamed_addr { 239 entry: 240 %div = sdiv i32 %a, %b 241 store i32 %div, i32* @div_resultsw, align 4 242 %cmp = icmp sgt i32 %c, 0 243 br i1 %cmp, label %if.then, label %if.end 244 245 if.then: ; preds = %entry 246 %rem = srem i32 %a, %b 247 store i32 %rem, i32* @mod_resultsw, align 4 248 br label %if.end 249 250 if.end: ; preds = %if.then, %entry 251 ret void 252 ; CHECK-LABEL: blocks_modulo_div_sw 253 ; CHECK: div 254 ; CHECK: modsw {{[0-9]+}}, 3, 4 255 ; CHECK: blr 256 ; CHECK-PWR8-LABEL: blocks_modulo_div_sw 257 ; CHECK-PWR8: div 258 ; CHECK-PWR8: mull 259 ; CHECK-PWR8: sub 260 ; CHECK-PWR8: blr 261 } 262 263 264