| 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 /// \file | 10 /// \file |
| (...skipping 1009 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1020 _add(T, T, AddAmount); | 1020 _add(T, T, AddAmount); |
| 1021 alignRegisterPow2(T, Alignment); | 1021 alignRegisterPow2(T, Alignment); |
| 1022 _sub(SP, SP, T); | 1022 _sub(SP, SP, T); |
| 1023 } | 1023 } |
| 1024 _mov(Dest, SP); | 1024 _mov(Dest, SP); |
| 1025 } | 1025 } |
| 1026 | 1026 |
| 1027 void TargetARM32::div0Check(Type Ty, Operand *SrcLo, Operand *SrcHi) { | 1027 void TargetARM32::div0Check(Type Ty, Operand *SrcLo, Operand *SrcHi) { |
| 1028 if (isGuaranteedNonzeroInt(SrcLo) || isGuaranteedNonzeroInt(SrcHi)) | 1028 if (isGuaranteedNonzeroInt(SrcLo) || isGuaranteedNonzeroInt(SrcHi)) |
| 1029 return; | 1029 return; |
| 1030 Variable *SrcLoReg = legalizeToVar(SrcLo); | 1030 Variable *SrcLoReg = legalizeToReg(SrcLo); |
| 1031 switch (Ty) { | 1031 switch (Ty) { |
| 1032 default: | 1032 default: |
| 1033 llvm_unreachable("Unexpected type"); | 1033 llvm_unreachable("Unexpected type"); |
| 1034 case IceType_i8: { | 1034 case IceType_i8: { |
| 1035 Operand *Mask = | 1035 Operand *Mask = |
| 1036 legalize(Ctx->getConstantInt32(0xFF), Legal_Reg | Legal_Flex); | 1036 legalize(Ctx->getConstantInt32(0xFF), Legal_Reg | Legal_Flex); |
| 1037 _tst(SrcLoReg, Mask); | 1037 _tst(SrcLoReg, Mask); |
| 1038 break; | 1038 break; |
| 1039 } | 1039 } |
| 1040 case IceType_i16: { | 1040 case IceType_i16: { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1059 _br(Label, CondARM32::NE); | 1059 _br(Label, CondARM32::NE); |
| 1060 _trap(); | 1060 _trap(); |
| 1061 Context.insert(Label); | 1061 Context.insert(Label); |
| 1062 } | 1062 } |
| 1063 | 1063 |
| 1064 void TargetARM32::lowerIDivRem(Variable *Dest, Variable *T, Variable *Src0R, | 1064 void TargetARM32::lowerIDivRem(Variable *Dest, Variable *T, Variable *Src0R, |
| 1065 Operand *Src1, ExtInstr ExtFunc, | 1065 Operand *Src1, ExtInstr ExtFunc, |
| 1066 DivInstr DivFunc, const char *DivHelperName, | 1066 DivInstr DivFunc, const char *DivHelperName, |
| 1067 bool IsRemainder) { | 1067 bool IsRemainder) { |
| 1068 div0Check(Dest->getType(), Src1, nullptr); | 1068 div0Check(Dest->getType(), Src1, nullptr); |
| 1069 Variable *Src1R = legalizeToVar(Src1); | 1069 Variable *Src1R = legalizeToReg(Src1); |
| 1070 Variable *T0R = Src0R; | 1070 Variable *T0R = Src0R; |
| 1071 Variable *T1R = Src1R; | 1071 Variable *T1R = Src1R; |
| 1072 if (Dest->getType() != IceType_i32) { | 1072 if (Dest->getType() != IceType_i32) { |
| 1073 T0R = makeReg(IceType_i32); | 1073 T0R = makeReg(IceType_i32); |
| 1074 (this->*ExtFunc)(T0R, Src0R, CondARM32::AL); | 1074 (this->*ExtFunc)(T0R, Src0R, CondARM32::AL); |
| 1075 T1R = makeReg(IceType_i32); | 1075 T1R = makeReg(IceType_i32); |
| 1076 (this->*ExtFunc)(T1R, Src1R, CondARM32::AL); | 1076 (this->*ExtFunc)(T1R, Src1R, CondARM32::AL); |
| 1077 } | 1077 } |
| 1078 if (hasCPUFeature(TargetARM32Features::HWDivArm)) { | 1078 if (hasCPUFeature(TargetARM32Features::HWDivArm)) { |
| 1079 (this->*DivFunc)(T, T0R, T1R, CondARM32::AL); | 1079 (this->*DivFunc)(T, T0R, T1R, CondARM32::AL); |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1156 constexpr SizeT MaxSrcs = 2; | 1156 constexpr SizeT MaxSrcs = 2; |
| 1157 InstCall *Call = makeHelperCall(HelperName, Dest, MaxSrcs); | 1157 InstCall *Call = makeHelperCall(HelperName, Dest, MaxSrcs); |
| 1158 Call->addArg(Src0); | 1158 Call->addArg(Src0); |
| 1159 Call->addArg(Src1); | 1159 Call->addArg(Src1); |
| 1160 lowerCall(Call); | 1160 lowerCall(Call); |
| 1161 return; | 1161 return; |
| 1162 } | 1162 } |
| 1163 } | 1163 } |
| 1164 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 1164 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| 1165 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 1165 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| 1166 Variable *Src0RLo = legalizeToVar(loOperand(Src0)); | 1166 Variable *Src0RLo = legalizeToReg(loOperand(Src0)); |
| 1167 Variable *Src0RHi = legalizeToVar(hiOperand(Src0)); | 1167 Variable *Src0RHi = legalizeToReg(hiOperand(Src0)); |
| 1168 Operand *Src1Lo = loOperand(Src1); | 1168 Operand *Src1Lo = loOperand(Src1); |
| 1169 Operand *Src1Hi = hiOperand(Src1); | 1169 Operand *Src1Hi = hiOperand(Src1); |
| 1170 Variable *T_Lo = makeReg(DestLo->getType()); | 1170 Variable *T_Lo = makeReg(DestLo->getType()); |
| 1171 Variable *T_Hi = makeReg(DestHi->getType()); | 1171 Variable *T_Hi = makeReg(DestHi->getType()); |
| 1172 switch (Inst->getOp()) { | 1172 switch (Inst->getOp()) { |
| 1173 case InstArithmetic::_num: | 1173 case InstArithmetic::_num: |
| 1174 llvm_unreachable("Unknown arithmetic operator"); | 1174 llvm_unreachable("Unknown arithmetic operator"); |
| 1175 return; | 1175 return; |
| 1176 case InstArithmetic::Add: | 1176 case InstArithmetic::Add: |
| 1177 Src1Lo = legalize(Src1Lo, Legal_Reg | Legal_Flex); | 1177 Src1Lo = legalize(Src1Lo, Legal_Reg | Legal_Flex); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1229 // t.hi =(mla) (b.hi * c.lo) + t.hi | 1229 // t.hi =(mla) (b.hi * c.lo) + t.hi |
| 1230 // a.lo = t.lo | 1230 // a.lo = t.lo |
| 1231 // a.hi = t.hi | 1231 // a.hi = t.hi |
| 1232 // | 1232 // |
| 1233 // LLVM's lowering has fewer instructions, but more register pressure: | 1233 // LLVM's lowering has fewer instructions, but more register pressure: |
| 1234 // t.lo is live from beginning to end, while GCC delays the two-dest | 1234 // t.lo is live from beginning to end, while GCC delays the two-dest |
| 1235 // instruction till the end, and kills c.hi immediately. | 1235 // instruction till the end, and kills c.hi immediately. |
| 1236 Variable *T_Acc = makeReg(IceType_i32); | 1236 Variable *T_Acc = makeReg(IceType_i32); |
| 1237 Variable *T_Acc1 = makeReg(IceType_i32); | 1237 Variable *T_Acc1 = makeReg(IceType_i32); |
| 1238 Variable *T_Hi1 = makeReg(IceType_i32); | 1238 Variable *T_Hi1 = makeReg(IceType_i32); |
| 1239 Variable *Src1RLo = legalizeToVar(Src1Lo); | 1239 Variable *Src1RLo = legalizeToReg(Src1Lo); |
| 1240 Variable *Src1RHi = legalizeToVar(Src1Hi); | 1240 Variable *Src1RHi = legalizeToReg(Src1Hi); |
| 1241 _mul(T_Acc, Src0RLo, Src1RHi); | 1241 _mul(T_Acc, Src0RLo, Src1RHi); |
| 1242 _mla(T_Acc1, Src1RLo, Src0RHi, T_Acc); | 1242 _mla(T_Acc1, Src1RLo, Src0RHi, T_Acc); |
| 1243 _umull(T_Lo, T_Hi1, Src0RLo, Src1RLo); | 1243 _umull(T_Lo, T_Hi1, Src0RLo, Src1RLo); |
| 1244 _add(T_Hi, T_Hi1, T_Acc1); | 1244 _add(T_Hi, T_Hi1, T_Acc1); |
| 1245 _mov(DestLo, T_Lo); | 1245 _mov(DestLo, T_Lo); |
| 1246 _mov(DestHi, T_Hi); | 1246 _mov(DestHi, T_Hi); |
| 1247 return; | 1247 return; |
| 1248 } | 1248 } |
| 1249 case InstArithmetic::Shl: { | 1249 case InstArithmetic::Shl: { |
| 1250 // a=b<<c ==> | 1250 // a=b<<c ==> |
| 1251 // GCC 4.8 does: | 1251 // GCC 4.8 does: |
| 1252 // sub t_c1, c.lo, #32 | 1252 // sub t_c1, c.lo, #32 |
| 1253 // lsl t_hi, b.hi, c.lo | 1253 // lsl t_hi, b.hi, c.lo |
| 1254 // orr t_hi, t_hi, b.lo, lsl t_c1 | 1254 // orr t_hi, t_hi, b.lo, lsl t_c1 |
| 1255 // rsb t_c2, c.lo, #32 | 1255 // rsb t_c2, c.lo, #32 |
| 1256 // orr t_hi, t_hi, b.lo, lsr t_c2 | 1256 // orr t_hi, t_hi, b.lo, lsr t_c2 |
| 1257 // lsl t_lo, b.lo, c.lo | 1257 // lsl t_lo, b.lo, c.lo |
| 1258 // a.lo = t_lo | 1258 // a.lo = t_lo |
| 1259 // a.hi = t_hi | 1259 // a.hi = t_hi |
| 1260 // Can be strength-reduced for constant-shifts, but we don't do | 1260 // Can be strength-reduced for constant-shifts, but we don't do |
| 1261 // that for now. | 1261 // that for now. |
| 1262 // Given the sub/rsb T_C, C.lo, #32, one of the T_C will be negative. | 1262 // Given the sub/rsb T_C, C.lo, #32, one of the T_C will be negative. |
| 1263 // On ARM, shifts only take the lower 8 bits of the shift register, | 1263 // On ARM, shifts only take the lower 8 bits of the shift register, |
| 1264 // and saturate to the range 0-32, so the negative value will | 1264 // and saturate to the range 0-32, so the negative value will |
| 1265 // saturate to 32. | 1265 // saturate to 32. |
| 1266 Variable *T_Hi = makeReg(IceType_i32); | 1266 Variable *T_Hi = makeReg(IceType_i32); |
| 1267 Variable *Src1RLo = legalizeToVar(Src1Lo); | 1267 Variable *Src1RLo = legalizeToReg(Src1Lo); |
| 1268 Constant *ThirtyTwo = Ctx->getConstantInt32(32); | 1268 Constant *ThirtyTwo = Ctx->getConstantInt32(32); |
| 1269 Variable *T_C1 = makeReg(IceType_i32); | 1269 Variable *T_C1 = makeReg(IceType_i32); |
| 1270 Variable *T_C2 = makeReg(IceType_i32); | 1270 Variable *T_C2 = makeReg(IceType_i32); |
| 1271 _sub(T_C1, Src1RLo, ThirtyTwo); | 1271 _sub(T_C1, Src1RLo, ThirtyTwo); |
| 1272 _lsl(T_Hi, Src0RHi, Src1RLo); | 1272 _lsl(T_Hi, Src0RHi, Src1RLo); |
| 1273 _orr(T_Hi, T_Hi, OperandARM32FlexReg::create(Func, IceType_i32, Src0RLo, | 1273 _orr(T_Hi, T_Hi, OperandARM32FlexReg::create(Func, IceType_i32, Src0RLo, |
| 1274 OperandARM32::LSL, T_C1)); | 1274 OperandARM32::LSL, T_C1)); |
| 1275 _rsb(T_C2, Src1RLo, ThirtyTwo); | 1275 _rsb(T_C2, Src1RLo, ThirtyTwo); |
| 1276 _orr(T_Hi, T_Hi, OperandARM32FlexReg::create(Func, IceType_i32, Src0RLo, | 1276 _orr(T_Hi, T_Hi, OperandARM32FlexReg::create(Func, IceType_i32, Src0RLo, |
| 1277 OperandARM32::LSR, T_C2)); | 1277 OperandARM32::LSR, T_C2)); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1296 // lsr t_hi, b.hi, c.lo | 1296 // lsr t_hi, b.hi, c.lo |
| 1297 // a.lo = t_lo | 1297 // a.lo = t_lo |
| 1298 // a.hi = t_hi | 1298 // a.hi = t_hi |
| 1299 case InstArithmetic::Ashr: { | 1299 case InstArithmetic::Ashr: { |
| 1300 // a=b>>c (signed) ==> ... | 1300 // a=b>>c (signed) ==> ... |
| 1301 // Ashr is similar, but the sub t_c2, c.lo, #32 should set flags, | 1301 // Ashr is similar, but the sub t_c2, c.lo, #32 should set flags, |
| 1302 // and the next orr should be conditioned on PLUS. The last two | 1302 // and the next orr should be conditioned on PLUS. The last two |
| 1303 // right shifts should also be arithmetic. | 1303 // right shifts should also be arithmetic. |
| 1304 bool IsAshr = Inst->getOp() == InstArithmetic::Ashr; | 1304 bool IsAshr = Inst->getOp() == InstArithmetic::Ashr; |
| 1305 Variable *T_Lo = makeReg(IceType_i32); | 1305 Variable *T_Lo = makeReg(IceType_i32); |
| 1306 Variable *Src1RLo = legalizeToVar(Src1Lo); | 1306 Variable *Src1RLo = legalizeToReg(Src1Lo); |
| 1307 Constant *ThirtyTwo = Ctx->getConstantInt32(32); | 1307 Constant *ThirtyTwo = Ctx->getConstantInt32(32); |
| 1308 Variable *T_C1 = makeReg(IceType_i32); | 1308 Variable *T_C1 = makeReg(IceType_i32); |
| 1309 Variable *T_C2 = makeReg(IceType_i32); | 1309 Variable *T_C2 = makeReg(IceType_i32); |
| 1310 _rsb(T_C1, Src1RLo, ThirtyTwo); | 1310 _rsb(T_C1, Src1RLo, ThirtyTwo); |
| 1311 _lsr(T_Lo, Src0RLo, Src1RLo); | 1311 _lsr(T_Lo, Src0RLo, Src1RLo); |
| 1312 _orr(T_Lo, T_Lo, OperandARM32FlexReg::create(Func, IceType_i32, Src0RHi, | 1312 _orr(T_Lo, T_Lo, OperandARM32FlexReg::create(Func, IceType_i32, Src0RHi, |
| 1313 OperandARM32::LSL, T_C1)); | 1313 OperandARM32::LSL, T_C1)); |
| 1314 OperandARM32::ShiftKind RShiftKind; | 1314 OperandARM32::ShiftKind RShiftKind; |
| 1315 CondARM32::Cond Pred; | 1315 CondARM32::Cond Pred; |
| 1316 if (IsAshr) { | 1316 if (IsAshr) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1346 llvm_unreachable("Call-helper-involved instruction for i64 type " | 1346 llvm_unreachable("Call-helper-involved instruction for i64 type " |
| 1347 "should have already been handled before"); | 1347 "should have already been handled before"); |
| 1348 return; | 1348 return; |
| 1349 } | 1349 } |
| 1350 return; | 1350 return; |
| 1351 } else if (isVectorType(Dest->getType())) { | 1351 } else if (isVectorType(Dest->getType())) { |
| 1352 UnimplementedError(Func->getContext()->getFlags()); | 1352 UnimplementedError(Func->getContext()->getFlags()); |
| 1353 return; | 1353 return; |
| 1354 } | 1354 } |
| 1355 // Dest->getType() is a non-i64 scalar. | 1355 // Dest->getType() is a non-i64 scalar. |
| 1356 Variable *Src0R = legalizeToVar(Src0); | 1356 Variable *Src0R = legalizeToReg(Src0); |
| 1357 Variable *T = makeReg(Dest->getType()); | 1357 Variable *T = makeReg(Dest->getType()); |
| 1358 // Handle div/rem separately. They require a non-legalized Src1 to inspect | 1358 // Handle div/rem separately. They require a non-legalized Src1 to inspect |
| 1359 // whether or not Src1 is a non-zero constant. Once legalized it is more | 1359 // whether or not Src1 is a non-zero constant. Once legalized it is more |
| 1360 // difficult to determine (constant may be moved to a register). | 1360 // difficult to determine (constant may be moved to a register). |
| 1361 switch (Inst->getOp()) { | 1361 switch (Inst->getOp()) { |
| 1362 default: | 1362 default: |
| 1363 break; | 1363 break; |
| 1364 case InstArithmetic::Udiv: { | 1364 case InstArithmetic::Udiv: { |
| 1365 constexpr bool IsRemainder = false; | 1365 constexpr bool IsRemainder = false; |
| 1366 lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_uxt, &TargetARM32::_udiv, | 1366 lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_uxt, &TargetARM32::_udiv, |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1406 return; | 1406 return; |
| 1407 case InstArithmetic::Xor: | 1407 case InstArithmetic::Xor: |
| 1408 _eor(T, Src0R, Src1RF); | 1408 _eor(T, Src0R, Src1RF); |
| 1409 _mov(Dest, T); | 1409 _mov(Dest, T); |
| 1410 return; | 1410 return; |
| 1411 case InstArithmetic::Sub: | 1411 case InstArithmetic::Sub: |
| 1412 _sub(T, Src0R, Src1RF); | 1412 _sub(T, Src0R, Src1RF); |
| 1413 _mov(Dest, T); | 1413 _mov(Dest, T); |
| 1414 return; | 1414 return; |
| 1415 case InstArithmetic::Mul: { | 1415 case InstArithmetic::Mul: { |
| 1416 Variable *Src1R = legalizeToVar(Src1RF); | 1416 Variable *Src1R = legalizeToReg(Src1RF); |
| 1417 _mul(T, Src0R, Src1R); | 1417 _mul(T, Src0R, Src1R); |
| 1418 _mov(Dest, T); | 1418 _mov(Dest, T); |
| 1419 return; | 1419 return; |
| 1420 } | 1420 } |
| 1421 case InstArithmetic::Shl: | 1421 case InstArithmetic::Shl: |
| 1422 _lsl(T, Src0R, Src1RF); | 1422 _lsl(T, Src0R, Src1RF); |
| 1423 _mov(Dest, T); | 1423 _mov(Dest, T); |
| 1424 return; | 1424 return; |
| 1425 case InstArithmetic::Lshr: | 1425 case InstArithmetic::Lshr: |
| 1426 _lsr(T, Src0R, Src1RF); | 1426 _lsr(T, Src0R, Src1RF); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1495 } | 1495 } |
| 1496 | 1496 |
| 1497 void TargetARM32::lowerBr(const InstBr *Inst) { | 1497 void TargetARM32::lowerBr(const InstBr *Inst) { |
| 1498 if (Inst->isUnconditional()) { | 1498 if (Inst->isUnconditional()) { |
| 1499 _br(Inst->getTargetUnconditional()); | 1499 _br(Inst->getTargetUnconditional()); |
| 1500 return; | 1500 return; |
| 1501 } | 1501 } |
| 1502 Operand *Cond = Inst->getCondition(); | 1502 Operand *Cond = Inst->getCondition(); |
| 1503 // TODO(jvoung): Handle folding opportunities. | 1503 // TODO(jvoung): Handle folding opportunities. |
| 1504 | 1504 |
| 1505 Variable *Src0R = legalizeToVar(Cond); | 1505 Variable *Src0R = legalizeToReg(Cond); |
| 1506 Constant *Zero = Ctx->getConstantZero(IceType_i32); | 1506 Constant *Zero = Ctx->getConstantZero(IceType_i32); |
| 1507 _cmp(Src0R, Zero); | 1507 _cmp(Src0R, Zero); |
| 1508 _br(Inst->getTargetTrue(), Inst->getTargetFalse(), CondARM32::NE); | 1508 _br(Inst->getTargetTrue(), Inst->getTargetFalse(), CondARM32::NE); |
| 1509 } | 1509 } |
| 1510 | 1510 |
| 1511 void TargetARM32::lowerCall(const InstCall *Instr) { | 1511 void TargetARM32::lowerCall(const InstCall *Instr) { |
| 1512 MaybeLeafFunc = false; | 1512 MaybeLeafFunc = false; |
| 1513 NeedsStackAlignment = true; | 1513 NeedsStackAlignment = true; |
| 1514 | 1514 |
| 1515 // Assign arguments to registers and stack. Also reserve stack. | 1515 // Assign arguments to registers and stack. Also reserve stack. |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1589 Variable *NewBase = Func->makeVariable(SP->getType()); | 1589 Variable *NewBase = Func->makeVariable(SP->getType()); |
| 1590 lowerArithmetic( | 1590 lowerArithmetic( |
| 1591 InstArithmetic::create(Func, InstArithmetic::Add, NewBase, SP, Loc)); | 1591 InstArithmetic::create(Func, InstArithmetic::Add, NewBase, SP, Loc)); |
| 1592 Addr = formMemoryOperand(NewBase, Ty); | 1592 Addr = formMemoryOperand(NewBase, Ty); |
| 1593 } | 1593 } |
| 1594 lowerStore(InstStore::create(Func, StackArg.first, Addr)); | 1594 lowerStore(InstStore::create(Func, StackArg.first, Addr)); |
| 1595 } | 1595 } |
| 1596 | 1596 |
| 1597 // Copy arguments to be passed in registers to the appropriate registers. | 1597 // Copy arguments to be passed in registers to the appropriate registers. |
| 1598 for (auto &GPRArg : GPRArgs) { | 1598 for (auto &GPRArg : GPRArgs) { |
| 1599 Variable *Reg = legalizeToVar(GPRArg.first, GPRArg.second); | 1599 Variable *Reg = legalizeToReg(GPRArg.first, GPRArg.second); |
| 1600 // Generate a FakeUse of register arguments so that they do not get | 1600 // Generate a FakeUse of register arguments so that they do not get |
| 1601 // dead code eliminated as a result of the FakeKill of scratch | 1601 // dead code eliminated as a result of the FakeKill of scratch |
| 1602 // registers after the call. | 1602 // registers after the call. |
| 1603 Context.insert(InstFakeUse::create(Func, Reg)); | 1603 Context.insert(InstFakeUse::create(Func, Reg)); |
| 1604 } | 1604 } |
| 1605 | 1605 |
| 1606 // Generate the call instruction. Assign its result to a temporary | 1606 // Generate the call instruction. Assign its result to a temporary |
| 1607 // with high register allocation weight. | 1607 // with high register allocation weight. |
| 1608 Variable *Dest = Instr->getDest(); | 1608 Variable *Dest = Instr->getDest(); |
| 1609 // ReturnReg doubles as ReturnRegLo as necessary. | 1609 // ReturnReg doubles as ReturnRegLo as necessary. |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1715 } else if (Dest->getType() == IceType_i64) { | 1715 } else if (Dest->getType() == IceType_i64) { |
| 1716 // t1=sxtb src; t2= mov t1 asr #31; dst.lo=t1; dst.hi=t2 | 1716 // t1=sxtb src; t2= mov t1 asr #31; dst.lo=t1; dst.hi=t2 |
| 1717 Constant *ShiftAmt = Ctx->getConstantInt32(31); | 1717 Constant *ShiftAmt = Ctx->getConstantInt32(31); |
| 1718 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 1718 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| 1719 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 1719 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| 1720 Variable *T_Lo = makeReg(DestLo->getType()); | 1720 Variable *T_Lo = makeReg(DestLo->getType()); |
| 1721 if (Src0->getType() == IceType_i32) { | 1721 if (Src0->getType() == IceType_i32) { |
| 1722 Operand *Src0RF = legalize(Src0, Legal_Reg | Legal_Flex); | 1722 Operand *Src0RF = legalize(Src0, Legal_Reg | Legal_Flex); |
| 1723 _mov(T_Lo, Src0RF); | 1723 _mov(T_Lo, Src0RF); |
| 1724 } else if (Src0->getType() == IceType_i1) { | 1724 } else if (Src0->getType() == IceType_i1) { |
| 1725 Variable *Src0R = legalizeToVar(Src0); | 1725 Variable *Src0R = legalizeToReg(Src0); |
| 1726 _lsl(T_Lo, Src0R, ShiftAmt); | 1726 _lsl(T_Lo, Src0R, ShiftAmt); |
| 1727 _asr(T_Lo, T_Lo, ShiftAmt); | 1727 _asr(T_Lo, T_Lo, ShiftAmt); |
| 1728 } else { | 1728 } else { |
| 1729 Variable *Src0R = legalizeToVar(Src0); | 1729 Variable *Src0R = legalizeToReg(Src0); |
| 1730 _sxt(T_Lo, Src0R); | 1730 _sxt(T_Lo, Src0R); |
| 1731 } | 1731 } |
| 1732 _mov(DestLo, T_Lo); | 1732 _mov(DestLo, T_Lo); |
| 1733 Variable *T_Hi = makeReg(DestHi->getType()); | 1733 Variable *T_Hi = makeReg(DestHi->getType()); |
| 1734 if (Src0->getType() != IceType_i1) { | 1734 if (Src0->getType() != IceType_i1) { |
| 1735 _mov(T_Hi, OperandARM32FlexReg::create(Func, IceType_i32, T_Lo, | 1735 _mov(T_Hi, OperandARM32FlexReg::create(Func, IceType_i32, T_Lo, |
| 1736 OperandARM32::ASR, ShiftAmt)); | 1736 OperandARM32::ASR, ShiftAmt)); |
| 1737 } else { | 1737 } else { |
| 1738 // For i1, the asr instruction is already done above. | 1738 // For i1, the asr instruction is already done above. |
| 1739 _mov(T_Hi, T_Lo); | 1739 _mov(T_Hi, T_Lo); |
| 1740 } | 1740 } |
| 1741 _mov(DestHi, T_Hi); | 1741 _mov(DestHi, T_Hi); |
| 1742 } else if (Src0->getType() == IceType_i1) { | 1742 } else if (Src0->getType() == IceType_i1) { |
| 1743 // GPR registers are 32-bit, so just use 31 as dst_bitwidth - 1. | 1743 // GPR registers are 32-bit, so just use 31 as dst_bitwidth - 1. |
| 1744 // lsl t1, src_reg, 31 | 1744 // lsl t1, src_reg, 31 |
| 1745 // asr t1, t1, 31 | 1745 // asr t1, t1, 31 |
| 1746 // dst = t1 | 1746 // dst = t1 |
| 1747 Variable *Src0R = legalizeToVar(Src0); | 1747 Variable *Src0R = legalizeToReg(Src0); |
| 1748 Constant *ShiftAmt = Ctx->getConstantInt32(31); | 1748 Constant *ShiftAmt = Ctx->getConstantInt32(31); |
| 1749 Variable *T = makeReg(Dest->getType()); | 1749 Variable *T = makeReg(Dest->getType()); |
| 1750 _lsl(T, Src0R, ShiftAmt); | 1750 _lsl(T, Src0R, ShiftAmt); |
| 1751 _asr(T, T, ShiftAmt); | 1751 _asr(T, T, ShiftAmt); |
| 1752 _mov(Dest, T); | 1752 _mov(Dest, T); |
| 1753 } else { | 1753 } else { |
| 1754 // t1 = sxt src; dst = t1 | 1754 // t1 = sxt src; dst = t1 |
| 1755 Variable *Src0R = legalizeToVar(Src0); | 1755 Variable *Src0R = legalizeToReg(Src0); |
| 1756 Variable *T = makeReg(Dest->getType()); | 1756 Variable *T = makeReg(Dest->getType()); |
| 1757 _sxt(T, Src0R); | 1757 _sxt(T, Src0R); |
| 1758 _mov(Dest, T); | 1758 _mov(Dest, T); |
| 1759 } | 1759 } |
| 1760 break; | 1760 break; |
| 1761 } | 1761 } |
| 1762 case InstCast::Zext: { | 1762 case InstCast::Zext: { |
| 1763 if (isVectorType(Dest->getType())) { | 1763 if (isVectorType(Dest->getType())) { |
| 1764 UnimplementedError(Func->getContext()->getFlags()); | 1764 UnimplementedError(Func->getContext()->getFlags()); |
| 1765 } else if (Dest->getType() == IceType_i64) { | 1765 } else if (Dest->getType() == IceType_i64) { |
| 1766 // t1=uxtb src; dst.lo=t1; dst.hi=0 | 1766 // t1=uxtb src; dst.lo=t1; dst.hi=0 |
| 1767 Constant *Zero = Ctx->getConstantZero(IceType_i32); | 1767 Constant *Zero = Ctx->getConstantZero(IceType_i32); |
| 1768 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 1768 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| 1769 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 1769 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| 1770 Variable *T_Lo = makeReg(DestLo->getType()); | 1770 Variable *T_Lo = makeReg(DestLo->getType()); |
| 1771 // i32 and i1 can just take up the whole register. | 1771 // i32 and i1 can just take up the whole register. |
| 1772 // i32 doesn't need uxt, while i1 will have an and mask later anyway. | 1772 // i32 doesn't need uxt, while i1 will have an and mask later anyway. |
| 1773 if (Src0->getType() == IceType_i32 || Src0->getType() == IceType_i1) { | 1773 if (Src0->getType() == IceType_i32 || Src0->getType() == IceType_i1) { |
| 1774 Operand *Src0RF = legalize(Src0, Legal_Reg | Legal_Flex); | 1774 Operand *Src0RF = legalize(Src0, Legal_Reg | Legal_Flex); |
| 1775 _mov(T_Lo, Src0RF); | 1775 _mov(T_Lo, Src0RF); |
| 1776 } else { | 1776 } else { |
| 1777 Variable *Src0R = legalizeToVar(Src0); | 1777 Variable *Src0R = legalizeToReg(Src0); |
| 1778 _uxt(T_Lo, Src0R); | 1778 _uxt(T_Lo, Src0R); |
| 1779 } | 1779 } |
| 1780 if (Src0->getType() == IceType_i1) { | 1780 if (Src0->getType() == IceType_i1) { |
| 1781 Constant *One = Ctx->getConstantInt32(1); | 1781 Constant *One = Ctx->getConstantInt32(1); |
| 1782 _and(T_Lo, T_Lo, One); | 1782 _and(T_Lo, T_Lo, One); |
| 1783 } | 1783 } |
| 1784 _mov(DestLo, T_Lo); | 1784 _mov(DestLo, T_Lo); |
| 1785 Variable *T_Hi = makeReg(DestLo->getType()); | 1785 Variable *T_Hi = makeReg(DestLo->getType()); |
| 1786 _mov(T_Hi, Zero); | 1786 _mov(T_Hi, Zero); |
| 1787 _mov(DestHi, T_Hi); | 1787 _mov(DestHi, T_Hi); |
| 1788 } else if (Src0->getType() == IceType_i1) { | 1788 } else if (Src0->getType() == IceType_i1) { |
| 1789 // t = Src0; t &= 1; Dest = t | 1789 // t = Src0; t &= 1; Dest = t |
| 1790 Operand *Src0RF = legalize(Src0, Legal_Reg | Legal_Flex); | 1790 Operand *Src0RF = legalize(Src0, Legal_Reg | Legal_Flex); |
| 1791 Constant *One = Ctx->getConstantInt32(1); | 1791 Constant *One = Ctx->getConstantInt32(1); |
| 1792 Variable *T = makeReg(Dest->getType()); | 1792 Variable *T = makeReg(Dest->getType()); |
| 1793 // Just use _mov instead of _uxt since all registers are 32-bit. | 1793 // Just use _mov instead of _uxt since all registers are 32-bit. |
| 1794 // _uxt requires the source to be a register so could have required | 1794 // _uxt requires the source to be a register so could have required |
| 1795 // a _mov from legalize anyway. | 1795 // a _mov from legalize anyway. |
| 1796 _mov(T, Src0RF); | 1796 _mov(T, Src0RF); |
| 1797 _and(T, T, One); | 1797 _and(T, T, One); |
| 1798 _mov(Dest, T); | 1798 _mov(Dest, T); |
| 1799 } else { | 1799 } else { |
| 1800 // t1 = uxt src; dst = t1 | 1800 // t1 = uxt src; dst = t1 |
| 1801 Variable *Src0R = legalizeToVar(Src0); | 1801 Variable *Src0R = legalizeToReg(Src0); |
| 1802 Variable *T = makeReg(Dest->getType()); | 1802 Variable *T = makeReg(Dest->getType()); |
| 1803 _uxt(T, Src0R); | 1803 _uxt(T, Src0R); |
| 1804 _mov(Dest, T); | 1804 _mov(Dest, T); |
| 1805 } | 1805 } |
| 1806 break; | 1806 break; |
| 1807 } | 1807 } |
| 1808 case InstCast::Trunc: { | 1808 case InstCast::Trunc: { |
| 1809 if (isVectorType(Dest->getType())) { | 1809 if (isVectorType(Dest->getType())) { |
| 1810 UnimplementedError(Func->getContext()->getFlags()); | 1810 UnimplementedError(Func->getContext()->getFlags()); |
| 1811 } else { | 1811 } else { |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1905 // perhaps for eq/ne). We could revisit special-casing eq/ne later. | 1905 // perhaps for eq/ne). We could revisit special-casing eq/ne later. |
| 1906 Constant *Zero = Ctx->getConstantZero(IceType_i32); | 1906 Constant *Zero = Ctx->getConstantZero(IceType_i32); |
| 1907 Constant *One = Ctx->getConstantInt32(1); | 1907 Constant *One = Ctx->getConstantInt32(1); |
| 1908 if (Src0->getType() == IceType_i64) { | 1908 if (Src0->getType() == IceType_i64) { |
| 1909 InstIcmp::ICond Conditon = Inst->getCondition(); | 1909 InstIcmp::ICond Conditon = Inst->getCondition(); |
| 1910 size_t Index = static_cast<size_t>(Conditon); | 1910 size_t Index = static_cast<size_t>(Conditon); |
| 1911 assert(Index < TableIcmp64Size); | 1911 assert(Index < TableIcmp64Size); |
| 1912 Variable *Src0Lo, *Src0Hi; | 1912 Variable *Src0Lo, *Src0Hi; |
| 1913 Operand *Src1LoRF, *Src1HiRF; | 1913 Operand *Src1LoRF, *Src1HiRF; |
| 1914 if (TableIcmp64[Index].Swapped) { | 1914 if (TableIcmp64[Index].Swapped) { |
| 1915 Src0Lo = legalizeToVar(loOperand(Src1)); | 1915 Src0Lo = legalizeToReg(loOperand(Src1)); |
| 1916 Src0Hi = legalizeToVar(hiOperand(Src1)); | 1916 Src0Hi = legalizeToReg(hiOperand(Src1)); |
| 1917 Src1LoRF = legalize(loOperand(Src0), Legal_Reg | Legal_Flex); | 1917 Src1LoRF = legalize(loOperand(Src0), Legal_Reg | Legal_Flex); |
| 1918 Src1HiRF = legalize(hiOperand(Src0), Legal_Reg | Legal_Flex); | 1918 Src1HiRF = legalize(hiOperand(Src0), Legal_Reg | Legal_Flex); |
| 1919 } else { | 1919 } else { |
| 1920 Src0Lo = legalizeToVar(loOperand(Src0)); | 1920 Src0Lo = legalizeToReg(loOperand(Src0)); |
| 1921 Src0Hi = legalizeToVar(hiOperand(Src0)); | 1921 Src0Hi = legalizeToReg(hiOperand(Src0)); |
| 1922 Src1LoRF = legalize(loOperand(Src1), Legal_Reg | Legal_Flex); | 1922 Src1LoRF = legalize(loOperand(Src1), Legal_Reg | Legal_Flex); |
| 1923 Src1HiRF = legalize(hiOperand(Src1), Legal_Reg | Legal_Flex); | 1923 Src1HiRF = legalize(hiOperand(Src1), Legal_Reg | Legal_Flex); |
| 1924 } | 1924 } |
| 1925 Variable *T = makeReg(IceType_i32); | 1925 Variable *T = makeReg(IceType_i32); |
| 1926 if (TableIcmp64[Index].IsSigned) { | 1926 if (TableIcmp64[Index].IsSigned) { |
| 1927 Variable *ScratchReg = makeReg(IceType_i32); | 1927 Variable *ScratchReg = makeReg(IceType_i32); |
| 1928 _cmp(Src0Lo, Src1LoRF); | 1928 _cmp(Src0Lo, Src1LoRF); |
| 1929 _sbcs(ScratchReg, Src0Hi, Src1HiRF); | 1929 _sbcs(ScratchReg, Src0Hi, Src1HiRF); |
| 1930 // ScratchReg isn't going to be used, but we need the | 1930 // ScratchReg isn't going to be used, but we need the |
| 1931 // side-effect of setting flags from this operation. | 1931 // side-effect of setting flags from this operation. |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1970 // We'll go with the LLVM way for now, since it's shorter and has just as | 1970 // We'll go with the LLVM way for now, since it's shorter and has just as |
| 1971 // few dependencies. | 1971 // few dependencies. |
| 1972 int32_t ShiftAmt = 32 - getScalarIntBitWidth(Src0->getType()); | 1972 int32_t ShiftAmt = 32 - getScalarIntBitWidth(Src0->getType()); |
| 1973 assert(ShiftAmt >= 0); | 1973 assert(ShiftAmt >= 0); |
| 1974 Constant *ShiftConst = nullptr; | 1974 Constant *ShiftConst = nullptr; |
| 1975 Variable *Src0R = nullptr; | 1975 Variable *Src0R = nullptr; |
| 1976 Variable *T = makeReg(IceType_i32); | 1976 Variable *T = makeReg(IceType_i32); |
| 1977 if (ShiftAmt) { | 1977 if (ShiftAmt) { |
| 1978 ShiftConst = Ctx->getConstantInt32(ShiftAmt); | 1978 ShiftConst = Ctx->getConstantInt32(ShiftAmt); |
| 1979 Src0R = makeReg(IceType_i32); | 1979 Src0R = makeReg(IceType_i32); |
| 1980 _lsl(Src0R, legalizeToVar(Src0), ShiftConst); | 1980 _lsl(Src0R, legalizeToReg(Src0), ShiftConst); |
| 1981 } else { | 1981 } else { |
| 1982 Src0R = legalizeToVar(Src0); | 1982 Src0R = legalizeToReg(Src0); |
| 1983 } | 1983 } |
| 1984 _mov(T, Zero); | 1984 _mov(T, Zero); |
| 1985 if (ShiftAmt) { | 1985 if (ShiftAmt) { |
| 1986 Variable *Src1R = legalizeToVar(Src1); | 1986 Variable *Src1R = legalizeToReg(Src1); |
| 1987 OperandARM32FlexReg *Src1RShifted = OperandARM32FlexReg::create( | 1987 OperandARM32FlexReg *Src1RShifted = OperandARM32FlexReg::create( |
| 1988 Func, IceType_i32, Src1R, OperandARM32::LSL, ShiftConst); | 1988 Func, IceType_i32, Src1R, OperandARM32::LSL, ShiftConst); |
| 1989 _cmp(Src0R, Src1RShifted); | 1989 _cmp(Src0R, Src1RShifted); |
| 1990 } else { | 1990 } else { |
| 1991 Operand *Src1RF = legalize(Src1, Legal_Reg | Legal_Flex); | 1991 Operand *Src1RF = legalize(Src1, Legal_Reg | Legal_Flex); |
| 1992 _cmp(Src0R, Src1RF); | 1992 _cmp(Src0R, Src1RF); |
| 1993 } | 1993 } |
| 1994 _mov_nonkillable(T, One, getIcmp32Mapping(Inst->getCondition())); | 1994 _mov_nonkillable(T, One, getIcmp32Mapping(Inst->getCondition())); |
| 1995 _mov(Dest, T); | 1995 _mov(Dest, T); |
| 1996 return; | 1996 return; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2030 case Intrinsics::AtomicStore: { | 2030 case Intrinsics::AtomicStore: { |
| 2031 UnimplementedError(Func->getContext()->getFlags()); | 2031 UnimplementedError(Func->getContext()->getFlags()); |
| 2032 return; | 2032 return; |
| 2033 } | 2033 } |
| 2034 case Intrinsics::Bswap: { | 2034 case Intrinsics::Bswap: { |
| 2035 Variable *Dest = Instr->getDest(); | 2035 Variable *Dest = Instr->getDest(); |
| 2036 Operand *Val = Instr->getArg(0); | 2036 Operand *Val = Instr->getArg(0); |
| 2037 Type Ty = Val->getType(); | 2037 Type Ty = Val->getType(); |
| 2038 if (Ty == IceType_i64) { | 2038 if (Ty == IceType_i64) { |
| 2039 Val = legalizeUndef(Val); | 2039 Val = legalizeUndef(Val); |
| 2040 Variable *Val_Lo = legalizeToVar(loOperand(Val)); | 2040 Variable *Val_Lo = legalizeToReg(loOperand(Val)); |
| 2041 Variable *Val_Hi = legalizeToVar(hiOperand(Val)); | 2041 Variable *Val_Hi = legalizeToReg(hiOperand(Val)); |
| 2042 Variable *T_Lo = makeReg(IceType_i32); | 2042 Variable *T_Lo = makeReg(IceType_i32); |
| 2043 Variable *T_Hi = makeReg(IceType_i32); | 2043 Variable *T_Hi = makeReg(IceType_i32); |
| 2044 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 2044 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| 2045 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 2045 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| 2046 _rev(T_Lo, Val_Lo); | 2046 _rev(T_Lo, Val_Lo); |
| 2047 _rev(T_Hi, Val_Hi); | 2047 _rev(T_Hi, Val_Hi); |
| 2048 _mov(DestLo, T_Hi); | 2048 _mov(DestLo, T_Hi); |
| 2049 _mov(DestHi, T_Lo); | 2049 _mov(DestHi, T_Lo); |
| 2050 } else { | 2050 } else { |
| 2051 assert(Ty == IceType_i32 || Ty == IceType_i16); | 2051 assert(Ty == IceType_i32 || Ty == IceType_i16); |
| 2052 Variable *ValR = legalizeToVar(Val); | 2052 Variable *ValR = legalizeToReg(Val); |
| 2053 Variable *T = makeReg(Ty); | 2053 Variable *T = makeReg(Ty); |
| 2054 _rev(T, ValR); | 2054 _rev(T, ValR); |
| 2055 if (Val->getType() == IceType_i16) { | 2055 if (Val->getType() == IceType_i16) { |
| 2056 Operand *Sixteen = | 2056 Operand *Sixteen = |
| 2057 legalize(Ctx->getConstantInt32(16), Legal_Reg | Legal_Flex); | 2057 legalize(Ctx->getConstantInt32(16), Legal_Reg | Legal_Flex); |
| 2058 _lsr(T, T, Sixteen); | 2058 _lsr(T, T, Sixteen); |
| 2059 } | 2059 } |
| 2060 _mov(Dest, T); | 2060 _mov(Dest, T); |
| 2061 } | 2061 } |
| 2062 return; | 2062 return; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2083 return; | 2083 return; |
| 2084 } | 2084 } |
| 2085 case Intrinsics::Ctlz: { | 2085 case Intrinsics::Ctlz: { |
| 2086 // The "is zero undef" parameter is ignored and we always return | 2086 // The "is zero undef" parameter is ignored and we always return |
| 2087 // a well-defined value. | 2087 // a well-defined value. |
| 2088 Operand *Val = Instr->getArg(0); | 2088 Operand *Val = Instr->getArg(0); |
| 2089 Variable *ValLoR; | 2089 Variable *ValLoR; |
| 2090 Variable *ValHiR = nullptr; | 2090 Variable *ValHiR = nullptr; |
| 2091 if (Val->getType() == IceType_i64) { | 2091 if (Val->getType() == IceType_i64) { |
| 2092 Val = legalizeUndef(Val); | 2092 Val = legalizeUndef(Val); |
| 2093 ValLoR = legalizeToVar(loOperand(Val)); | 2093 ValLoR = legalizeToReg(loOperand(Val)); |
| 2094 ValHiR = legalizeToVar(hiOperand(Val)); | 2094 ValHiR = legalizeToReg(hiOperand(Val)); |
| 2095 } else { | 2095 } else { |
| 2096 ValLoR = legalizeToVar(Val); | 2096 ValLoR = legalizeToReg(Val); |
| 2097 } | 2097 } |
| 2098 lowerCLZ(Instr->getDest(), ValLoR, ValHiR); | 2098 lowerCLZ(Instr->getDest(), ValLoR, ValHiR); |
| 2099 return; | 2099 return; |
| 2100 } | 2100 } |
| 2101 case Intrinsics::Cttz: { | 2101 case Intrinsics::Cttz: { |
| 2102 // Essentially like Clz, but reverse the bits first. | 2102 // Essentially like Clz, but reverse the bits first. |
| 2103 Operand *Val = Instr->getArg(0); | 2103 Operand *Val = Instr->getArg(0); |
| 2104 Variable *ValLoR; | 2104 Variable *ValLoR; |
| 2105 Variable *ValHiR = nullptr; | 2105 Variable *ValHiR = nullptr; |
| 2106 if (Val->getType() == IceType_i64) { | 2106 if (Val->getType() == IceType_i64) { |
| 2107 Val = legalizeUndef(Val); | 2107 Val = legalizeUndef(Val); |
| 2108 ValLoR = legalizeToVar(loOperand(Val)); | 2108 ValLoR = legalizeToReg(loOperand(Val)); |
| 2109 ValHiR = legalizeToVar(hiOperand(Val)); | 2109 ValHiR = legalizeToReg(hiOperand(Val)); |
| 2110 Variable *TLo = makeReg(IceType_i32); | 2110 Variable *TLo = makeReg(IceType_i32); |
| 2111 Variable *THi = makeReg(IceType_i32); | 2111 Variable *THi = makeReg(IceType_i32); |
| 2112 _rbit(TLo, ValLoR); | 2112 _rbit(TLo, ValLoR); |
| 2113 _rbit(THi, ValHiR); | 2113 _rbit(THi, ValHiR); |
| 2114 ValLoR = THi; | 2114 ValLoR = THi; |
| 2115 ValHiR = TLo; | 2115 ValHiR = TLo; |
| 2116 } else { | 2116 } else { |
| 2117 ValLoR = legalizeToVar(Val); | 2117 ValLoR = legalizeToReg(Val); |
| 2118 Variable *T = makeReg(IceType_i32); | 2118 Variable *T = makeReg(IceType_i32); |
| 2119 _rbit(T, ValLoR); | 2119 _rbit(T, ValLoR); |
| 2120 ValLoR = T; | 2120 ValLoR = T; |
| 2121 } | 2121 } |
| 2122 lowerCLZ(Instr->getDest(), ValLoR, ValHiR); | 2122 lowerCLZ(Instr->getDest(), ValLoR, ValHiR); |
| 2123 return; | 2123 return; |
| 2124 } | 2124 } |
| 2125 case Intrinsics::Fabs: { | 2125 case Intrinsics::Fabs: { |
| 2126 UnimplementedError(Func->getContext()->getFlags()); | 2126 UnimplementedError(Func->getContext()->getFlags()); |
| 2127 return; | 2127 return; |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2265 void TargetARM32::lowerPhi(const InstPhi * /*Inst*/) { | 2265 void TargetARM32::lowerPhi(const InstPhi * /*Inst*/) { |
| 2266 Func->setError("Phi found in regular instruction list"); | 2266 Func->setError("Phi found in regular instruction list"); |
| 2267 } | 2267 } |
| 2268 | 2268 |
| 2269 void TargetARM32::lowerRet(const InstRet *Inst) { | 2269 void TargetARM32::lowerRet(const InstRet *Inst) { |
| 2270 Variable *Reg = nullptr; | 2270 Variable *Reg = nullptr; |
| 2271 if (Inst->hasRetValue()) { | 2271 if (Inst->hasRetValue()) { |
| 2272 Operand *Src0 = Inst->getRetValue(); | 2272 Operand *Src0 = Inst->getRetValue(); |
| 2273 if (Src0->getType() == IceType_i64) { | 2273 if (Src0->getType() == IceType_i64) { |
| 2274 Src0 = legalizeUndef(Src0); | 2274 Src0 = legalizeUndef(Src0); |
| 2275 Variable *R0 = legalizeToVar(loOperand(Src0), RegARM32::Reg_r0); | 2275 Variable *R0 = legalizeToReg(loOperand(Src0), RegARM32::Reg_r0); |
| 2276 Variable *R1 = legalizeToVar(hiOperand(Src0), RegARM32::Reg_r1); | 2276 Variable *R1 = legalizeToReg(hiOperand(Src0), RegARM32::Reg_r1); |
| 2277 Reg = R0; | 2277 Reg = R0; |
| 2278 Context.insert(InstFakeUse::create(Func, R1)); | 2278 Context.insert(InstFakeUse::create(Func, R1)); |
| 2279 } else if (isScalarFloatingType(Src0->getType())) { | 2279 } else if (isScalarFloatingType(Src0->getType())) { |
| 2280 UnimplementedError(Func->getContext()->getFlags()); | 2280 UnimplementedError(Func->getContext()->getFlags()); |
| 2281 } else if (isVectorType(Src0->getType())) { | 2281 } else if (isVectorType(Src0->getType())) { |
| 2282 UnimplementedError(Func->getContext()->getFlags()); | 2282 UnimplementedError(Func->getContext()->getFlags()); |
| 2283 } else { | 2283 } else { |
| 2284 Operand *Src0F = legalize(Src0, Legal_Reg | Legal_Flex); | 2284 Operand *Src0F = legalize(Src0, Legal_Reg | Legal_Flex); |
| 2285 _mov(Reg, Src0F, CondARM32::AL, RegARM32::Reg_r0); | 2285 _mov(Reg, Src0F, CondARM32::AL, RegARM32::Reg_r0); |
| 2286 } | 2286 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2310 if (isVectorType(DestTy)) { | 2310 if (isVectorType(DestTy)) { |
| 2311 UnimplementedError(Func->getContext()->getFlags()); | 2311 UnimplementedError(Func->getContext()->getFlags()); |
| 2312 return; | 2312 return; |
| 2313 } | 2313 } |
| 2314 if (isFloatingType(DestTy)) { | 2314 if (isFloatingType(DestTy)) { |
| 2315 UnimplementedError(Func->getContext()->getFlags()); | 2315 UnimplementedError(Func->getContext()->getFlags()); |
| 2316 return; | 2316 return; |
| 2317 } | 2317 } |
| 2318 // TODO(jvoung): handle folding opportunities. | 2318 // TODO(jvoung): handle folding opportunities. |
| 2319 // cmp cond, #0; mov t, SrcF; mov_cond t, SrcT; mov dest, t | 2319 // cmp cond, #0; mov t, SrcF; mov_cond t, SrcT; mov dest, t |
| 2320 Variable *CmpOpnd0 = legalizeToVar(Condition); | 2320 Variable *CmpOpnd0 = legalizeToReg(Condition); |
| 2321 Operand *CmpOpnd1 = Ctx->getConstantZero(IceType_i32); | 2321 Operand *CmpOpnd1 = Ctx->getConstantZero(IceType_i32); |
| 2322 _cmp(CmpOpnd0, CmpOpnd1); | 2322 _cmp(CmpOpnd0, CmpOpnd1); |
| 2323 CondARM32::Cond Cond = CondARM32::NE; | 2323 CondARM32::Cond Cond = CondARM32::NE; |
| 2324 if (DestTy == IceType_i64) { | 2324 if (DestTy == IceType_i64) { |
| 2325 SrcT = legalizeUndef(SrcT); | 2325 SrcT = legalizeUndef(SrcT); |
| 2326 SrcF = legalizeUndef(SrcF); | 2326 SrcF = legalizeUndef(SrcF); |
| 2327 // Set the low portion. | 2327 // Set the low portion. |
| 2328 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 2328 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| 2329 Variable *TLo = nullptr; | 2329 Variable *TLo = nullptr; |
| 2330 Operand *SrcFLo = legalize(loOperand(SrcF), Legal_Reg | Legal_Flex); | 2330 Operand *SrcFLo = legalize(loOperand(SrcF), Legal_Reg | Legal_Flex); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2351 } | 2351 } |
| 2352 | 2352 |
| 2353 void TargetARM32::lowerStore(const InstStore *Inst) { | 2353 void TargetARM32::lowerStore(const InstStore *Inst) { |
| 2354 Operand *Value = Inst->getData(); | 2354 Operand *Value = Inst->getData(); |
| 2355 Operand *Addr = Inst->getAddr(); | 2355 Operand *Addr = Inst->getAddr(); |
| 2356 OperandARM32Mem *NewAddr = formMemoryOperand(Addr, Value->getType()); | 2356 OperandARM32Mem *NewAddr = formMemoryOperand(Addr, Value->getType()); |
| 2357 Type Ty = NewAddr->getType(); | 2357 Type Ty = NewAddr->getType(); |
| 2358 | 2358 |
| 2359 if (Ty == IceType_i64) { | 2359 if (Ty == IceType_i64) { |
| 2360 Value = legalizeUndef(Value); | 2360 Value = legalizeUndef(Value); |
| 2361 Variable *ValueHi = legalizeToVar(hiOperand(Value)); | 2361 Variable *ValueHi = legalizeToReg(hiOperand(Value)); |
| 2362 Variable *ValueLo = legalizeToVar(loOperand(Value)); | 2362 Variable *ValueLo = legalizeToReg(loOperand(Value)); |
| 2363 _str(ValueHi, llvm::cast<OperandARM32Mem>(hiOperand(NewAddr))); | 2363 _str(ValueHi, llvm::cast<OperandARM32Mem>(hiOperand(NewAddr))); |
| 2364 _str(ValueLo, llvm::cast<OperandARM32Mem>(loOperand(NewAddr))); | 2364 _str(ValueLo, llvm::cast<OperandARM32Mem>(loOperand(NewAddr))); |
| 2365 } else if (isVectorType(Ty)) { | 2365 } else if (isVectorType(Ty)) { |
| 2366 UnimplementedError(Func->getContext()->getFlags()); | 2366 UnimplementedError(Func->getContext()->getFlags()); |
| 2367 } else { | 2367 } else { |
| 2368 Variable *ValueR = legalizeToVar(Value); | 2368 Variable *ValueR = legalizeToReg(Value); |
| 2369 _str(ValueR, NewAddr); | 2369 _str(ValueR, NewAddr); |
| 2370 } | 2370 } |
| 2371 } | 2371 } |
| 2372 | 2372 |
| 2373 void TargetARM32::doAddressOptStore() { | 2373 void TargetARM32::doAddressOptStore() { |
| 2374 UnimplementedError(Func->getContext()->getFlags()); | 2374 UnimplementedError(Func->getContext()->getFlags()); |
| 2375 } | 2375 } |
| 2376 | 2376 |
| 2377 void TargetARM32::lowerSwitch(const InstSwitch *Inst) { | 2377 void TargetARM32::lowerSwitch(const InstSwitch *Inst) { |
| 2378 // This implements the most naive possible lowering. | 2378 // This implements the most naive possible lowering. |
| 2379 // cmp a,val[0]; jeq label[0]; cmp a,val[1]; jeq label[1]; ... jmp default | 2379 // cmp a,val[0]; jeq label[0]; cmp a,val[1]; jeq label[1]; ... jmp default |
| 2380 Operand *Src0 = Inst->getComparison(); | 2380 Operand *Src0 = Inst->getComparison(); |
| 2381 SizeT NumCases = Inst->getNumCases(); | 2381 SizeT NumCases = Inst->getNumCases(); |
| 2382 if (Src0->getType() == IceType_i64) { | 2382 if (Src0->getType() == IceType_i64) { |
| 2383 Src0 = legalizeUndef(Src0); | 2383 Src0 = legalizeUndef(Src0); |
| 2384 Variable *Src0Lo = legalizeToVar(loOperand(Src0)); | 2384 Variable *Src0Lo = legalizeToReg(loOperand(Src0)); |
| 2385 Variable *Src0Hi = legalizeToVar(hiOperand(Src0)); | 2385 Variable *Src0Hi = legalizeToReg(hiOperand(Src0)); |
| 2386 for (SizeT I = 0; I < NumCases; ++I) { | 2386 for (SizeT I = 0; I < NumCases; ++I) { |
| 2387 Operand *ValueLo = Ctx->getConstantInt32(Inst->getValue(I)); | 2387 Operand *ValueLo = Ctx->getConstantInt32(Inst->getValue(I)); |
| 2388 Operand *ValueHi = Ctx->getConstantInt32(Inst->getValue(I) >> 32); | 2388 Operand *ValueHi = Ctx->getConstantInt32(Inst->getValue(I) >> 32); |
| 2389 ValueLo = legalize(ValueLo, Legal_Reg | Legal_Flex); | 2389 ValueLo = legalize(ValueLo, Legal_Reg | Legal_Flex); |
| 2390 ValueHi = legalize(ValueHi, Legal_Reg | Legal_Flex); | 2390 ValueHi = legalize(ValueHi, Legal_Reg | Legal_Flex); |
| 2391 _cmp(Src0Lo, ValueLo); | 2391 _cmp(Src0Lo, ValueLo); |
| 2392 _cmp(Src0Hi, ValueHi, CondARM32::EQ); | 2392 _cmp(Src0Hi, ValueHi, CondARM32::EQ); |
| 2393 _br(Inst->getLabel(I), CondARM32::EQ); | 2393 _br(Inst->getLabel(I), CondARM32::EQ); |
| 2394 } | 2394 } |
| 2395 _br(Inst->getLabelDefault()); | 2395 _br(Inst->getLabelDefault()); |
| 2396 return; | 2396 return; |
| 2397 } | 2397 } |
| 2398 | 2398 |
| 2399 // 32 bit integer | 2399 // 32 bit integer |
| 2400 Variable *Src0Var = legalizeToVar(Src0); | 2400 Variable *Src0Var = legalizeToReg(Src0); |
| 2401 for (SizeT I = 0; I < NumCases; ++I) { | 2401 for (SizeT I = 0; I < NumCases; ++I) { |
| 2402 Operand *Value = Ctx->getConstantInt32(Inst->getValue(I)); | 2402 Operand *Value = Ctx->getConstantInt32(Inst->getValue(I)); |
| 2403 Value = legalize(Value, Legal_Reg | Legal_Flex); | 2403 Value = legalize(Value, Legal_Reg | Legal_Flex); |
| 2404 _cmp(Src0Var, Value); | 2404 _cmp(Src0Var, Value); |
| 2405 _br(Inst->getLabel(I), CondARM32::EQ); | 2405 _br(Inst->getLabel(I), CondARM32::EQ); |
| 2406 } | 2406 } |
| 2407 _br(Inst->getLabelDefault()); | 2407 _br(Inst->getLabelDefault()); |
| 2408 } | 2408 } |
| 2409 | 2409 |
| 2410 void TargetARM32::lowerUnreachable(const InstUnreachable * /*Inst*/) { | 2410 void TargetARM32::lowerUnreachable(const InstUnreachable * /*Inst*/) { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2458 // (e.g., OperandARM32Mem and !Legal_Mem), we can always copy | 2458 // (e.g., OperandARM32Mem and !Legal_Mem), we can always copy |
| 2459 // to a register. | 2459 // to a register. |
| 2460 if (auto Mem = llvm::dyn_cast<OperandARM32Mem>(From)) { | 2460 if (auto Mem = llvm::dyn_cast<OperandARM32Mem>(From)) { |
| 2461 // Before doing anything with a Mem operand, we need to ensure | 2461 // Before doing anything with a Mem operand, we need to ensure |
| 2462 // that the Base and Index components are in physical registers. | 2462 // that the Base and Index components are in physical registers. |
| 2463 Variable *Base = Mem->getBase(); | 2463 Variable *Base = Mem->getBase(); |
| 2464 Variable *Index = Mem->getIndex(); | 2464 Variable *Index = Mem->getIndex(); |
| 2465 Variable *RegBase = nullptr; | 2465 Variable *RegBase = nullptr; |
| 2466 Variable *RegIndex = nullptr; | 2466 Variable *RegIndex = nullptr; |
| 2467 if (Base) { | 2467 if (Base) { |
| 2468 RegBase = legalizeToVar(Base); | 2468 RegBase = legalizeToReg(Base); |
| 2469 } | 2469 } |
| 2470 if (Index) { | 2470 if (Index) { |
| 2471 RegIndex = legalizeToVar(Index); | 2471 RegIndex = legalizeToReg(Index); |
| 2472 } | 2472 } |
| 2473 // Create a new operand if there was a change. | 2473 // Create a new operand if there was a change. |
| 2474 if (Base != RegBase || Index != RegIndex) { | 2474 if (Base != RegBase || Index != RegIndex) { |
| 2475 // There is only a reg +/- reg or reg + imm form. | 2475 // There is only a reg +/- reg or reg + imm form. |
| 2476 // Figure out which to re-create. | 2476 // Figure out which to re-create. |
| 2477 if (Mem->isRegReg()) { | 2477 if (Mem->isRegReg()) { |
| 2478 Mem = OperandARM32Mem::create(Func, Ty, RegBase, RegIndex, | 2478 Mem = OperandARM32Mem::create(Func, Ty, RegBase, RegIndex, |
| 2479 Mem->getShiftOp(), Mem->getShiftAmt(), | 2479 Mem->getShiftOp(), Mem->getShiftAmt(), |
| 2480 Mem->getAddrMode()); | 2480 Mem->getAddrMode()); |
| 2481 } else { | 2481 } else { |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2576 From = copyToReg(From, RegNum); | 2576 From = copyToReg(From, RegNum); |
| 2577 } | 2577 } |
| 2578 return From; | 2578 return From; |
| 2579 } | 2579 } |
| 2580 llvm_unreachable("Unhandled operand kind in legalize()"); | 2580 llvm_unreachable("Unhandled operand kind in legalize()"); |
| 2581 | 2581 |
| 2582 return From; | 2582 return From; |
| 2583 } | 2583 } |
| 2584 | 2584 |
| 2585 /// Provide a trivial wrapper to legalize() for this common usage. | 2585 /// Provide a trivial wrapper to legalize() for this common usage. |
| 2586 Variable *TargetARM32::legalizeToVar(Operand *From, int32_t RegNum) { | 2586 Variable *TargetARM32::legalizeToReg(Operand *From, int32_t RegNum) { |
| 2587 return llvm::cast<Variable>(legalize(From, Legal_Reg, RegNum)); | 2587 return llvm::cast<Variable>(legalize(From, Legal_Reg, RegNum)); |
| 2588 } | 2588 } |
| 2589 | 2589 |
| 2590 /// Legalize undef values to concrete values. | 2590 /// Legalize undef values to concrete values. |
| 2591 Operand *TargetARM32::legalizeUndef(Operand *From, int32_t RegNum) { | 2591 Operand *TargetARM32::legalizeUndef(Operand *From, int32_t RegNum) { |
| 2592 Type Ty = From->getType(); | 2592 Type Ty = From->getType(); |
| 2593 if (llvm::isa<ConstantUndef>(From)) { | 2593 if (llvm::isa<ConstantUndef>(From)) { |
| 2594 // Lower undefs to zero. Another option is to lower undefs to an | 2594 // Lower undefs to zero. Another option is to lower undefs to an |
| 2595 // uninitialized register; however, using an uninitialized register | 2595 // uninitialized register; however, using an uninitialized register |
| 2596 // results in less predictable code. | 2596 // results in less predictable code. |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2613 OperandARM32Mem *Mem = llvm::dyn_cast<OperandARM32Mem>(Operand); | 2613 OperandARM32Mem *Mem = llvm::dyn_cast<OperandARM32Mem>(Operand); |
| 2614 // It may be the case that address mode optimization already creates | 2614 // It may be the case that address mode optimization already creates |
| 2615 // an OperandARM32Mem, so in that case it wouldn't need another level | 2615 // an OperandARM32Mem, so in that case it wouldn't need another level |
| 2616 // of transformation. | 2616 // of transformation. |
| 2617 if (Mem) { | 2617 if (Mem) { |
| 2618 return llvm::cast<OperandARM32Mem>(legalize(Mem)); | 2618 return llvm::cast<OperandARM32Mem>(legalize(Mem)); |
| 2619 } | 2619 } |
| 2620 // If we didn't do address mode optimization, then we only | 2620 // If we didn't do address mode optimization, then we only |
| 2621 // have a base/offset to work with. ARM always requires a base | 2621 // have a base/offset to work with. ARM always requires a base |
| 2622 // register, so just use that to hold the operand. | 2622 // register, so just use that to hold the operand. |
| 2623 Variable *Base = legalizeToVar(Operand); | 2623 Variable *Base = legalizeToReg(Operand); |
| 2624 return OperandARM32Mem::create( | 2624 return OperandARM32Mem::create( |
| 2625 Func, Ty, Base, | 2625 Func, Ty, Base, |
| 2626 llvm::cast<ConstantInteger32>(Ctx->getConstantZero(IceType_i32))); | 2626 llvm::cast<ConstantInteger32>(Ctx->getConstantZero(IceType_i32))); |
| 2627 } | 2627 } |
| 2628 | 2628 |
| 2629 Variable *TargetARM32::makeReg(Type Type, int32_t RegNum) { | 2629 Variable *TargetARM32::makeReg(Type Type, int32_t RegNum) { |
| 2630 // There aren't any 64-bit integer registers for ARM32. | 2630 // There aren't any 64-bit integer registers for ARM32. |
| 2631 assert(Type != IceType_i64); | 2631 assert(Type != IceType_i64); |
| 2632 Variable *Reg = Func->makeVariable(Type); | 2632 Variable *Reg = Func->makeVariable(Type); |
| 2633 if (RegNum == Variable::NoRegister) | 2633 if (RegNum == Variable::NoRegister) |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2764 << ".eabi_attribute 68, 1 @ Tag_Virtualization_use\n"; | 2764 << ".eabi_attribute 68, 1 @ Tag_Virtualization_use\n"; |
| 2765 if (CPUFeatures.hasFeature(TargetARM32Features::HWDivArm)) { | 2765 if (CPUFeatures.hasFeature(TargetARM32Features::HWDivArm)) { |
| 2766 Str << ".eabi_attribute 44, 2 @ Tag_DIV_use\n"; | 2766 Str << ".eabi_attribute 44, 2 @ Tag_DIV_use\n"; |
| 2767 } | 2767 } |
| 2768 // Technically R9 is used for TLS with Sandboxing, and we reserve it. | 2768 // Technically R9 is used for TLS with Sandboxing, and we reserve it. |
| 2769 // However, for compatibility with current NaCl LLVM, don't claim that. | 2769 // However, for compatibility with current NaCl LLVM, don't claim that. |
| 2770 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; | 2770 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; |
| 2771 } | 2771 } |
| 2772 | 2772 |
| 2773 } // end of namespace Ice | 2773 } // end of namespace Ice |
| OLD | NEW |