Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(292)

Side by Side Diff: src/IceTargetLoweringARM32.cpp

Issue 1214693004: ARM lowering integer divide and remainder, with div by 0 checks. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: review fixes Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/IceTargetLoweringARM32.h ('k') | tests_lit/llvm2ice_tests/64bit.pnacl.ll » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 uint32_t applyStackAlignmentTy(uint32_t Value, Type Ty) { 134 uint32_t applyStackAlignmentTy(uint32_t Value, Type Ty) {
135 // Use natural alignment, except that normally (non-NaCl) ARM only 135 // Use natural alignment, except that normally (non-NaCl) ARM only
136 // aligns vectors to 8 bytes. 136 // aligns vectors to 8 bytes.
137 // TODO(jvoung): Check this ... 137 // TODO(jvoung): Check this ...
138 size_t typeAlignInBytes = typeWidthInBytes(Ty); 138 size_t typeAlignInBytes = typeWidthInBytes(Ty);
139 if (isVectorType(Ty)) 139 if (isVectorType(Ty))
140 typeAlignInBytes = 8; 140 typeAlignInBytes = 8;
141 return Utils::applyAlignment(Value, typeAlignInBytes); 141 return Utils::applyAlignment(Value, typeAlignInBytes);
142 } 142 }
143 143
144 // Conservatively check if at compile time we know that the operand is
145 // definitely a non-zero integer.
146 bool isGuaranteedNonzeroInt(const Operand *Op) {
147 if (auto *Const = llvm::dyn_cast_or_null<ConstantInteger32>(Op)) {
148 return Const->getValue() != 0;
149 }
150 return false;
151 }
152
144 } // end of anonymous namespace 153 } // end of anonymous namespace
145 154
146 TargetARM32::TargetARM32(Cfg *Func) : TargetLowering(Func) { 155 TargetARM32Features::TargetARM32Features(const ClFlags &Flags) {
147 static_assert( 156 static_assert(
148 (ARM32InstructionSet::End - ARM32InstructionSet::Begin) == 157 (ARM32InstructionSet::End - ARM32InstructionSet::Begin) ==
149 (TargetInstructionSet::ARM32InstructionSet_End - 158 (TargetInstructionSet::ARM32InstructionSet_End -
150 TargetInstructionSet::ARM32InstructionSet_Begin), 159 TargetInstructionSet::ARM32InstructionSet_Begin),
151 "ARM32InstructionSet range different from TargetInstructionSet"); 160 "ARM32InstructionSet range different from TargetInstructionSet");
152 if (Func->getContext()->getFlags().getTargetInstructionSet() != 161 if (Flags.getTargetInstructionSet() !=
153 TargetInstructionSet::BaseInstructionSet) { 162 TargetInstructionSet::BaseInstructionSet) {
154 InstructionSet = static_cast<ARM32InstructionSet>( 163 InstructionSet = static_cast<ARM32InstructionSet>(
155 (Func->getContext()->getFlags().getTargetInstructionSet() - 164 (Flags.getTargetInstructionSet() -
156 TargetInstructionSet::ARM32InstructionSet_Begin) + 165 TargetInstructionSet::ARM32InstructionSet_Begin) +
157 ARM32InstructionSet::Begin); 166 ARM32InstructionSet::Begin);
158 } 167 }
168 }
169
170 TargetARM32::TargetARM32(Cfg *Func)
171 : TargetLowering(Func), CPUFeatures(Func->getContext()->getFlags()) {
159 // TODO: Don't initialize IntegerRegisters and friends every time. 172 // TODO: Don't initialize IntegerRegisters and friends every time.
160 // Instead, initialize in some sort of static initializer for the 173 // Instead, initialize in some sort of static initializer for the
161 // class. 174 // class.
162 llvm::SmallBitVector IntegerRegisters(RegARM32::Reg_NUM); 175 llvm::SmallBitVector IntegerRegisters(RegARM32::Reg_NUM);
163 llvm::SmallBitVector FloatRegisters(RegARM32::Reg_NUM); 176 llvm::SmallBitVector FloatRegisters(RegARM32::Reg_NUM);
164 llvm::SmallBitVector VectorRegisters(RegARM32::Reg_NUM); 177 llvm::SmallBitVector VectorRegisters(RegARM32::Reg_NUM);
165 llvm::SmallBitVector InvalidRegisters(RegARM32::Reg_NUM); 178 llvm::SmallBitVector InvalidRegisters(RegARM32::Reg_NUM);
166 ScratchRegs.resize(RegARM32::Reg_NUM); 179 ScratchRegs.resize(RegARM32::Reg_NUM);
167 #define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \ 180 #define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \
168 isFP) \ 181 isFP) \
(...skipping 833 matching lines...) Expand 10 before | Expand all | Expand 10 after
1002 Variable *T = makeReg(IceType_i32); 1015 Variable *T = makeReg(IceType_i32);
1003 _mov(T, TotalSize); 1016 _mov(T, TotalSize);
1004 Operand *AddAmount = legalize(Ctx->getConstantInt32(Alignment - 1)); 1017 Operand *AddAmount = legalize(Ctx->getConstantInt32(Alignment - 1));
1005 _add(T, T, AddAmount); 1018 _add(T, T, AddAmount);
1006 alignRegisterPow2(T, Alignment); 1019 alignRegisterPow2(T, Alignment);
1007 _sub(SP, SP, T); 1020 _sub(SP, SP, T);
1008 } 1021 }
1009 _mov(Dest, SP); 1022 _mov(Dest, SP);
1010 } 1023 }
1011 1024
1025 void TargetARM32::div0Check(Type Ty, Operand *SrcLo, Operand *SrcHi) {
1026 if (isGuaranteedNonzeroInt(SrcLo) || isGuaranteedNonzeroInt(SrcHi))
1027 return;
1028 Variable *SrcLoReg = legalizeToVar(SrcLo);
1029 switch (Ty) {
1030 default:
1031 llvm_unreachable("Unexpected type");
1032 case IceType_i8: {
1033 Operand *Mask =
1034 legalize(Ctx->getConstantInt32(0xFF), Legal_Reg | Legal_Flex);
1035 _tst(SrcLoReg, Mask);
1036 break;
1037 }
1038 case IceType_i16: {
1039 Operand *Mask =
1040 legalize(Ctx->getConstantInt32(0xFFFF), Legal_Reg | Legal_Flex);
1041 _tst(SrcLoReg, Mask);
1042 break;
1043 }
1044 case IceType_i32: {
1045 _tst(SrcLoReg, SrcLoReg);
1046 break;
1047 }
1048 case IceType_i64: {
1049 Variable *ScratchReg = makeReg(IceType_i32);
1050 _orrs(ScratchReg, SrcLoReg, SrcHi);
1051 // ScratchReg isn't going to be used, but we need the
1052 // side-effect of setting flags from this operation.
1053 Context.insert(InstFakeUse::create(Func, ScratchReg));
1054 }
1055 }
1056 InstARM32Label *Label = InstARM32Label::create(Func, this);
1057 _br(Label, CondARM32::NE);
1058 _trap();
1059 Context.insert(Label);
1060 }
1061
1062 void TargetARM32::lowerIDivRem(Variable *Dest, Variable *T, Variable *Src0R,
1063 Operand *Src1, ExtInstr ExtFunc,
1064 DivInstr DivFunc, const char *DivHelperName,
1065 bool IsRemainder) {
1066 div0Check(Dest->getType(), Src1, nullptr);
1067 Variable *Src1R = legalizeToVar(Src1);
1068 Variable *T0R = Src0R;
1069 Variable *T1R = Src1R;
1070 if (Dest->getType() != IceType_i32) {
1071 T0R = makeReg(IceType_i32);
1072 (this->*ExtFunc)(T0R, Src0R, CondARM32::AL);
1073 T1R = makeReg(IceType_i32);
1074 (this->*ExtFunc)(T1R, Src1R, CondARM32::AL);
1075 }
1076 if (hasCPUFeature(TargetARM32Features::HWDivArm)) {
1077 (this->*DivFunc)(T, T0R, T1R, CondARM32::AL);
1078 if (IsRemainder) {
1079 Variable *T2 = makeReg(IceType_i32);
1080 _mls(T2, T, T1R, T0R);
1081 T = T2;
1082 }
1083 _mov(Dest, T);
1084 } else {
1085 constexpr SizeT MaxSrcs = 2;
1086 InstCall *Call = makeHelperCall(DivHelperName, Dest, MaxSrcs);
1087 Call->addArg(T0R);
1088 Call->addArg(T1R);
1089 lowerCall(Call);
1090 }
1091 return;
1092 }
1093
1012 void TargetARM32::lowerArithmetic(const InstArithmetic *Inst) { 1094 void TargetARM32::lowerArithmetic(const InstArithmetic *Inst) {
1013 Variable *Dest = Inst->getDest(); 1095 Variable *Dest = Inst->getDest();
1014 // 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
1015 // 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
1016 // instruction. E.g., reverse subtract with immediate, register vs 1098 // instruction. E.g., reverse subtract with immediate, register vs
1017 // register, immediate. 1099 // register, immediate.
1018 // 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
1019 // bits can be flipped and a different operation applied. 1101 // bits can be flipped and a different operation applied.
1020 // 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.
1021 Operand *Src0 = Inst->getSrc(0); 1103 Operand *Src0 = Inst->getSrc(0);
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
1175 Pred); 1257 Pred);
1176 _mov(DestLo, T_Lo); 1258 _mov(DestLo, T_Lo);
1177 Variable *T_Hi = makeReg(IceType_i32); 1259 Variable *T_Hi = makeReg(IceType_i32);
1178 _mov(T_Hi, OperandARM32FlexReg::create(Func, IceType_i32, Src0RHi, 1260 _mov(T_Hi, OperandARM32FlexReg::create(Func, IceType_i32, Src0RHi,
1179 RShiftKind, Src1RLo)); 1261 RShiftKind, Src1RLo));
1180 _mov(DestHi, T_Hi); 1262 _mov(DestHi, T_Hi);
1181 } break; 1263 } break;
1182 case InstArithmetic::Udiv: 1264 case InstArithmetic::Udiv:
1183 case InstArithmetic::Sdiv: 1265 case InstArithmetic::Sdiv:
1184 case InstArithmetic::Urem: 1266 case InstArithmetic::Urem:
1185 case InstArithmetic::Srem: 1267 case InstArithmetic::Srem: {
1186 UnimplementedError(Func->getContext()->getFlags()); 1268 // Check for divide by 0 (ARM normally doesn't trap, but we want it
1187 break; 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;
1307 }
1188 case InstArithmetic::Fadd: 1308 case InstArithmetic::Fadd:
1189 case InstArithmetic::Fsub: 1309 case InstArithmetic::Fsub:
1190 case InstArithmetic::Fmul: 1310 case InstArithmetic::Fmul:
1191 case InstArithmetic::Fdiv: 1311 case InstArithmetic::Fdiv:
1192 case InstArithmetic::Frem: 1312 case InstArithmetic::Frem:
1193 llvm_unreachable("FP instruction with i64 type"); 1313 llvm_unreachable("FP instruction with i64 type");
1194 break; 1314 break;
1195 } 1315 }
1196 } else if (isVectorType(Dest->getType())) { 1316 } else if (isVectorType(Dest->getType())) {
1197 UnimplementedError(Func->getContext()->getFlags()); 1317 UnimplementedError(Func->getContext()->getFlags());
1198 } else { // Dest->getType() is non-i64 scalar 1318 } else { // Dest->getType() is non-i64 scalar
1199 Variable *Src0R = legalizeToVar(Inst->getSrc(0)); 1319 Variable *Src0R = legalizeToVar(Inst->getSrc(0));
1200 Src1 = legalize(Inst->getSrc(1), Legal_Reg | Legal_Flex); 1320 Operand *Src1RF = legalize(Inst->getSrc(1), Legal_Reg | Legal_Flex);
1201 Variable *T = makeReg(Dest->getType()); 1321 Variable *T = makeReg(Dest->getType());
1202 switch (Inst->getOp()) { 1322 switch (Inst->getOp()) {
1203 case InstArithmetic::_num: 1323 case InstArithmetic::_num:
1204 llvm_unreachable("Unknown arithmetic operator"); 1324 llvm_unreachable("Unknown arithmetic operator");
1205 break; 1325 break;
1206 case InstArithmetic::Add: { 1326 case InstArithmetic::Add: {
1207 _add(T, Src0R, Src1); 1327 _add(T, Src0R, Src1RF);
1208 _mov(Dest, T); 1328 _mov(Dest, T);
1209 } break; 1329 } break;
1210 case InstArithmetic::And: { 1330 case InstArithmetic::And: {
1211 _and(T, Src0R, Src1); 1331 _and(T, Src0R, Src1RF);
1212 _mov(Dest, T); 1332 _mov(Dest, T);
1213 } break; 1333 } break;
1214 case InstArithmetic::Or: { 1334 case InstArithmetic::Or: {
1215 _orr(T, Src0R, Src1); 1335 _orr(T, Src0R, Src1RF);
1216 _mov(Dest, T); 1336 _mov(Dest, T);
1217 } break; 1337 } break;
1218 case InstArithmetic::Xor: { 1338 case InstArithmetic::Xor: {
1219 _eor(T, Src0R, Src1); 1339 _eor(T, Src0R, Src1RF);
1220 _mov(Dest, T); 1340 _mov(Dest, T);
1221 } break; 1341 } break;
1222 case InstArithmetic::Sub: { 1342 case InstArithmetic::Sub: {
1223 _sub(T, Src0R, Src1); 1343 _sub(T, Src0R, Src1RF);
1224 _mov(Dest, T); 1344 _mov(Dest, T);
1225 } break; 1345 } break;
1226 case InstArithmetic::Mul: { 1346 case InstArithmetic::Mul: {
1227 Variable *Src1R = legalizeToVar(Src1); 1347 Variable *Src1R = legalizeToVar(Src1RF);
1228 _mul(T, Src0R, Src1R); 1348 _mul(T, Src0R, Src1R);
1229 _mov(Dest, T); 1349 _mov(Dest, T);
1230 } break; 1350 } break;
1231 case InstArithmetic::Shl: 1351 case InstArithmetic::Shl:
1232 _lsl(T, Src0R, Src1); 1352 _lsl(T, Src0R, Src1RF);
1233 _mov(Dest, T); 1353 _mov(Dest, T);
1234 break; 1354 break;
1235 case InstArithmetic::Lshr: 1355 case InstArithmetic::Lshr:
1236 _lsr(T, Src0R, Src1); 1356 _lsr(T, Src0R, Src1RF);
1237 _mov(Dest, T); 1357 _mov(Dest, T);
1238 break; 1358 break;
1239 case InstArithmetic::Ashr: 1359 case InstArithmetic::Ashr:
1240 _asr(T, Src0R, Src1); 1360 _asr(T, Src0R, Src1RF);
1241 _mov(Dest, T); 1361 _mov(Dest, T);
1242 break; 1362 break;
1243 case InstArithmetic::Udiv: 1363 case InstArithmetic::Udiv: {
1244 UnimplementedError(Func->getContext()->getFlags()); 1364 constexpr bool IsRemainder = false;
1245 break; 1365 lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_uxt,
1246 case InstArithmetic::Sdiv: 1366 &TargetARM32::_udiv, H_udiv_i32, IsRemainder);
1247 UnimplementedError(Func->getContext()->getFlags()); 1367 return;
1248 break; 1368 }
1249 case InstArithmetic::Urem: 1369 case InstArithmetic::Sdiv: {
1250 UnimplementedError(Func->getContext()->getFlags()); 1370 constexpr bool IsRemainder = false;
1251 break; 1371 lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_sxt,
1252 case InstArithmetic::Srem: 1372 &TargetARM32::_sdiv, H_sdiv_i32, IsRemainder);
1253 UnimplementedError(Func->getContext()->getFlags()); 1373 return;
1254 break; 1374 }
1375 case InstArithmetic::Urem: {
1376 constexpr bool IsRemainder = true;
1377 lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_uxt,
1378 &TargetARM32::_udiv, H_urem_i32, IsRemainder);
1379 return;
1380 }
1381 case InstArithmetic::Srem: {
1382 constexpr bool IsRemainder = true;
1383 lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_sxt,
1384 &TargetARM32::_sdiv, H_srem_i32, IsRemainder);
1385 return;
1386 }
1255 case InstArithmetic::Fadd: 1387 case InstArithmetic::Fadd:
1256 UnimplementedError(Func->getContext()->getFlags()); 1388 UnimplementedError(Func->getContext()->getFlags());
1257 break; 1389 break;
1258 case InstArithmetic::Fsub: 1390 case InstArithmetic::Fsub:
1259 UnimplementedError(Func->getContext()->getFlags()); 1391 UnimplementedError(Func->getContext()->getFlags());
1260 break; 1392 break;
1261 case InstArithmetic::Fmul: 1393 case InstArithmetic::Fmul:
1262 UnimplementedError(Func->getContext()->getFlags()); 1394 UnimplementedError(Func->getContext()->getFlags());
1263 break; 1395 break;
1264 case InstArithmetic::Fdiv: 1396 case InstArithmetic::Fdiv:
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1315 if (Inst->isUnconditional()) { 1447 if (Inst->isUnconditional()) {
1316 _br(Inst->getTargetUnconditional()); 1448 _br(Inst->getTargetUnconditional());
1317 return; 1449 return;
1318 } 1450 }
1319 Operand *Cond = Inst->getCondition(); 1451 Operand *Cond = Inst->getCondition();
1320 // TODO(jvoung): Handle folding opportunities. 1452 // TODO(jvoung): Handle folding opportunities.
1321 1453
1322 Variable *Src0R = legalizeToVar(Cond); 1454 Variable *Src0R = legalizeToVar(Cond);
1323 Constant *Zero = Ctx->getConstantZero(IceType_i32); 1455 Constant *Zero = Ctx->getConstantZero(IceType_i32);
1324 _cmp(Src0R, Zero); 1456 _cmp(Src0R, Zero);
1325 _br(CondARM32::NE, Inst->getTargetTrue(), Inst->getTargetFalse()); 1457 _br(Inst->getTargetTrue(), Inst->getTargetFalse(), CondARM32::NE);
1326 } 1458 }
1327 1459
1328 void TargetARM32::lowerCall(const InstCall *Instr) { 1460 void TargetARM32::lowerCall(const InstCall *Instr) {
1329 MaybeLeafFunc = false; 1461 MaybeLeafFunc = false;
1330 NeedsStackAlignment = true; 1462 NeedsStackAlignment = true;
1331 1463
1332 // Assign arguments to registers and stack. Also reserve stack. 1464 // Assign arguments to registers and stack. Also reserve stack.
1333 TargetARM32::CallingConv CC; 1465 TargetARM32::CallingConv CC;
1334 // Pair of Arg Operand -> GPR number assignments. 1466 // Pair of Arg Operand -> GPR number assignments.
1335 llvm::SmallVector<std::pair<Operand *, int32_t>, 1467 llvm::SmallVector<std::pair<Operand *, int32_t>,
(...skipping 770 matching lines...) Expand 10 before | Expand all | Expand 10 after
2106 for (SizeT I = 0; I < NumCases; ++I) { 2238 for (SizeT I = 0; I < NumCases; ++I) {
2107 Operand *Value = Ctx->getConstantInt32(Inst->getValue(I)); 2239 Operand *Value = Ctx->getConstantInt32(Inst->getValue(I));
2108 Value = legalize(Value, Legal_Reg | Legal_Flex); 2240 Value = legalize(Value, Legal_Reg | Legal_Flex);
2109 _cmp(Src0Var, Value); 2241 _cmp(Src0Var, Value);
2110 _br(Inst->getLabel(I), CondARM32::EQ); 2242 _br(Inst->getLabel(I), CondARM32::EQ);
2111 } 2243 }
2112 _br(Inst->getLabelDefault()); 2244 _br(Inst->getLabelDefault());
2113 } 2245 }
2114 2246
2115 void TargetARM32::lowerUnreachable(const InstUnreachable * /*Inst*/) { 2247 void TargetARM32::lowerUnreachable(const InstUnreachable * /*Inst*/) {
2116 UnimplementedError(Func->getContext()->getFlags()); 2248 _trap();
2117 } 2249 }
2118 2250
2119 // Turn an i64 Phi instruction into a pair of i32 Phi instructions, to 2251 // Turn an i64 Phi instruction into a pair of i32 Phi instructions, to
2120 // preserve integrity of liveness analysis. Undef values are also 2252 // preserve integrity of liveness analysis. Undef values are also
2121 // turned into zeroes, since loOperand() and hiOperand() don't expect 2253 // turned into zeroes, since loOperand() and hiOperand() don't expect
2122 // Undef input. 2254 // Undef input.
2123 void TargetARM32::prelowerPhis() { 2255 void TargetARM32::prelowerPhis() {
2124 UnimplementedError(Func->getContext()->getFlags()); 2256 UnimplementedError(Func->getContext()->getFlags());
2125 } 2257 }
2126 2258
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after
2410 } 2542 }
2411 } 2543 }
2412 2544
2413 void TargetDataARM32::lowerConstants() { 2545 void TargetDataARM32::lowerConstants() {
2414 if (Ctx->getFlags().getDisableTranslation()) 2546 if (Ctx->getFlags().getDisableTranslation())
2415 return; 2547 return;
2416 UnimplementedError(Ctx->getFlags()); 2548 UnimplementedError(Ctx->getFlags());
2417 } 2549 }
2418 2550
2419 TargetHeaderARM32::TargetHeaderARM32(GlobalContext *Ctx) 2551 TargetHeaderARM32::TargetHeaderARM32(GlobalContext *Ctx)
2420 : TargetHeaderLowering(Ctx) {} 2552 : TargetHeaderLowering(Ctx), CPUFeatures(Ctx->getFlags()) {}
2421 2553
2422 void TargetHeaderARM32::lower() { 2554 void TargetHeaderARM32::lower() {
2423 OstreamLocker L(Ctx); 2555 OstreamLocker L(Ctx);
2424 Ostream &Str = Ctx->getStrEmit(); 2556 Ostream &Str = Ctx->getStrEmit();
2425 Str << ".syntax unified\n"; 2557 Str << ".syntax unified\n";
2426 // Emit build attributes in format: .eabi_attribute TAG, VALUE. 2558 // Emit build attributes in format: .eabi_attribute TAG, VALUE.
2427 // See Sec. 2 of "Addenda to, and Errata in the ABI for the ARM architecture" 2559 // See Sec. 2 of "Addenda to, and Errata in the ABI for the ARM architecture"
2428 // http://infocenter.arm.com/help/topic/com.arm.doc.ihi0045d/IHI0045D_ABI_adde nda.pdf 2560 // http://infocenter.arm.com/help/topic/com.arm.doc.ihi0045d/IHI0045D_ABI_adde nda.pdf
2429 // 2561 //
2430 // Tag_conformance should be be emitted first in a file-scope 2562 // Tag_conformance should be be emitted first in a file-scope
2431 // sub-subsection of the first public subsection of the attributes. 2563 // sub-subsection of the first public subsection of the attributes.
2432 Str << ".eabi_attribute 67, \"2.09\" @ Tag_conformance\n"; 2564 Str << ".eabi_attribute 67, \"2.09\" @ Tag_conformance\n";
2433 // Chromebooks are at least A15, but do A9 for higher compat. 2565 // Chromebooks are at least A15, but do A9 for higher compat.
2434 Str << ".cpu cortex-a9\n" 2566 // For some reason, the LLVM ARM asm parser has the .cpu directive override
2435 << ".eabi_attribute 6, 10 @ Tag_CPU_arch: ARMv7\n" 2567 // the mattr specified on the commandline. So to test hwdiv, we need to set
2568 // the .cpu directive higher (can't just rely on --mattr=...).
2569 if (CPUFeatures.hasFeature(TargetARM32Features::HWDivArm)) {
2570 Str << ".cpu cortex-a15\n";
2571 } else {
2572 Str << ".cpu cortex-a9\n";
2573 }
2574 Str << ".eabi_attribute 6, 10 @ Tag_CPU_arch: ARMv7\n"
2436 << ".eabi_attribute 7, 65 @ Tag_CPU_arch_profile: App profile\n"; 2575 << ".eabi_attribute 7, 65 @ Tag_CPU_arch_profile: App profile\n";
2437 Str << ".eabi_attribute 8, 1 @ Tag_ARM_ISA_use: Yes\n" 2576 Str << ".eabi_attribute 8, 1 @ Tag_ARM_ISA_use: Yes\n"
2438 << ".eabi_attribute 9, 2 @ Tag_THUMB_ISA_use: Thumb-2\n"; 2577 << ".eabi_attribute 9, 2 @ Tag_THUMB_ISA_use: Thumb-2\n";
2439 // TODO(jvoung): check other CPU features like HW div.
2440 Str << ".fpu neon\n" 2578 Str << ".fpu neon\n"
2441 << ".eabi_attribute 17, 1 @ Tag_ABI_PCS_GOT_use: permit directly\n" 2579 << ".eabi_attribute 17, 1 @ Tag_ABI_PCS_GOT_use: permit directly\n"
2442 << ".eabi_attribute 20, 1 @ Tag_ABI_FP_denormal\n" 2580 << ".eabi_attribute 20, 1 @ Tag_ABI_FP_denormal\n"
2443 << ".eabi_attribute 21, 1 @ Tag_ABI_FP_exceptions\n" 2581 << ".eabi_attribute 21, 1 @ Tag_ABI_FP_exceptions\n"
2444 << ".eabi_attribute 23, 3 @ Tag_ABI_FP_number_model: IEEE 754\n" 2582 << ".eabi_attribute 23, 3 @ Tag_ABI_FP_number_model: IEEE 754\n"
2445 << ".eabi_attribute 34, 1 @ Tag_CPU_unaligned_access\n" 2583 << ".eabi_attribute 34, 1 @ Tag_CPU_unaligned_access\n"
2446 << ".eabi_attribute 24, 1 @ Tag_ABI_align_needed: 8-byte\n" 2584 << ".eabi_attribute 24, 1 @ Tag_ABI_align_needed: 8-byte\n"
2447 << ".eabi_attribute 25, 1 @ Tag_ABI_align_preserved: 8-byte\n" 2585 << ".eabi_attribute 25, 1 @ Tag_ABI_align_preserved: 8-byte\n"
2448 << ".eabi_attribute 28, 1 @ Tag_ABI_VFP_args\n" 2586 << ".eabi_attribute 28, 1 @ Tag_ABI_VFP_args\n"
2449 << ".eabi_attribute 36, 1 @ Tag_FP_HP_extension\n" 2587 << ".eabi_attribute 36, 1 @ Tag_FP_HP_extension\n"
2450 << ".eabi_attribute 38, 1 @ Tag_ABI_FP_16bit_format\n" 2588 << ".eabi_attribute 38, 1 @ Tag_ABI_FP_16bit_format\n"
2451 << ".eabi_attribute 42, 1 @ Tag_MPextension_use\n" 2589 << ".eabi_attribute 42, 1 @ Tag_MPextension_use\n"
2452 << ".eabi_attribute 68, 1 @ Tag_Virtualization_use\n"; 2590 << ".eabi_attribute 68, 1 @ Tag_Virtualization_use\n";
2591 if (CPUFeatures.hasFeature(TargetARM32Features::HWDivArm)) {
2592 Str << ".eabi_attribute 44, 2 @ Tag_DIV_use\n";
2593 }
2453 // Technically R9 is used for TLS with Sandboxing, and we reserve it. 2594 // Technically R9 is used for TLS with Sandboxing, and we reserve it.
2454 // However, for compatibility with current NaCl LLVM, don't claim that. 2595 // However, for compatibility with current NaCl LLVM, don't claim that.
2455 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; 2596 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n";
2456 } 2597 }
2457 2598
2458 } // end of namespace Ice 2599 } // end of namespace Ice
OLDNEW
« no previous file with comments | « src/IceTargetLoweringARM32.h ('k') | tests_lit/llvm2ice_tests/64bit.pnacl.ll » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698