Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 //===- subzero/src/IceTargetLoweringARM32.cpp - ARM32 lowering ------------===// | 1 //===- subzero/src/IceTargetLoweringARM32.cpp - ARM32 lowering ------------===// |
| 2 // | 2 // |
| 3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
| 4 // | 4 // |
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 // | 9 // |
| 10 // This file implements the TargetLoweringARM32 class, which consists almost | 10 // This file implements the TargetLoweringARM32 class, which consists almost |
| (...skipping 1085 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1096 // TODO(jvoung): Should be able to flip Src0 and Src1 if it is easier | 1096 // TODO(jvoung): Should be able to flip Src0 and Src1 if it is easier |
| 1097 // to legalize Src0 to flex or Src1 to flex and there is a reversible | 1097 // to legalize Src0 to flex or Src1 to flex and there is a reversible |
| 1098 // instruction. E.g., reverse subtract with immediate, register vs | 1098 // instruction. E.g., reverse subtract with immediate, register vs |
| 1099 // register, immediate. | 1099 // register, immediate. |
| 1100 // Or it may be the case that the operands aren't swapped, but the | 1100 // Or it may be the case that the operands aren't swapped, but the |
| 1101 // bits can be flipped and a different operation applied. | 1101 // bits can be flipped and a different operation applied. |
| 1102 // E.g., use BIC (bit clear) instead of AND for some masks. | 1102 // E.g., use BIC (bit clear) instead of AND for some masks. |
| 1103 Operand *Src0 = Inst->getSrc(0); | 1103 Operand *Src0 = Inst->getSrc(0); |
| 1104 Operand *Src1 = Inst->getSrc(1); | 1104 Operand *Src1 = Inst->getSrc(1); |
| 1105 if (Dest->getType() == IceType_i64) { | 1105 if (Dest->getType() == IceType_i64) { |
| 1106 // These helper-call-involved instructions are lowered in this | |
| 1107 // separate switch. This is because we would otherwise assume that | |
| 1108 // we need to legalize Src0 to Src0RLo and Src0Hi. However, those go unused | |
| 1109 // with helper calls, and such unused/redundant instructions will fail | |
| 1110 // liveness analysis under -Om1 setting. | |
|
Jim Stichnoth
2015/07/07 11:50:29
Hmm, I wonder if that Om1 validation check should
| |
| 1111 switch (Inst->getOp()) { | |
| 1112 default: | |
| 1113 break; | |
| 1114 case InstArithmetic::Udiv: | |
| 1115 case InstArithmetic::Sdiv: | |
| 1116 case InstArithmetic::Urem: | |
| 1117 case InstArithmetic::Srem: { | |
| 1118 // Check for divide by 0 (ARM normally doesn't trap, but we want it | |
| 1119 // to trap for NaCl). Src1Lo and Src1Hi may have already been legalized | |
| 1120 // to a register, which will hide a constant source operand. | |
| 1121 // Instead, check the not-yet-legalized Src1 to optimize-out a divide | |
| 1122 // by 0 check. | |
| 1123 if (auto *C64 = llvm::dyn_cast<ConstantInteger64>(Src1)) { | |
| 1124 if (C64->getValue() == 0) { | |
| 1125 _trap(); | |
| 1126 return; | |
| 1127 } | |
| 1128 } else { | |
| 1129 Operand *Src1Lo = legalize(loOperand(Src1), Legal_Reg | Legal_Flex); | |
| 1130 Operand *Src1Hi = legalize(hiOperand(Src1), Legal_Reg | Legal_Flex); | |
| 1131 div0Check(IceType_i64, Src1Lo, Src1Hi); | |
| 1132 } | |
| 1133 // Technically, ARM has their own aeabi routines, but we can use the | |
| 1134 // non-aeabi routine as well. LLVM uses __aeabi_ldivmod for div, | |
| 1135 // but uses the more standard __moddi3 for rem. | |
| 1136 const char *HelperName = ""; | |
| 1137 switch (Inst->getOp()) { | |
| 1138 default: | |
| 1139 llvm_unreachable("Should have only matched div ops."); | |
| 1140 break; | |
| 1141 case InstArithmetic::Udiv: | |
| 1142 HelperName = H_udiv_i64; | |
| 1143 break; | |
| 1144 case InstArithmetic::Sdiv: | |
| 1145 HelperName = H_sdiv_i64; | |
| 1146 break; | |
| 1147 case InstArithmetic::Urem: | |
| 1148 HelperName = H_urem_i64; | |
| 1149 break; | |
| 1150 case InstArithmetic::Srem: | |
| 1151 HelperName = H_srem_i64; | |
| 1152 break; | |
| 1153 } | |
| 1154 constexpr SizeT MaxSrcs = 2; | |
| 1155 InstCall *Call = makeHelperCall(HelperName, Dest, MaxSrcs); | |
| 1156 Call->addArg(Src0); | |
| 1157 Call->addArg(Src1); | |
| 1158 lowerCall(Call); | |
| 1159 return; | |
| 1160 } | |
| 1161 } | |
| 1106 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 1162 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| 1107 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 1163 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| 1108 Variable *Src0RLo = legalizeToVar(loOperand(Src0)); | 1164 Variable *Src0RLo = legalizeToVar(loOperand(Src0)); |
| 1109 Variable *Src0RHi = legalizeToVar(hiOperand(Src0)); | 1165 Variable *Src0RHi = legalizeToVar(hiOperand(Src0)); |
| 1110 Operand *Src1Lo = legalize(loOperand(Src1), Legal_Reg | Legal_Flex); | 1166 Operand *Src1Lo = loOperand(Src1); |
| 1111 Operand *Src1Hi = legalize(hiOperand(Src1), Legal_Reg | Legal_Flex); | 1167 Operand *Src1Hi = hiOperand(Src1); |
| 1112 Variable *T_Lo = makeReg(DestLo->getType()); | 1168 Variable *T_Lo = makeReg(DestLo->getType()); |
| 1113 Variable *T_Hi = makeReg(DestHi->getType()); | 1169 Variable *T_Hi = makeReg(DestHi->getType()); |
| 1114 switch (Inst->getOp()) { | 1170 switch (Inst->getOp()) { |
| 1115 case InstArithmetic::_num: | 1171 case InstArithmetic::_num: |
| 1116 llvm_unreachable("Unknown arithmetic operator"); | 1172 llvm_unreachable("Unknown arithmetic operator"); |
| 1117 break; | 1173 return; |
| 1118 case InstArithmetic::Add: | 1174 case InstArithmetic::Add: |
| 1175 Src1Lo = legalize(Src1Lo, Legal_Reg | Legal_Flex); | |
| 1176 Src1Hi = legalize(Src1Hi, Legal_Reg | Legal_Flex); | |
| 1119 _adds(T_Lo, Src0RLo, Src1Lo); | 1177 _adds(T_Lo, Src0RLo, Src1Lo); |
| 1120 _mov(DestLo, T_Lo); | 1178 _mov(DestLo, T_Lo); |
| 1121 _adc(T_Hi, Src0RHi, Src1Hi); | 1179 _adc(T_Hi, Src0RHi, Src1Hi); |
| 1122 _mov(DestHi, T_Hi); | 1180 _mov(DestHi, T_Hi); |
| 1123 break; | 1181 return; |
| 1124 case InstArithmetic::And: | 1182 case InstArithmetic::And: |
| 1183 Src1Lo = legalize(Src1Lo, Legal_Reg | Legal_Flex); | |
| 1184 Src1Hi = legalize(Src1Hi, Legal_Reg | Legal_Flex); | |
| 1125 _and(T_Lo, Src0RLo, Src1Lo); | 1185 _and(T_Lo, Src0RLo, Src1Lo); |
| 1126 _mov(DestLo, T_Lo); | 1186 _mov(DestLo, T_Lo); |
| 1127 _and(T_Hi, Src0RHi, Src1Hi); | 1187 _and(T_Hi, Src0RHi, Src1Hi); |
| 1128 _mov(DestHi, T_Hi); | 1188 _mov(DestHi, T_Hi); |
| 1129 break; | 1189 return; |
| 1130 case InstArithmetic::Or: | 1190 case InstArithmetic::Or: |
| 1191 Src1Lo = legalize(Src1Lo, Legal_Reg | Legal_Flex); | |
| 1192 Src1Hi = legalize(Src1Hi, Legal_Reg | Legal_Flex); | |
| 1131 _orr(T_Lo, Src0RLo, Src1Lo); | 1193 _orr(T_Lo, Src0RLo, Src1Lo); |
| 1132 _mov(DestLo, T_Lo); | 1194 _mov(DestLo, T_Lo); |
| 1133 _orr(T_Hi, Src0RHi, Src1Hi); | 1195 _orr(T_Hi, Src0RHi, Src1Hi); |
| 1134 _mov(DestHi, T_Hi); | 1196 _mov(DestHi, T_Hi); |
| 1135 break; | 1197 return; |
| 1136 case InstArithmetic::Xor: | 1198 case InstArithmetic::Xor: |
| 1199 Src1Lo = legalize(Src1Lo, Legal_Reg | Legal_Flex); | |
| 1200 Src1Hi = legalize(Src1Hi, Legal_Reg | Legal_Flex); | |
| 1137 _eor(T_Lo, Src0RLo, Src1Lo); | 1201 _eor(T_Lo, Src0RLo, Src1Lo); |
| 1138 _mov(DestLo, T_Lo); | 1202 _mov(DestLo, T_Lo); |
| 1139 _eor(T_Hi, Src0RHi, Src1Hi); | 1203 _eor(T_Hi, Src0RHi, Src1Hi); |
| 1140 _mov(DestHi, T_Hi); | 1204 _mov(DestHi, T_Hi); |
| 1141 break; | 1205 return; |
| 1142 case InstArithmetic::Sub: | 1206 case InstArithmetic::Sub: |
| 1207 Src1Lo = legalize(Src1Lo, Legal_Reg | Legal_Flex); | |
| 1208 Src1Hi = legalize(Src1Hi, Legal_Reg | Legal_Flex); | |
| 1143 _subs(T_Lo, Src0RLo, Src1Lo); | 1209 _subs(T_Lo, Src0RLo, Src1Lo); |
| 1144 _mov(DestLo, T_Lo); | 1210 _mov(DestLo, T_Lo); |
| 1145 _sbc(T_Hi, Src0RHi, Src1Hi); | 1211 _sbc(T_Hi, Src0RHi, Src1Hi); |
| 1146 _mov(DestHi, T_Hi); | 1212 _mov(DestHi, T_Hi); |
| 1147 break; | 1213 return; |
| 1148 case InstArithmetic::Mul: { | 1214 case InstArithmetic::Mul: { |
| 1149 // GCC 4.8 does: | 1215 // GCC 4.8 does: |
| 1150 // a=b*c ==> | 1216 // a=b*c ==> |
| 1151 // t_acc =(mul) (b.lo * c.hi) | 1217 // t_acc =(mul) (b.lo * c.hi) |
| 1152 // t_acc =(mla) (c.lo * b.hi) + t_acc | 1218 // t_acc =(mla) (c.lo * b.hi) + t_acc |
| 1153 // t.hi,t.lo =(umull) b.lo * c.lo | 1219 // t.hi,t.lo =(umull) b.lo * c.lo |
| 1154 // t.hi += t_acc | 1220 // t.hi += t_acc |
| 1155 // a.lo = t.lo | 1221 // a.lo = t.lo |
| 1156 // a.hi = t.hi | 1222 // a.hi = t.hi |
| 1157 // | 1223 // |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 1169 Variable *T_Acc1 = makeReg(IceType_i32); | 1235 Variable *T_Acc1 = makeReg(IceType_i32); |
| 1170 Variable *T_Hi1 = makeReg(IceType_i32); | 1236 Variable *T_Hi1 = makeReg(IceType_i32); |
| 1171 Variable *Src1RLo = legalizeToVar(Src1Lo); | 1237 Variable *Src1RLo = legalizeToVar(Src1Lo); |
| 1172 Variable *Src1RHi = legalizeToVar(Src1Hi); | 1238 Variable *Src1RHi = legalizeToVar(Src1Hi); |
| 1173 _mul(T_Acc, Src0RLo, Src1RHi); | 1239 _mul(T_Acc, Src0RLo, Src1RHi); |
| 1174 _mla(T_Acc1, Src1RLo, Src0RHi, T_Acc); | 1240 _mla(T_Acc1, Src1RLo, Src0RHi, T_Acc); |
| 1175 _umull(T_Lo, T_Hi1, Src0RLo, Src1RLo); | 1241 _umull(T_Lo, T_Hi1, Src0RLo, Src1RLo); |
| 1176 _add(T_Hi, T_Hi1, T_Acc1); | 1242 _add(T_Hi, T_Hi1, T_Acc1); |
| 1177 _mov(DestLo, T_Lo); | 1243 _mov(DestLo, T_Lo); |
| 1178 _mov(DestHi, T_Hi); | 1244 _mov(DestHi, T_Hi); |
| 1179 } break; | 1245 return; |
| 1246 } | |
| 1180 case InstArithmetic::Shl: { | 1247 case InstArithmetic::Shl: { |
| 1181 // a=b<<c ==> | 1248 // a=b<<c ==> |
| 1182 // GCC 4.8 does: | 1249 // GCC 4.8 does: |
| 1183 // sub t_c1, c.lo, #32 | 1250 // sub t_c1, c.lo, #32 |
| 1184 // lsl t_hi, b.hi, c.lo | 1251 // lsl t_hi, b.hi, c.lo |
| 1185 // orr t_hi, t_hi, b.lo, lsl t_c1 | 1252 // orr t_hi, t_hi, b.lo, lsl t_c1 |
| 1186 // rsb t_c2, c.lo, #32 | 1253 // rsb t_c2, c.lo, #32 |
| 1187 // orr t_hi, t_hi, b.lo, lsr t_c2 | 1254 // orr t_hi, t_hi, b.lo, lsr t_c2 |
| 1188 // lsl t_lo, b.lo, c.lo | 1255 // lsl t_lo, b.lo, c.lo |
| 1189 // a.lo = t_lo | 1256 // a.lo = t_lo |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 1207 _orr(T_Hi, T_Hi, OperandARM32FlexReg::create(Func, IceType_i32, Src0RLo, | 1274 _orr(T_Hi, T_Hi, OperandARM32FlexReg::create(Func, IceType_i32, Src0RLo, |
| 1208 OperandARM32::LSR, T_C2)); | 1275 OperandARM32::LSR, T_C2)); |
| 1209 _mov(DestHi, T_Hi); | 1276 _mov(DestHi, T_Hi); |
| 1210 Variable *T_Lo = makeReg(IceType_i32); | 1277 Variable *T_Lo = makeReg(IceType_i32); |
| 1211 // _mov seems to sometimes have better register preferencing than lsl. | 1278 // _mov seems to sometimes have better register preferencing than lsl. |
| 1212 // Otherwise mov w/ lsl shifted register is a pseudo-instruction | 1279 // Otherwise mov w/ lsl shifted register is a pseudo-instruction |
| 1213 // that maps to lsl. | 1280 // that maps to lsl. |
| 1214 _mov(T_Lo, OperandARM32FlexReg::create(Func, IceType_i32, Src0RLo, | 1281 _mov(T_Lo, OperandARM32FlexReg::create(Func, IceType_i32, Src0RLo, |
| 1215 OperandARM32::LSL, Src1RLo)); | 1282 OperandARM32::LSL, Src1RLo)); |
| 1216 _mov(DestLo, T_Lo); | 1283 _mov(DestLo, T_Lo); |
| 1217 } break; | 1284 return; |
| 1285 } | |
| 1218 case InstArithmetic::Lshr: | 1286 case InstArithmetic::Lshr: |
| 1219 // a=b>>c (unsigned) ==> | 1287 // a=b>>c (unsigned) ==> |
| 1220 // GCC 4.8 does: | 1288 // GCC 4.8 does: |
| 1221 // rsb t_c1, c.lo, #32 | 1289 // rsb t_c1, c.lo, #32 |
| 1222 // lsr t_lo, b.lo, c.lo | 1290 // lsr t_lo, b.lo, c.lo |
| 1223 // orr t_lo, t_lo, b.hi, lsl t_c1 | 1291 // orr t_lo, t_lo, b.hi, lsl t_c1 |
| 1224 // sub t_c2, c.lo, #32 | 1292 // sub t_c2, c.lo, #32 |
| 1225 // orr t_lo, t_lo, b.hi, lsr t_c2 | 1293 // orr t_lo, t_lo, b.hi, lsr t_c2 |
| 1226 // lsr t_hi, b.hi, c.lo | 1294 // lsr t_hi, b.hi, c.lo |
| 1227 // a.lo = t_lo | 1295 // a.lo = t_lo |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 1253 Pred = CondARM32::AL; | 1321 Pred = CondARM32::AL; |
| 1254 } | 1322 } |
| 1255 _orr(T_Lo, T_Lo, OperandARM32FlexReg::create(Func, IceType_i32, Src0RHi, | 1323 _orr(T_Lo, T_Lo, OperandARM32FlexReg::create(Func, IceType_i32, Src0RHi, |
| 1256 RShiftKind, T_C2), | 1324 RShiftKind, T_C2), |
| 1257 Pred); | 1325 Pred); |
| 1258 _mov(DestLo, T_Lo); | 1326 _mov(DestLo, T_Lo); |
| 1259 Variable *T_Hi = makeReg(IceType_i32); | 1327 Variable *T_Hi = makeReg(IceType_i32); |
| 1260 _mov(T_Hi, OperandARM32FlexReg::create(Func, IceType_i32, Src0RHi, | 1328 _mov(T_Hi, OperandARM32FlexReg::create(Func, IceType_i32, Src0RHi, |
| 1261 RShiftKind, Src1RLo)); | 1329 RShiftKind, Src1RLo)); |
| 1262 _mov(DestHi, T_Hi); | 1330 _mov(DestHi, T_Hi); |
| 1263 } break; | |
| 1264 case InstArithmetic::Udiv: | |
| 1265 case InstArithmetic::Sdiv: | |
| 1266 case InstArithmetic::Urem: | |
| 1267 case InstArithmetic::Srem: { | |
| 1268 // Check for divide by 0 (ARM normally doesn't trap, but we want it | |
| 1269 // to trap for NaCl). Src1Lo and Src1Hi may have already been legalized | |
| 1270 // to a register, which will hide a constant source operand. | |
| 1271 // Instead, check the not-yet-legalized Src1 to optimize-out a divide | |
| 1272 // by 0 check. | |
| 1273 if (auto *C64 = llvm::dyn_cast<ConstantInteger64>(Src1)) { | |
| 1274 if (C64->getValue() == 0) { | |
| 1275 div0Check(IceType_i64, Src1Lo, Src1Hi); | |
| 1276 } | |
| 1277 } else { | |
| 1278 div0Check(IceType_i64, Src1Lo, Src1Hi); | |
| 1279 } | |
| 1280 // Technically, ARM has their own aeabi routines, but we can use the | |
| 1281 // non-aeabi routine as well. LLVM uses __aeabi_ldivmod for div, | |
| 1282 // but uses the more standard __moddi3 for rem. | |
| 1283 const char *HelperName = ""; | |
| 1284 switch (Inst->getOp()) { | |
| 1285 case InstArithmetic::Udiv: | |
| 1286 HelperName = H_udiv_i64; | |
| 1287 break; | |
| 1288 case InstArithmetic::Sdiv: | |
| 1289 HelperName = H_sdiv_i64; | |
| 1290 break; | |
| 1291 case InstArithmetic::Urem: | |
| 1292 HelperName = H_urem_i64; | |
| 1293 break; | |
| 1294 case InstArithmetic::Srem: | |
| 1295 HelperName = H_srem_i64; | |
| 1296 break; | |
| 1297 default: | |
| 1298 llvm_unreachable("Should have only matched div ops."); | |
| 1299 break; | |
| 1300 } | |
| 1301 constexpr SizeT MaxSrcs = 2; | |
| 1302 InstCall *Call = makeHelperCall(HelperName, Dest, MaxSrcs); | |
| 1303 Call->addArg(Inst->getSrc(0)); | |
| 1304 Call->addArg(Inst->getSrc(1)); | |
| 1305 lowerCall(Call); | |
| 1306 return; | 1331 return; |
| 1307 } | 1332 } |
| 1308 case InstArithmetic::Fadd: | 1333 case InstArithmetic::Fadd: |
| 1309 case InstArithmetic::Fsub: | 1334 case InstArithmetic::Fsub: |
| 1310 case InstArithmetic::Fmul: | 1335 case InstArithmetic::Fmul: |
| 1311 case InstArithmetic::Fdiv: | 1336 case InstArithmetic::Fdiv: |
| 1312 case InstArithmetic::Frem: | 1337 case InstArithmetic::Frem: |
| 1313 llvm_unreachable("FP instruction with i64 type"); | 1338 llvm_unreachable("FP instruction with i64 type"); |
| 1314 break; | 1339 return; |
| 1340 case InstArithmetic::Udiv: | |
| 1341 case InstArithmetic::Sdiv: | |
| 1342 case InstArithmetic::Urem: | |
| 1343 case InstArithmetic::Srem: | |
| 1344 llvm_unreachable("Call-helper-involved instruction for i64 type " | |
| 1345 "should have already been handled before"); | |
| 1346 return; | |
| 1315 } | 1347 } |
| 1348 return; | |
| 1316 } else if (isVectorType(Dest->getType())) { | 1349 } else if (isVectorType(Dest->getType())) { |
| 1317 UnimplementedError(Func->getContext()->getFlags()); | 1350 UnimplementedError(Func->getContext()->getFlags()); |
| 1318 } else { // Dest->getType() is non-i64 scalar | 1351 return; |
| 1319 Variable *Src0R = legalizeToVar(Inst->getSrc(0)); | 1352 } |
| 1320 Operand *Src1RF = legalize(Inst->getSrc(1), Legal_Reg | Legal_Flex); | 1353 // Dest->getType() is a non-i64 scalar. |
| 1321 Variable *T = makeReg(Dest->getType()); | 1354 Variable *Src0R = legalizeToVar(Src0); |
| 1322 switch (Inst->getOp()) { | 1355 Variable *T = makeReg(Dest->getType()); |
| 1323 case InstArithmetic::_num: | 1356 // Handle div/rem separately. They require a non-legalized Src1 to inspect |
| 1324 llvm_unreachable("Unknown arithmetic operator"); | 1357 // whether or not Src1 is a non-zero constant. Once legalized it is more |
| 1325 break; | 1358 // difficult to determine (constant may be moved to a register). |
| 1326 case InstArithmetic::Add: { | 1359 switch (Inst->getOp()) { |
| 1327 _add(T, Src0R, Src1RF); | 1360 default: |
| 1328 _mov(Dest, T); | 1361 break; |
| 1329 } break; | 1362 case InstArithmetic::Udiv: { |
| 1330 case InstArithmetic::And: { | 1363 constexpr bool IsRemainder = false; |
| 1331 _and(T, Src0R, Src1RF); | 1364 lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_uxt, &TargetARM32::_udiv, |
| 1332 _mov(Dest, T); | 1365 H_udiv_i32, IsRemainder); |
| 1333 } break; | 1366 return; |
| 1334 case InstArithmetic::Or: { | 1367 } |
| 1335 _orr(T, Src0R, Src1RF); | 1368 case InstArithmetic::Sdiv: { |
| 1336 _mov(Dest, T); | 1369 constexpr bool IsRemainder = false; |
| 1337 } break; | 1370 lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_sxt, &TargetARM32::_sdiv, |
| 1338 case InstArithmetic::Xor: { | 1371 H_sdiv_i32, IsRemainder); |
| 1339 _eor(T, Src0R, Src1RF); | 1372 return; |
| 1340 _mov(Dest, T); | 1373 } |
| 1341 } break; | 1374 case InstArithmetic::Urem: { |
| 1342 case InstArithmetic::Sub: { | 1375 constexpr bool IsRemainder = true; |
| 1343 _sub(T, Src0R, Src1RF); | 1376 lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_uxt, &TargetARM32::_udiv, |
| 1344 _mov(Dest, T); | 1377 H_urem_i32, IsRemainder); |
| 1345 } break; | 1378 return; |
| 1346 case InstArithmetic::Mul: { | 1379 } |
| 1347 Variable *Src1R = legalizeToVar(Src1RF); | 1380 case InstArithmetic::Srem: { |
| 1348 _mul(T, Src0R, Src1R); | 1381 constexpr bool IsRemainder = true; |
| 1349 _mov(Dest, T); | 1382 lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_sxt, &TargetARM32::_sdiv, |
| 1350 } break; | 1383 H_srem_i32, IsRemainder); |
| 1351 case InstArithmetic::Shl: | 1384 return; |
| 1352 _lsl(T, Src0R, Src1RF); | 1385 } |
| 1353 _mov(Dest, T); | 1386 } |
| 1354 break; | 1387 |
| 1355 case InstArithmetic::Lshr: | 1388 Operand *Src1RF = legalize(Src1, Legal_Reg | Legal_Flex); |
| 1356 _lsr(T, Src0R, Src1RF); | 1389 switch (Inst->getOp()) { |
| 1357 _mov(Dest, T); | 1390 case InstArithmetic::_num: |
| 1358 break; | 1391 llvm_unreachable("Unknown arithmetic operator"); |
| 1359 case InstArithmetic::Ashr: | 1392 return; |
| 1360 _asr(T, Src0R, Src1RF); | 1393 case InstArithmetic::Add: |
| 1361 _mov(Dest, T); | 1394 _add(T, Src0R, Src1RF); |
| 1362 break; | 1395 _mov(Dest, T); |
| 1363 case InstArithmetic::Udiv: { | 1396 return; |
| 1364 constexpr bool IsRemainder = false; | 1397 case InstArithmetic::And: |
| 1365 lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_uxt, | 1398 _and(T, Src0R, Src1RF); |
| 1366 &TargetARM32::_udiv, H_udiv_i32, IsRemainder); | 1399 _mov(Dest, T); |
| 1367 return; | 1400 return; |
| 1368 } | 1401 case InstArithmetic::Or: |
| 1369 case InstArithmetic::Sdiv: { | 1402 _orr(T, Src0R, Src1RF); |
| 1370 constexpr bool IsRemainder = false; | 1403 _mov(Dest, T); |
| 1371 lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_sxt, | 1404 return; |
| 1372 &TargetARM32::_sdiv, H_sdiv_i32, IsRemainder); | 1405 case InstArithmetic::Xor: |
| 1373 return; | 1406 _eor(T, Src0R, Src1RF); |
| 1374 } | 1407 _mov(Dest, T); |
| 1375 case InstArithmetic::Urem: { | 1408 return; |
| 1376 constexpr bool IsRemainder = true; | 1409 case InstArithmetic::Sub: |
| 1377 lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_uxt, | 1410 _sub(T, Src0R, Src1RF); |
| 1378 &TargetARM32::_udiv, H_urem_i32, IsRemainder); | 1411 _mov(Dest, T); |
| 1379 return; | 1412 return; |
| 1380 } | 1413 case InstArithmetic::Mul: { |
| 1381 case InstArithmetic::Srem: { | 1414 Variable *Src1R = legalizeToVar(Src1RF); |
| 1382 constexpr bool IsRemainder = true; | 1415 _mul(T, Src0R, Src1R); |
| 1383 lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_sxt, | 1416 _mov(Dest, T); |
| 1384 &TargetARM32::_sdiv, H_srem_i32, IsRemainder); | 1417 return; |
| 1385 return; | 1418 } |
| 1386 } | 1419 case InstArithmetic::Shl: |
| 1387 case InstArithmetic::Fadd: | 1420 _lsl(T, Src0R, Src1RF); |
| 1388 UnimplementedError(Func->getContext()->getFlags()); | 1421 _mov(Dest, T); |
| 1389 break; | 1422 return; |
| 1390 case InstArithmetic::Fsub: | 1423 case InstArithmetic::Lshr: |
| 1391 UnimplementedError(Func->getContext()->getFlags()); | 1424 _lsr(T, Src0R, Src1RF); |
| 1392 break; | 1425 _mov(Dest, T); |
| 1393 case InstArithmetic::Fmul: | 1426 return; |
| 1394 UnimplementedError(Func->getContext()->getFlags()); | 1427 case InstArithmetic::Ashr: |
| 1395 break; | 1428 _asr(T, Src0R, Src1RF); |
| 1396 case InstArithmetic::Fdiv: | 1429 _mov(Dest, T); |
| 1397 UnimplementedError(Func->getContext()->getFlags()); | 1430 return; |
| 1398 break; | 1431 case InstArithmetic::Udiv: |
| 1399 case InstArithmetic::Frem: | 1432 case InstArithmetic::Sdiv: |
| 1400 UnimplementedError(Func->getContext()->getFlags()); | 1433 case InstArithmetic::Urem: |
| 1401 break; | 1434 case InstArithmetic::Srem: |
| 1402 } | 1435 llvm_unreachable("Integer div/rem should have been handled earlier."); |
| 1436 return; | |
| 1437 case InstArithmetic::Fadd: | |
| 1438 UnimplementedError(Func->getContext()->getFlags()); | |
| 1439 return; | |
| 1440 case InstArithmetic::Fsub: | |
| 1441 UnimplementedError(Func->getContext()->getFlags()); | |
| 1442 return; | |
| 1443 case InstArithmetic::Fmul: | |
| 1444 UnimplementedError(Func->getContext()->getFlags()); | |
| 1445 return; | |
| 1446 case InstArithmetic::Fdiv: | |
| 1447 UnimplementedError(Func->getContext()->getFlags()); | |
| 1448 return; | |
| 1449 case InstArithmetic::Frem: | |
| 1450 UnimplementedError(Func->getContext()->getFlags()); | |
| 1451 return; | |
| 1403 } | 1452 } |
| 1404 } | 1453 } |
| 1405 | 1454 |
| 1406 void TargetARM32::lowerAssign(const InstAssign *Inst) { | 1455 void TargetARM32::lowerAssign(const InstAssign *Inst) { |
| 1407 Variable *Dest = Inst->getDest(); | 1456 Variable *Dest = Inst->getDest(); |
| 1408 Operand *Src0 = Inst->getSrc(0); | 1457 Operand *Src0 = Inst->getSrc(0); |
| 1409 assert(Dest->getType() == Src0->getType()); | 1458 assert(Dest->getType() == Src0->getType()); |
| 1410 if (Dest->getType() == IceType_i64) { | 1459 if (Dest->getType() == IceType_i64) { |
| 1411 Src0 = legalize(Src0); | 1460 Src0 = legalize(Src0); |
| 1412 Operand *Src0Lo = loOperand(Src0); | 1461 Operand *Src0Lo = loOperand(Src0); |
| (...skipping 1177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2590 << ".eabi_attribute 68, 1 @ Tag_Virtualization_use\n"; | 2639 << ".eabi_attribute 68, 1 @ Tag_Virtualization_use\n"; |
| 2591 if (CPUFeatures.hasFeature(TargetARM32Features::HWDivArm)) { | 2640 if (CPUFeatures.hasFeature(TargetARM32Features::HWDivArm)) { |
| 2592 Str << ".eabi_attribute 44, 2 @ Tag_DIV_use\n"; | 2641 Str << ".eabi_attribute 44, 2 @ Tag_DIV_use\n"; |
| 2593 } | 2642 } |
| 2594 // Technically R9 is used for TLS with Sandboxing, and we reserve it. | 2643 // Technically R9 is used for TLS with Sandboxing, and we reserve it. |
| 2595 // However, for compatibility with current NaCl LLVM, don't claim that. | 2644 // However, for compatibility with current NaCl LLVM, don't claim that. |
| 2596 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; | 2645 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; |
| 2597 } | 2646 } |
| 2598 | 2647 |
| 2599 } // end of namespace Ice | 2648 } // end of namespace Ice |
| OLD | NEW |