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

Side by Side Diff: src/IceInstARM32.cpp

Issue 1596613002: Clean up handling of ARM IR instruction "mov". (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Update Dart files. Created 4 years, 11 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/IceInstARM32.h ('k') | tests_lit/assembler/arm32/vmov-cast.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/IceInstARM32.cpp - ARM32 instruction implementation ----===// 1 //===- subzero/src/IceInstARM32.cpp - ARM32 instruction implementation ----===//
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 997 matching lines...) Expand 10 before | Expand all | Expand 10 after
1008 template <> const char *InstARM32Tst::Opcode = "tst"; 1008 template <> const char *InstARM32Tst::Opcode = "tst";
1009 1009
1010 void InstARM32::dump(const Cfg *Func) const { 1010 void InstARM32::dump(const Cfg *Func) const {
1011 if (!BuildDefs::dump()) 1011 if (!BuildDefs::dump())
1012 return; 1012 return;
1013 Ostream &Str = Func->getContext()->getStrDump(); 1013 Ostream &Str = Func->getContext()->getStrDump();
1014 Str << "[ARM32] "; 1014 Str << "[ARM32] ";
1015 Inst::dump(Func); 1015 Inst::dump(Func);
1016 } 1016 }
1017 1017
1018 void InstARM32Mov::emitMultiDestSingleSource(const Cfg *Func) const { 1018 void InstARM32Mov::emitMultiDestSingleSource(const Cfg *Func,
1019 if (!BuildDefs::dump()) 1019 const EmitForm Form) const {
John 2016/01/16 00:24:13 I understand what you're doing, but it seems to me
Karl 2016/01/19 18:32:39 Ok. For the moment, I will not try to merge code b
1020 return;
1021 Ostream &Str = Func->getContext()->getStrEmit();
1022 Variable *DestLo = getDest(); 1020 Variable *DestLo = getDest();
1023 Variable *DestHi = getDestHi(); 1021 Variable *DestHi = getDestHi();
1024 auto *Src = llvm::cast<Variable>(getSrc(0));
1025
1026 assert(DestHi->hasReg()); 1022 assert(DestHi->hasReg());
1027 assert(DestLo->hasReg()); 1023 assert(DestLo->hasReg());
1024 auto *Src = llvm::cast<Variable>(getSrc(0));
1028 assert(llvm::isa<Variable>(Src) && Src->hasReg()); 1025 assert(llvm::isa<Variable>(Src) && Src->hasReg());
1029 1026 switch (Form) {
1030 Str << "\t" 1027 case Emit_Text: {
1031 "vmov" << getPredicate() << "\t"; 1028 if (!BuildDefs::dump())
1032 DestLo->emit(Func); 1029 return;
1033 Str << ", "; 1030 Ostream &Str = Func->getContext()->getStrEmit();
1034 DestHi->emit(Func); 1031 Str << "\t"
1035 Str << ", "; 1032 "vmov" << getPredicate() << "\t";
1036 Src->emit(Func); 1033 DestLo->emit(Func);
1034 Str << ", ";
1035 DestHi->emit(Func);
1036 Str << ", ";
1037 Src->emit(Func);
1038 return;
1039 }
1040 case Emit_Binary: {
1041 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1042 Asm->setNeedsTextFixup();
1043 return;
1044 }
1045 }
1037 } 1046 }
1038 1047
1039 void InstARM32Mov::emitSingleDestMultiSource(const Cfg *Func) const { 1048 void InstARM32Mov::emitSingleDestMultiSource(const Cfg *Func,
1040 if (!BuildDefs::dump()) 1049 const EmitForm Form) const {
1041 return;
1042 Ostream &Str = Func->getContext()->getStrEmit();
1043 Variable *Dest = getDest(); 1050 Variable *Dest = getDest();
1044 auto *SrcLo = llvm::cast<Variable>(getSrc(0)); 1051 auto *SrcLo = llvm::cast<Variable>(getSrc(0));
1045 auto *SrcHi = llvm::cast<Variable>(getSrc(1)); 1052 auto *SrcHi = llvm::cast<Variable>(getSrc(1));
1046 1053
1047 assert(SrcHi->hasReg()); 1054 assert(SrcHi->hasReg());
1048 assert(SrcLo->hasReg()); 1055 assert(SrcLo->hasReg());
1049 assert(Dest->hasReg()); 1056 assert(Dest->hasReg());
1050 assert(getSrcSize() == 2); 1057 assert(getSrcSize() == 2);
1051 1058
1052 Str << "\t" 1059 switch (Form) {
1053 "vmov" << getPredicate() << "\t"; 1060 case Emit_Text: {
1054 Dest->emit(Func); 1061 if (!BuildDefs::dump())
1055 Str << ", "; 1062 return;
1056 SrcLo->emit(Func); 1063 Ostream &Str = Func->getContext()->getStrEmit();
1057 Str << ", "; 1064 Str << "\t"
1058 SrcHi->emit(Func); 1065 "vmov" << getPredicate() << "\t";
1066 Dest->emit(Func);
1067 Str << ", ";
1068 SrcLo->emit(Func);
1069 Str << ", ";
1070 SrcHi->emit(Func);
1071 return;
1072 }
1073 case Emit_Binary: {
1074 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1075 Asm->setNeedsTextFixup();
1076 return;
1077 }
1078 }
1059 } 1079 }
1060 1080
1061 namespace { 1081 namespace {
1062 1082
1063 bool isVariableWithoutRegister(const Operand *Op) { 1083 bool isVariableWithoutRegister(const Operand *Op) {
1064 if (const auto *OpV = llvm::dyn_cast<Variable>(Op)) { 1084 if (const auto *OpV = llvm::dyn_cast<Variable>(Op)) {
1065 return !OpV->hasReg(); 1085 return !OpV->hasReg();
1066 } 1086 }
1067 return false; 1087 return false;
1068 } 1088 }
1069 bool isMemoryAccess(Operand *Op) { 1089 bool isMemoryAccess(Operand *Op) {
1070 return isVariableWithoutRegister(Op) || llvm::isa<OperandARM32Mem>(Op); 1090 return isVariableWithoutRegister(Op) || llvm::isa<OperandARM32Mem>(Op);
1071 } 1091 }
1072 1092
1073 bool isMoveBetweenCoreAndVFPRegisters(Variable *Dest, Operand *Src) { 1093 bool isMoveBetweenCoreAndVFPRegisters(Variable *Dest, Operand *Src) {
1074 const Type DestTy = Dest->getType(); 1094 const Type DestTy = Dest->getType();
1075 const Type SrcTy = Src->getType(); 1095 const Type SrcTy = Src->getType();
1076 return !isVectorType(DestTy) && !isVectorType(SrcTy) && 1096 return !isVectorType(DestTy) && !isVectorType(SrcTy) &&
1077 (isScalarIntegerType(DestTy) == isScalarFloatingType(SrcTy)); 1097 (isScalarIntegerType(DestTy) == isScalarFloatingType(SrcTy));
1078 } 1098 }
1079 1099
1080 } // end of anonymous namespace 1100 } // end of anonymous namespace
1081 1101
1082 void InstARM32Mov::emitSingleDestSingleSource(const Cfg *Func) const { 1102 void InstARM32Mov::emitSingleDestSingleSource(const Cfg *Func,
1083 if (!BuildDefs::dump()) 1103 const EmitForm Form) const {
1084 return;
1085 Ostream &Str = Func->getContext()->getStrEmit();
1086 Variable *Dest = getDest(); 1104 Variable *Dest = getDest();
1087
1088 if (!Dest->hasReg()) { 1105 if (!Dest->hasReg()) {
1089 llvm::report_fatal_error("mov can't store."); 1106 llvm::report_fatal_error("mov can't store.");
1090 } 1107 }
1091 1108
1092 Operand *Src0 = getSrc(0); 1109 Operand *Src0 = getSrc(0);
1093 if (isMemoryAccess(Src0)) { 1110 if (isMemoryAccess(Src0)) {
1094 llvm::report_fatal_error("mov can't load."); 1111 llvm::report_fatal_error("mov can't load.");
1095 } 1112 }
1096 1113
1097 Type Ty = Dest->getType(); 1114 Type DestTy = Dest->getType();
1098 const bool IsVector = isVectorType(Ty); 1115 const bool IsVector = isVectorType(DestTy);
1099 const bool IsScalarFP = isScalarFloatingType(Ty); 1116 const bool IsScalarFP = isScalarFloatingType(DestTy);
1100 const bool CoreVFPMove = isMoveBetweenCoreAndVFPRegisters(Dest, Src0); 1117 const bool CoreVFPMove = isMoveBetweenCoreAndVFPRegisters(Dest, Src0);
1101 const bool IsVMove = (IsVector || IsScalarFP || CoreVFPMove); 1118 const bool IsVMove = (IsVector || IsScalarFP || CoreVFPMove);
1102 const char *Opcode = IsVMove ? "vmov" : "mov";
1103 // when vmov{c}'ing, we need to emit a width string. Otherwise, the
1104 // assembler might be tempted to assume we want a vector vmov{c}, and that
1105 // is disallowed because ARM.
1106 const char *WidthString = !CoreVFPMove ? getVecWidthString(Ty) : "";
1107 Str << "\t" << Opcode;
1108 if (IsVMove) { 1119 if (IsVMove) {
1109 Str << getPredicate() << WidthString; 1120 switch (Form) {
1110 } else { 1121 case Emit_Text: {
1111 Str << WidthString << getPredicate(); 1122 if (!BuildDefs::dump())
1123 return;
1124 Ostream &Str = Func->getContext()->getStrEmit();
1125 Variable *Dest = getDest();
1126 Operand *Src0 = getSrc(0);
1127 // when vmov{c}'ing, we need to emit a width string. Otherwise, the
1128 // assembler might be tempted to assume we want a vector vmov{c}, and
1129 // that is disallowed.
1130 const bool CoreVFPMove = isMoveBetweenCoreAndVFPRegisters(Dest, Src0);
1131 const char *WidthString = !CoreVFPMove ? getVecWidthString(DestTy) : "";
1132 Str << "\t"
1133 << "vmov" << getPredicate() << WidthString << "\t";
1134 Dest->emit(Func);
1135 Str << ", ";
1136 Src0->emit(Func);
1137 return;
1138 }
1139 case Emit_Binary: {
1140 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1141 if (!llvm::isa<Variable>(Src0))
1142 // TODO(kschimpf) Handle moving contants into registers.
1143 return Asm->setNeedsTextFixup();
1144
1145 // Move register to register.
1146 switch (DestTy) {
1147 default:
1148 // TODO(kschimpf): Fill this out more.
1149 return Asm->setNeedsTextFixup();
1150 case IceType_f32:
1151 Type Src0Ty = Src0->getType();
1152 switch (Src0Ty) {
1153 default:
1154 // TODO(kschimpf): Fill this out more.
1155 return Asm->setNeedsTextFixup();
1156 case IceType_i32:
1157 return Asm->vmovsr(Dest, Src0, getPredicate());
1158 }
1159 }
1160 }
1161 }
1112 } 1162 }
1113 Str << "\t"; 1163
1114 Dest->emit(Func); 1164 switch (Form) {
1115 Str << ", "; 1165 case Emit_Text: {
1116 Src0->emit(Func); 1166 Ostream &Str = Func->getContext()->getStrEmit();
1167 Str << "\t"
1168 << "mov" << getPredicate() << "\t";
1169 getDest()->emit(Func);
1170 Str << ", ";
1171 getSrc(0)->emit(Func);
1172 return;
1173 }
1174 case Emit_Binary: {
1175 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1176 Asm->mov(getDest(), getSrc(0), getPredicate());
1177 return;
1178 }
1179 }
1117 } 1180 }
1118 1181
1119 void InstARM32Mov::emitIASSingleDestSingleSource(const Cfg *Func) const { 1182 void InstARM32Mov::emitUsingForm(const Cfg *Func, const EmitForm Form) const {
1120 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); 1183 assert(!(isMultiDest() && isMultiSource()) && "Invalid vmov type.");
1121 Variable *Dest = getDest(); 1184 if (isMultiDest()) {
1122 Operand *Src0 = getSrc(0); 1185 emitMultiDestSingleSource(Func, Form);
1123 1186 return;
1124 if (!Dest->hasReg()) {
1125 llvm::report_fatal_error("mov can't store.");
1126 } 1187 }
1127 1188
1128 if (isMemoryAccess(Src0)) { 1189 if (isMultiSource()) {
1129 llvm::report_fatal_error("mov can't load."); 1190 emitSingleDestMultiSource(Func, Form);
1191 return;
1130 } 1192 }
1131 1193 emitSingleDestSingleSource(Func, Form);
1132 const Type DestTy = Dest->getType();
1133 const bool DestIsVector = isVectorType(DestTy);
1134 const bool DestIsScalarFP = isScalarFloatingType(DestTy);
1135 const bool CoreVFPMove = isMoveBetweenCoreAndVFPRegisters(Dest, Src0);
1136 if (DestIsVector || DestIsScalarFP || CoreVFPMove)
1137 return Asm->setNeedsTextFixup();
1138 return Asm->mov(Dest, Src0, getPredicate());
1139 } 1194 }
1140 1195
1141 void InstARM32Mov::emit(const Cfg *Func) const { 1196 void InstARM32Mov::emit(const Cfg *Func) const {
1142 if (!BuildDefs::dump()) 1197 if (!BuildDefs::dump())
1143 return; 1198 return;
1144 assert(!(isMultiDest() && isMultiSource()) && "Invalid vmov type."); 1199 emitUsingForm(Func, Emit_Text);
1145 if (isMultiDest()) {
1146 emitMultiDestSingleSource(Func);
1147 return;
1148 }
1149
1150 if (isMultiSource()) {
1151 emitSingleDestMultiSource(Func);
1152 return;
1153 }
1154
1155 emitSingleDestSingleSource(Func);
1156 } 1200 }
1157 1201
1158 void InstARM32Mov::emitIAS(const Cfg *Func) const { 1202 void InstARM32Mov::emitIAS(const Cfg *Func) const {
1159 assert(!(isMultiDest() && isMultiSource()) && "Invalid vmov type."); 1203 emitUsingForm(Func, Emit_Binary);
1160 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); 1204 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1161 if (!(isMultiDest() || isMultiSource()))
1162 // Must be single source/dest.
1163 emitIASSingleDestSingleSource(Func);
1164 else
1165 Asm->setNeedsTextFixup();
1166 if (Asm->needsTextFixup()) 1205 if (Asm->needsTextFixup())
1167 emitUsingTextFixup(Func); 1206 emitUsingTextFixup(Func);
1168 } 1207 }
1169 1208
1170 void InstARM32Mov::dump(const Cfg *Func) const { 1209 void InstARM32Mov::dump(const Cfg *Func) const {
1171 if (!BuildDefs::dump()) 1210 if (!BuildDefs::dump())
1172 return; 1211 return;
1173 assert(getSrcSize() == 1 || getSrcSize() == 2); 1212 assert(getSrcSize() == 1 || getSrcSize() == 2);
1174 Ostream &Str = Func->getContext()->getStrDump(); 1213 Ostream &Str = Func->getContext()->getStrDump();
1175 Variable *Dest = getDest(); 1214 Variable *Dest = getDest();
(...skipping 1040 matching lines...) Expand 10 before | Expand all | Expand 10 after
2216 2255
2217 template class InstARM32FourAddrGPR<InstARM32::Mla>; 2256 template class InstARM32FourAddrGPR<InstARM32::Mla>;
2218 template class InstARM32FourAddrGPR<InstARM32::Mls>; 2257 template class InstARM32FourAddrGPR<InstARM32::Mls>;
2219 2258
2220 template class InstARM32CmpLike<InstARM32::Cmn>; 2259 template class InstARM32CmpLike<InstARM32::Cmn>;
2221 template class InstARM32CmpLike<InstARM32::Cmp>; 2260 template class InstARM32CmpLike<InstARM32::Cmp>;
2222 template class InstARM32CmpLike<InstARM32::Tst>; 2261 template class InstARM32CmpLike<InstARM32::Tst>;
2223 2262
2224 } // end of namespace ARM32 2263 } // end of namespace ARM32
2225 } // end of namespace Ice 2264 } // end of namespace Ice
OLDNEW
« no previous file with comments | « src/IceInstARM32.h ('k') | tests_lit/assembler/arm32/vmov-cast.ll » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698