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

Side by Side Diff: src/IceTargetLoweringARM32.cpp

Issue 1417393003: Subzero. ARM32. New bool folding. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Fixes lit tests. Created 5 years, 1 month 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
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 /// \file 10 /// \file
(...skipping 1026 matching lines...) Expand 10 before | Expand all | Expand 10 after
1037 assert(Mem->getBase()->hasReg()); 1037 assert(Mem->getBase()->hasReg());
1038 assert(Mem->getBase()->getRegNum() == (int32_t)getFrameOrStackReg()); 1038 assert(Mem->getBase()->getRegNum() == (int32_t)getFrameOrStackReg());
1039 Legalized = true; 1039 Legalized = true;
1040 Src = legalizeStackSlot(SrcTy, Offset, StackAdjust, OrigBaseReg, 1040 Src = legalizeStackSlot(SrcTy, Offset, StackAdjust, OrigBaseReg,
1041 NewBaseReg, NewBaseOffset); 1041 NewBaseReg, NewBaseOffset);
1042 } 1042 }
1043 } 1043 }
1044 } 1044 }
1045 1045
1046 if (Legalized) { 1046 if (Legalized) {
1047 _mov(Dest, Src); 1047 if (MovInstr->isDestRedefined()) {
1048 _mov_redefined(Dest, Src, MovInstr->getPredicate());
1049 } else {
1050 _mov(Dest, Src, MovInstr->getPredicate());
1051 }
1048 MovInstr->setDeleted(); 1052 MovInstr->setDeleted();
1049 } 1053 }
1050 } 1054 }
1051 1055
1052 void TargetARM32::legalizeStackSlots() { 1056 void TargetARM32::legalizeStackSlots() {
1053 // If a stack variable's frame offset doesn't fit, convert from: 1057 // If a stack variable's frame offset doesn't fit, convert from:
1054 // ldr X, OFF[SP] 1058 // ldr X, OFF[SP]
1055 // to: 1059 // to:
1056 // movw/movt TMP, OFF_PART 1060 // movw/movt TMP, OFF_PART
1057 // add TMP, TMP, SP 1061 // add TMP, TMP, SP
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after
1339 } else { 1343 } else {
1340 constexpr SizeT MaxSrcs = 2; 1344 constexpr SizeT MaxSrcs = 2;
1341 InstCall *Call = makeHelperCall(DivHelperName, Dest, MaxSrcs); 1345 InstCall *Call = makeHelperCall(DivHelperName, Dest, MaxSrcs);
1342 Call->addArg(T0R); 1346 Call->addArg(T0R);
1343 Call->addArg(T1R); 1347 Call->addArg(T1R);
1344 lowerCall(Call); 1348 lowerCall(Call);
1345 } 1349 }
1346 return; 1350 return;
1347 } 1351 }
1348 1352
1353 TargetARM32::SafeBoolChain
1354 TargetARM32::lowerInt1Arithmetic(const InstArithmetic *Inst) {
1355 Variable *Dest = Inst->getDest();
1356 assert(Dest->getType() == IceType_i1);
1357
1358 // So folding didn't work for Inst. Not a problem: We just need to
1359 // materialize the Sources, and perform the operation. We create reguar
Jim Stichnoth 2015/11/11 18:55:04 regular
John 2015/11/11 22:19:44 Done.
1360 // Variables (and not infinite-weight ones) because this call might recurse a
1361 // lot, and we might end up with tons of infinite weight temporaries.
1362 assert(Inst->getSrcSize() == 2);
1363 Variable *Src0 = Func->makeVariable(IceType_i1);
Jim Stichnoth 2015/11/11 18:55:04 Can you do this instead? Variable *Src0 = mak
John 2015/11/11 22:19:44 N/A
1364 SafeBoolChain Src0Safe = lowerInt1(Src0, Inst->getSrc(0));
1365
1366 Operand *Src1 = Inst->getSrc(1);
1367 SafeBoolChain Src1Safe = SBC_Yes;
1368
1369 if (!llvm::isa<Constant>(Src1)) {
1370 Variable *Src1V = Func->makeVariable(IceType_i1);
1371 Src1Safe = lowerInt1(Src1V, Src1);
1372 Src1 = Src1V;
1373 }
1374
1375 Variable *T = makeReg(IceType_i1);
1376 Src0 = legalizeToReg(Src0);
1377 Operand *Src1RF = legalize(Src1, Legal_Reg | Legal_Flex);
1378 switch (Inst->getOp()) {
1379 default:
1380 // If this Unreachable is ever executed, add the offending operation to
1381 // the list of valid consumers.
1382 llvm_unreachable("Unhandled i1 Op");
Jim Stichnoth 2015/11/11 18:55:04 llvm::report_fatal_error here and below
John 2015/11/11 22:19:46 Done.
1383 case InstArithmetic::And:
1384 _and(T, Src0, Src1RF);
1385 break;
1386 case InstArithmetic::Or:
1387 _orr(T, Src0, Src1RF);
1388 break;
1389 case InstArithmetic::Xor:
1390 _eor(T, Src0, Src1RF);
1391 break;
1392 }
1393 _mov(Dest, T);
1394 return Src0Safe == SBC_Yes && Src1Safe == SBC_Yes ? SBC_Yes : SBC_No;
1395 }
1396
1349 void TargetARM32::lowerArithmetic(const InstArithmetic *Inst) { 1397 void TargetARM32::lowerArithmetic(const InstArithmetic *Inst) {
1350 Variable *Dest = Inst->getDest(); 1398 Variable *Dest = Inst->getDest();
1399 if (Dest->getType() == IceType_i1) {
1400 lowerInt1Arithmetic(Inst);
1401 return;
1402 }
1403
1351 // TODO(jvoung): Should be able to flip Src0 and Src1 if it is easier to 1404 // TODO(jvoung): Should be able to flip Src0 and Src1 if it is easier to
1352 // legalize Src0 to flex or Src1 to flex and there is a reversible 1405 // legalize Src0 to flex or Src1 to flex and there is a reversible
1353 // instruction. E.g., reverse subtract with immediate, register vs register, 1406 // instruction. E.g., reverse subtract with immediate, register vs register,
1354 // immediate. 1407 // immediate.
1355 // Or it may be the case that the operands aren't swapped, but the bits can 1408 // Or it may be the case that the operands aren't swapped, but the bits can
1356 // be flipped and a different operation applied. E.g., use BIC (bit clear) 1409 // be flipped and a different operation applied. E.g., use BIC (bit clear)
1357 // instead of AND for some masks. 1410 // instead of AND for some masks.
1358 Operand *Src0 = legalizeUndef(Inst->getSrc(0)); 1411 Operand *Src0 = legalizeUndef(Inst->getSrc(0));
1359 Operand *Src1 = legalizeUndef(Inst->getSrc(1)); 1412 Operand *Src1 = legalizeUndef(Inst->getSrc(1));
1360 if (Dest->getType() == IceType_i64) { 1413 if (Dest->getType() == IceType_i64) {
(...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after
1807 _mov(Dest, SrcR); 1860 _mov(Dest, SrcR);
1808 } else if (isFloatingType(Dest->getType())) { 1861 } else if (isFloatingType(Dest->getType())) {
1809 Variable *SrcR = legalizeToReg(NewSrc); 1862 Variable *SrcR = legalizeToReg(NewSrc);
1810 _mov(Dest, SrcR); 1863 _mov(Dest, SrcR);
1811 } else { 1864 } else {
1812 _mov(Dest, NewSrc); 1865 _mov(Dest, NewSrc);
1813 } 1866 }
1814 } 1867 }
1815 } 1868 }
1816 1869
1870 TargetARM32::ShortCircuitCondAndLabel TargetARM32::lowerInt1ForBranch(
1871 Operand *Boolean, const LowerInt1BranchTarget &TargetTrue,
1872 const LowerInt1BranchTarget &TargetFalse, uint32_t ShortCircuitable) {
1873 InstARM32Label *NewShortCircuitLabel = nullptr;
1874 Operand *_1 = legalize(Ctx->getConstantInt1(1), Legal_Reg | Legal_Flex);
1875
1876 const Inst *Producer = BoolComputations.getProducerOf(Boolean);
1877
1878 if (Producer == nullptr) {
1879 // No producer, no problem: just do emit codee to perform (Boolean & 1) and
Jim Stichnoth 2015/11/11 18:55:04 codee?
John 2015/11/11 22:19:46 Done.
1880 // set the flags register. The branch should be taken if the resulting flags
1881 // indicate a non-zero result.
1882 _tst(legalizeToReg(Boolean), _1);
1883 return ShortCircuitCondAndLabel(CondWhenTrue(CondARM32::NE));
1884 }
1885
1886 switch (Producer->getKind()) {
1887 default:
1888 llvm_unreachable("Unexpected producer.");
1889 case Inst::Icmp: {
1890 return ShortCircuitCondAndLabel(
1891 lowerIcmpCond(llvm::cast<InstIcmp>(Producer)));
1892 } break;
1893 case Inst::Fcmp: {
1894 return ShortCircuitCondAndLabel(
1895 lowerFcmpCond(llvm::cast<InstFcmp>(Producer)));
1896 } break;
1897 case Inst::Cast: {
1898 const auto *CastProducer = llvm::cast<InstCast>(Producer);
1899 assert(CastProducer->getCastKind() == InstCast::Trunc);
1900 Operand *Src = CastProducer->getSrc(0);
1901 if (Src->getType() == IceType_i64)
1902 Src = loOperand(Src);
1903 _tst(legalizeToReg(Src), _1);
1904 return ShortCircuitCondAndLabel(CondWhenTrue(CondARM32::NE));
1905 } break;
1906 case Inst::Arithmetic: {
1907 const auto *ArithProducer = llvm::cast<InstArithmetic>(Producer);
1908 switch (ArithProducer->getOp()) {
1909 default:
1910 llvm_unreachable("Unhandled Arithmetic Producer.");
1911 case InstArithmetic::And: {
1912 if (!(ShortCircuitable & SC_And)) {
1913 NewShortCircuitLabel = InstARM32Label::create(Func, this);
1914 }
1915
1916 LowerInt1BranchTarget NewTarget =
1917 TargetFalse.createForLabelOrDuplicate(NewShortCircuitLabel);
1918
1919 ShortCircuitCondAndLabel CondAndLabel = lowerInt1ForBranch(
1920 Producer->getSrc(0), TargetTrue, NewTarget, SC_And);
1921 const CondWhenTrue &Cond = CondAndLabel.Cond;
1922
1923 _br_short_circuit(NewTarget, Cond.invert());
1924
1925 InstARM32Label *const ShortCircuitLabel = CondAndLabel.ShortCircuitTarget;
1926 if (ShortCircuitLabel != nullptr)
1927 Context.insert(ShortCircuitLabel);
1928
1929 return ShortCircuitCondAndLabel(
1930 lowerInt1ForBranch(Producer->getSrc(1), TargetTrue, NewTarget, SC_All)
1931 .assertNoLabelAndReturnCond(),
1932 NewShortCircuitLabel);
1933 } break;
1934 case InstArithmetic::Or: {
1935 if (!(ShortCircuitable & SC_Or)) {
1936 NewShortCircuitLabel = InstARM32Label::create(Func, this);
1937 }
1938
1939 LowerInt1BranchTarget NewTarget =
1940 TargetTrue.createForLabelOrDuplicate(NewShortCircuitLabel);
1941
1942 ShortCircuitCondAndLabel CondAndLabel = lowerInt1ForBranch(
1943 Producer->getSrc(0), NewTarget, TargetFalse, SC_Or);
1944 const CondWhenTrue &Cond = CondAndLabel.Cond;
1945
1946 _br_short_circuit(NewTarget, Cond);
1947
1948 InstARM32Label *const ShortCircuitLabel = CondAndLabel.ShortCircuitTarget;
1949 if (ShortCircuitLabel != nullptr)
1950 Context.insert(ShortCircuitLabel);
1951
1952 return ShortCircuitCondAndLabel(lowerInt1ForBranch(Producer->getSrc(1),
1953 NewTarget, TargetFalse,
1954 SC_All)
1955 .assertNoLabelAndReturnCond(),
1956 NewShortCircuitLabel);
1957 } break;
1958 }
1959 }
1960 }
1961 }
1962
1817 void TargetARM32::lowerBr(const InstBr *Instr) { 1963 void TargetARM32::lowerBr(const InstBr *Instr) {
1818 if (Instr->isUnconditional()) { 1964 if (Instr->isUnconditional()) {
1819 _br(Instr->getTargetUnconditional()); 1965 _br(Instr->getTargetUnconditional());
1820 return; 1966 return;
1821 } 1967 }
1822 Operand *Cond = Instr->getCondition();
1823 1968
1824 CondARM32::Cond BrCondTrue0 = CondARM32::NE; 1969 CfgNode *TargetTrue = Instr->getTargetTrue();
1825 CondARM32::Cond BrCondTrue1 = CondARM32::kNone; 1970 CfgNode *TargetFalse = Instr->getTargetFalse();
1826 CondARM32::Cond BrCondFalse = CondARM32::kNone; 1971 ShortCircuitCondAndLabel CondAndLabel = lowerInt1ForBranch(
1827 if (!_mov_i1_to_flags(Cond, &BrCondTrue0, &BrCondTrue1, &BrCondFalse)) { 1972 Instr->getCondition(), LowerInt1BranchTarget(TargetTrue),
1828 // "Cond" was not folded. 1973 LowerInt1BranchTarget(TargetFalse), SC_All);
1829 Type Ty = Cond->getType(); 1974 assert(CondAndLabel.ShortCircuitTarget == nullptr);
1830 Variable *Src0R = legalizeToReg(Cond); 1975
1831 assert(Ty == IceType_i1); 1976 const CondWhenTrue &Cond = CondAndLabel.Cond;
1832 if (Ty != IceType_i32) 1977 if (Cond.WhenTrue1 != CondARM32::kNone) {
1833 _uxt(Src0R, Src0R); 1978 assert(Cond.WhenTrue0 != CondARM32::AL);
1834 Constant *_0 = Ctx->getConstantZero(IceType_i32); 1979 _br(TargetTrue, Cond.WhenTrue1);
1835 _cmp(Src0R, _0);
1836 BrCondTrue0 = CondARM32::NE;
1837 } 1980 }
1838 1981
1839 if (BrCondTrue1 != CondARM32::kNone) { 1982 switch (Cond.WhenTrue0) {
1840 _br(Instr->getTargetTrue(), BrCondTrue1); 1983 default:
1984 _br(TargetTrue, TargetFalse, Cond.WhenTrue0);
1985 break;
1986 case CondARM32::kNone:
1987 _br(TargetFalse);
1988 break;
1989 case CondARM32::AL:
1990 _br(TargetTrue);
1991 break;
1841 } 1992 }
1842
1843 if (BrCondTrue0 == CondARM32::kNone) {
1844 assert(BrCondTrue1 == CondARM32::kNone);
1845 _br(Instr->getTargetFalse());
1846 return;
1847 }
1848
1849 if (BrCondTrue0 == CondARM32::AL) {
1850 assert(BrCondTrue1 == CondARM32::kNone);
1851 assert(BrCondFalse == CondARM32::kNone);
1852 _br(Instr->getTargetTrue());
1853 return;
1854 }
1855
1856 _br(Instr->getTargetTrue(), Instr->getTargetFalse(), BrCondTrue0);
1857 } 1993 }
1858 1994
1859 void TargetARM32::lowerCall(const InstCall *Instr) { 1995 void TargetARM32::lowerCall(const InstCall *Instr) {
1860 MaybeLeafFunc = false; 1996 MaybeLeafFunc = false;
1861 NeedsStackAlignment = true; 1997 NeedsStackAlignment = true;
1862 1998
1863 // Assign arguments to registers and stack. Also reserve stack. 1999 // Assign arguments to registers and stack. Also reserve stack.
1864 TargetARM32::CallingConv CC; 2000 TargetARM32::CallingConv CC;
1865 // Pair of Arg Operand -> GPR number assignments. 2001 // Pair of Arg Operand -> GPR number assignments.
1866 llvm::SmallVector<std::pair<Operand *, int32_t>, 2002 llvm::SmallVector<std::pair<Operand *, int32_t>,
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
1952 Variable *ReturnReg = nullptr; 2088 Variable *ReturnReg = nullptr;
1953 Variable *ReturnRegHi = nullptr; 2089 Variable *ReturnRegHi = nullptr;
1954 if (Dest) { 2090 if (Dest) {
1955 switch (Dest->getType()) { 2091 switch (Dest->getType()) {
1956 case IceType_NUM: 2092 case IceType_NUM:
1957 llvm_unreachable("Invalid Call dest type"); 2093 llvm_unreachable("Invalid Call dest type");
1958 break; 2094 break;
1959 case IceType_void: 2095 case IceType_void:
1960 break; 2096 break;
1961 case IceType_i1: 2097 case IceType_i1:
2098 assert(BoolComputations.getProducerOf(Dest) == nullptr);
Jim Stichnoth 2015/11/11 18:55:04 Note the deliberate fallthrough in a comment?
John 2015/11/11 22:19:44 Done.
1962 case IceType_i8: 2099 case IceType_i8:
1963 case IceType_i16: 2100 case IceType_i16:
1964 case IceType_i32: 2101 case IceType_i32:
1965 ReturnReg = makeReg(Dest->getType(), RegARM32::Reg_r0); 2102 ReturnReg = makeReg(Dest->getType(), RegARM32::Reg_r0);
1966 break; 2103 break;
1967 case IceType_i64: 2104 case IceType_i64:
1968 ReturnReg = makeReg(IceType_i32, RegARM32::Reg_r0); 2105 ReturnReg = makeReg(IceType_i32, RegARM32::Reg_r0);
1969 ReturnRegHi = makeReg(IceType_i32, RegARM32::Reg_r1); 2106 ReturnRegHi = makeReg(IceType_i32, RegARM32::Reg_r1);
1970 break; 2107 break;
1971 case IceType_f32: 2108 case IceType_f32:
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
2082 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); 2219 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest));
2083 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); 2220 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest));
2084 Variable *T_Lo = makeReg(DestLo->getType()); 2221 Variable *T_Lo = makeReg(DestLo->getType());
2085 if (Src0->getType() == IceType_i32) { 2222 if (Src0->getType() == IceType_i32) {
2086 Operand *Src0RF = legalize(Src0, Legal_Reg | Legal_Flex); 2223 Operand *Src0RF = legalize(Src0, Legal_Reg | Legal_Flex);
2087 _mov(T_Lo, Src0RF); 2224 _mov(T_Lo, Src0RF);
2088 } else if (Src0->getType() != IceType_i1) { 2225 } else if (Src0->getType() != IceType_i1) {
2089 Variable *Src0R = legalizeToReg(Src0); 2226 Variable *Src0R = legalizeToReg(Src0);
2090 _sxt(T_Lo, Src0R); 2227 _sxt(T_Lo, Src0R);
2091 } else { 2228 } else {
2092 CondARM32::Cond CondTrue0, CondTrue1, CondFalse; 2229 Operand *_0 = Ctx->getConstantZero(IceType_i32);
2093 if (_mov_i1_to_flags(Src0, &CondTrue0, &CondTrue1, &CondFalse)) { 2230 Operand *_m1 = Ctx->getConstantInt32(-1);
2094 // Handle bool folding. 2231 lowerInt1ForSelect(T_Lo, Src0, _m1, _0);
2095 Constant *_0 = Ctx->getConstantZero(IceType_i32);
2096 Operand *_m1 =
2097 legalize(Ctx->getConstantInt32(-1), Legal_Reg | Legal_Flex);
2098 _cmov(T_Lo, _m1, CondTrue0, CondTrue1, _0, CondFalse);
2099 } else {
2100 Variable *Src0R = legalizeToReg(Src0);
2101 _lsl(T_Lo, Src0R, ShiftAmt);
2102 _asr(T_Lo, T_Lo, ShiftAmt);
2103 }
2104 } 2232 }
2105 _mov(DestLo, T_Lo); 2233 _mov(DestLo, T_Lo);
2106 Variable *T_Hi = makeReg(DestHi->getType()); 2234 Variable *T_Hi = makeReg(DestHi->getType());
2107 if (Src0->getType() != IceType_i1) { 2235 if (Src0->getType() != IceType_i1) {
2108 _mov(T_Hi, OperandARM32FlexReg::create(Func, IceType_i32, T_Lo, 2236 _mov(T_Hi, OperandARM32FlexReg::create(Func, IceType_i32, T_Lo,
2109 OperandARM32::ASR, ShiftAmt)); 2237 OperandARM32::ASR, ShiftAmt));
2110 } else { 2238 } else {
2111 // For i1, the asr instruction is already done above. 2239 // For i1, the asr instruction is already done above.
2112 _mov(T_Hi, T_Lo); 2240 _mov(T_Hi, T_Lo);
2113 } 2241 }
2114 _mov(DestHi, T_Hi); 2242 _mov(DestHi, T_Hi);
2115 } else if (Src0->getType() != IceType_i1) { 2243 } else if (Src0->getType() != IceType_i1) {
2116 // t1 = sxt src; dst = t1 2244 // t1 = sxt src; dst = t1
2117 Variable *Src0R = legalizeToReg(Src0); 2245 Variable *Src0R = legalizeToReg(Src0);
2118 Variable *T = makeReg(Dest->getType()); 2246 Variable *T = makeReg(Dest->getType());
2119 _sxt(T, Src0R); 2247 _sxt(T, Src0R);
2120 _mov(Dest, T); 2248 _mov(Dest, T);
2121 } else { 2249 } else {
2250 Constant *_0 = Ctx->getConstantZero(IceType_i32);
2251 Operand *_m1 = Ctx->getConstantInt(Dest->getType(), -1);
2122 Variable *T = makeReg(Dest->getType()); 2252 Variable *T = makeReg(Dest->getType());
2123 CondARM32::Cond CondTrue0, CondTrue1, CondFalse; 2253 lowerInt1ForSelect(T, Src0, _m1, _0);
2124 if (_mov_i1_to_flags(Src0, &CondTrue0, &CondTrue1, &CondFalse)) {
2125 // Handle bool folding.
2126 Constant *_0 = Ctx->getConstantZero(IceType_i32);
2127 Operand *_m1 =
2128 legalize(Ctx->getConstantInt32(-1), Legal_Reg | Legal_Flex);
2129 _cmov(T, _m1, CondTrue0, CondTrue1, _0, CondFalse);
2130 } else {
2131 // GPR registers are 32-bit, so just use 31 as dst_bitwidth - 1.
2132 // lsl t1, src_reg, 31
2133 // asr t1, t1, 31
2134 // dst = t1
2135 Variable *Src0R = legalizeToReg(Src0);
2136 Constant *ShiftAmt = Ctx->getConstantInt32(31);
2137 _lsl(T, Src0R, ShiftAmt);
2138 _asr(T, T, ShiftAmt);
2139 }
2140 _mov(Dest, T); 2254 _mov(Dest, T);
2141 } 2255 }
2142 break; 2256 break;
2143 } 2257 }
2144 case InstCast::Zext: { 2258 case InstCast::Zext: {
2145 if (isVectorType(Dest->getType())) { 2259 if (isVectorType(Dest->getType())) {
2146 Variable *T = makeReg(Dest->getType()); 2260 Variable *T = makeReg(Dest->getType());
2147 Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0))); 2261 Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0)));
2148 _mov(Dest, T); 2262 _mov(Dest, T);
2149 UnimplementedError(Func->getContext()->getFlags()); 2263 UnimplementedError(Func->getContext()->getFlags());
2150 } else if (Dest->getType() == IceType_i64) { 2264 } else if (Dest->getType() == IceType_i64) {
2151 // t1=uxtb src; dst.lo=t1; dst.hi=0 2265 // t1=uxtb src; dst.lo=t1; dst.hi=0
2152 Constant *_0 = Ctx->getConstantZero(IceType_i32); 2266 Operand *_0 =
2153 Constant *_1 = Ctx->getConstantInt32(1); 2267 legalize(Ctx->getConstantZero(IceType_i32), Legal_Reg | Legal_Flex);
2154 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); 2268 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest));
2155 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); 2269 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest));
2156 Variable *T_Lo = makeReg(DestLo->getType()); 2270 Variable *T_Lo = makeReg(DestLo->getType());
2157 2271
2158 CondARM32::Cond CondTrue0, CondTrue1, CondFalse; 2272 switch (Src0->getType()) {
2159 if (_mov_i1_to_flags(Src0, &CondTrue0, &CondTrue1, &CondFalse)) { 2273 default: {
2160 // Handle folding opportunities. 2274 assert(Src0->getType() != IceType_i64);
2161 Variable *T_Hi = makeReg(DestLo->getType()); 2275 _uxt(T_Lo, legalizeToReg(Src0));
2162 _mov(T_Hi, _0); 2276 } break;
2163 _mov(DestHi, T_Hi); 2277 case IceType_i32: {
2164 _cmov(T_Lo, _1, CondTrue0, CondTrue1, _0, CondFalse); 2278 _mov(T_Lo, legalize(Src0, Legal_Reg | Legal_Flex));
2165 _mov(DestLo, T_Lo); 2279 } break;
2166 return; 2280 case IceType_i1: {
2281 SafeBoolChain Safe = lowerInt1(T_Lo, Src0);
2282 if (Safe == SBC_No) {
2283 Operand *_1 =
2284 legalize(Ctx->getConstantInt1(1), Legal_Reg | Legal_Flex);
2285 _and(T_Lo, T_Lo, _1);
2286 }
2287 } break;
2167 } 2288 }
2168 2289
2169 // i32 and i1 can just take up the whole register. i32 doesn't need uxt,
2170 // while i1 will have an and mask later anyway.
2171 if (Src0->getType() == IceType_i32 || Src0->getType() == IceType_i1) {
2172 Operand *Src0RF = legalize(Src0, Legal_Reg | Legal_Flex);
2173 _mov(T_Lo, Src0RF);
2174 } else {
2175 Variable *Src0R = legalizeToReg(Src0);
2176 _uxt(T_Lo, Src0R);
2177 }
2178 if (Src0->getType() == IceType_i1) {
2179 Constant *One = Ctx->getConstantInt32(1);
2180 _and(T_Lo, T_Lo, One);
2181 }
2182 _mov(DestLo, T_Lo); 2290 _mov(DestLo, T_Lo);
2291
2183 Variable *T_Hi = makeReg(DestLo->getType()); 2292 Variable *T_Hi = makeReg(DestLo->getType());
2184 _mov(T_Hi, _0); 2293 _mov(T_Hi, _0);
2185 _mov(DestHi, T_Hi); 2294 _mov(DestHi, T_Hi);
2186 } else if (Src0->getType() == IceType_i1) { 2295 } else if (Src0->getType() == IceType_i1) {
2187 Constant *_1 = Ctx->getConstantInt32(1);
2188 Variable *T = makeReg(Dest->getType()); 2296 Variable *T = makeReg(Dest->getType());
2189 2297
2190 CondARM32::Cond CondTrue0, CondTrue1, CondFalse; 2298 SafeBoolChain Safe = lowerInt1(T, Src0);
2191 if (_mov_i1_to_flags(Src0, &CondTrue0, &CondTrue1, &CondFalse)) { 2299 if (Safe == SBC_No) {
2192 // Handle folding opportunities. 2300 Operand *_1 = legalize(Ctx->getConstantInt1(1), Legal_Reg | Legal_Flex);
2193 Constant *_0 = Ctx->getConstantZero(IceType_i32); 2301 _and(T, T, _1);
2194 _cmov(T, _1, CondTrue0, CondTrue1, _0, CondFalse);
2195 _mov(Dest, T);
2196 return;
2197 } 2302 }
2198 2303
2199 // t = Src0; t &= 1; Dest = t
2200 Operand *Src0RF = legalize(Src0, Legal_Reg | Legal_Flex);
2201 // Just use _mov instead of _uxt since all registers are 32-bit. _uxt
2202 // requires the source to be a register so could have required a _mov
2203 // from legalize anyway.
2204 _mov(T, Src0RF);
2205 _and(T, T, _1);
2206 _mov(Dest, T); 2304 _mov(Dest, T);
2207 } else { 2305 } else {
2208 // t1 = uxt src; dst = t1 2306 // t1 = uxt src; dst = t1
2209 Variable *Src0R = legalizeToReg(Src0); 2307 Variable *Src0R = legalizeToReg(Src0);
2210 Variable *T = makeReg(Dest->getType()); 2308 Variable *T = makeReg(Dest->getType());
2211 _uxt(T, Src0R); 2309 _uxt(T, Src0R);
2212 _mov(Dest, T); 2310 _mov(Dest, T);
2213 } 2311 }
2214 break; 2312 break;
2215 } 2313 }
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
2466 CondARM32::Cond CC1; 2564 CondARM32::Cond CC1;
2467 } TableFcmp[] = { 2565 } TableFcmp[] = {
2468 #define X(val, CC0, CC1) \ 2566 #define X(val, CC0, CC1) \
2469 { CondARM32::CC0, CondARM32::CC1 } \ 2567 { CondARM32::CC0, CondARM32::CC1 } \
2470 , 2568 ,
2471 FCMPARM32_TABLE 2569 FCMPARM32_TABLE
2472 #undef X 2570 #undef X
2473 }; 2571 };
2474 } // end of anonymous namespace 2572 } // end of anonymous namespace
2475 2573
2476 void TargetARM32::lowerFcmpCond(const InstFcmp *Instr, 2574 TargetARM32::CondWhenTrue TargetARM32::lowerFcmpCond(const InstFcmp *Instr) {
2477 CondARM32::Cond *CondIfTrue0,
2478 CondARM32::Cond *CondIfTrue1,
2479 CondARM32::Cond *CondIfFalse) {
2480 InstFcmp::FCond Condition = Instr->getCondition(); 2575 InstFcmp::FCond Condition = Instr->getCondition();
2481 switch (Condition) { 2576 switch (Condition) {
2482 case InstFcmp::False: 2577 case InstFcmp::False:
2483 *CondIfFalse = CondARM32::AL; 2578 return CondWhenTrue(CondARM32::kNone);
2484 *CondIfTrue0 = *CondIfTrue1 = CondARM32::kNone;
2485 break;
2486 case InstFcmp::True: 2579 case InstFcmp::True:
2487 *CondIfFalse = *CondIfTrue1 = CondARM32::kNone; 2580 return CondWhenTrue(CondARM32::AL);
2488 *CondIfTrue0 = CondARM32::AL;
2489 break; 2581 break;
2490 default: { 2582 default: {
2491 Variable *Src0R = legalizeToReg(Instr->getSrc(0)); 2583 Variable *Src0R = legalizeToReg(Instr->getSrc(0));
2492 Variable *Src1R = legalizeToReg(Instr->getSrc(1)); 2584 Variable *Src1R = legalizeToReg(Instr->getSrc(1));
2493 _vcmp(Src0R, Src1R); 2585 _vcmp(Src0R, Src1R);
2494 _vmrs(); 2586 _vmrs();
2495 assert(Condition < llvm::array_lengthof(TableFcmp)); 2587 assert(Condition < llvm::array_lengthof(TableFcmp));
2496 *CondIfTrue0 = TableFcmp[Condition].CC0; 2588 return CondWhenTrue(TableFcmp[Condition].CC0, TableFcmp[Condition].CC1);
2497 *CondIfTrue1 = TableFcmp[Condition].CC1;
2498 *CondIfFalse = (*CondIfTrue1 != CondARM32::kNone)
2499 ? CondARM32::AL
2500 : InstARM32::getOppositeCondition(*CondIfTrue0);
2501 } 2589 }
2502 } 2590 }
2503 } 2591 }
2504 2592
2505 void TargetARM32::lowerFcmp(const InstFcmp *Instr) { 2593 void TargetARM32::lowerFcmp(const InstFcmp *Instr) {
2506 Variable *Dest = Instr->getDest(); 2594 Variable *Dest = Instr->getDest();
2507 if (isVectorType(Dest->getType())) { 2595 if (isVectorType(Dest->getType())) {
2508 Variable *T = makeReg(Dest->getType()); 2596 Variable *T = makeReg(Dest->getType());
2509 Context.insert(InstFakeDef::create(Func, T)); 2597 Context.insert(InstFakeDef::create(Func, T));
2510 _mov(Dest, T); 2598 _mov(Dest, T);
2511 UnimplementedError(Func->getContext()->getFlags()); 2599 UnimplementedError(Func->getContext()->getFlags());
2512 return; 2600 return;
2513 } 2601 }
2514 2602
2515 Variable *T = makeReg(IceType_i1); 2603 Variable *T = makeReg(IceType_i1);
2516 Operand *_1 = Ctx->getConstantInt32(1); 2604 Operand *_1 = legalize(Ctx->getConstantInt32(1), Legal_Reg | Legal_Flex);
2517 Operand *_0 = Ctx->getConstantZero(IceType_i32); 2605 Operand *_0 =
2606 legalize(Ctx->getConstantZero(IceType_i32), Legal_Reg | Legal_Flex);
2518 2607
2519 CondARM32::Cond CondIfTrue0, CondIfTrue1, CondIfFalse; 2608 CondWhenTrue Cond = lowerFcmpCond(Instr);
2520 lowerFcmpCond(Instr, &CondIfTrue0, &CondIfTrue1, &CondIfFalse);
2521 2609
2522 bool RedefineT = false; 2610 bool RedefineT = false;
2523 if (CondIfFalse != CondARM32::kNone) { 2611 if (Cond.WhenTrue0 != CondARM32::AL) {
2524 assert(!RedefineT); 2612 _mov(T, _0);
2525 _mov(T, _0, CondIfFalse);
2526 RedefineT = true; 2613 RedefineT = true;
2527 } 2614 }
2528 2615
2529 if (CondIfTrue0 != CondARM32::kNone) { 2616 if (Cond.WhenTrue0 == CondARM32::kNone) {
2530 if (RedefineT) { 2617 _mov(Dest, T);
2531 _mov_redefined(T, _1, CondIfTrue0); 2618 return;
2532 } else {
2533 _mov(T, _1, CondIfTrue0);
2534 }
2535 RedefineT = true;
2536 } 2619 }
2537 2620
2538 if (CondIfTrue1 != CondARM32::kNone) { 2621 if (RedefineT) {
2539 assert(RedefineT); 2622 _mov_redefined(T, _1, Cond.WhenTrue0);
2540 _mov_redefined(T, _1, CondIfTrue1); 2623 } else {
2624 _mov(T, _1, Cond.WhenTrue0);
2625 }
2626
2627 if (Cond.WhenTrue1 != CondARM32::kNone) {
2628 _mov_redefined(T, _1, Cond.WhenTrue1);
2541 } 2629 }
2542 2630
2543 _mov(Dest, T); 2631 _mov(Dest, T);
2544 } 2632 }
2545 2633
2546 void TargetARM32::lowerIcmpCond(const InstIcmp *Inst, 2634 TargetARM32::CondWhenTrue TargetARM32::lowerIcmpCond(const InstIcmp *Inst) {
2547 CondARM32::Cond *CondIfTrue, 2635 assert(Inst->getSrc(0)->getType() != IceType_i1);
2548 CondARM32::Cond *CondIfFalse) { 2636 assert(Inst->getSrc(1)->getType() != IceType_i1);
2637
2549 Operand *Src0 = legalizeUndef(Inst->getSrc(0)); 2638 Operand *Src0 = legalizeUndef(Inst->getSrc(0));
2550 Operand *Src1 = legalizeUndef(Inst->getSrc(1)); 2639 Operand *Src1 = legalizeUndef(Inst->getSrc(1));
2551 2640
2552 // a=icmp cond, b, c ==> 2641 // a=icmp cond, b, c ==>
2553 // GCC does: 2642 // GCC does:
2554 // cmp b.hi, c.hi or cmp b.lo, c.lo 2643 // cmp b.hi, c.hi or cmp b.lo, c.lo
2555 // cmp.eq b.lo, c.lo sbcs t1, b.hi, c.hi 2644 // cmp.eq b.lo, c.lo sbcs t1, b.hi, c.hi
2556 // mov.<C1> t, #1 mov.<C1> t, #1 2645 // mov.<C1> t, #1 mov.<C1> t, #1
2557 // mov.<C2> t, #0 mov.<C2> t, #0 2646 // mov.<C2> t, #0 mov.<C2> t, #0
2558 // mov a, t mov a, t 2647 // mov a, t mov a, t
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
2600 Variable *ScratchReg = makeReg(IceType_i32); 2689 Variable *ScratchReg = makeReg(IceType_i32);
2601 _cmp(Src0Lo, Src1LoRF); 2690 _cmp(Src0Lo, Src1LoRF);
2602 _sbcs(ScratchReg, Src0Hi, Src1HiRF); 2691 _sbcs(ScratchReg, Src0Hi, Src1HiRF);
2603 // ScratchReg isn't going to be used, but we need the side-effect of 2692 // ScratchReg isn't going to be used, but we need the side-effect of
2604 // setting flags from this operation. 2693 // setting flags from this operation.
2605 Context.insert(InstFakeUse::create(Func, ScratchReg)); 2694 Context.insert(InstFakeUse::create(Func, ScratchReg));
2606 } else { 2695 } else {
2607 _cmp(Src0Hi, Src1HiRF); 2696 _cmp(Src0Hi, Src1HiRF);
2608 _cmp(Src0Lo, Src1LoRF, CondARM32::EQ); 2697 _cmp(Src0Lo, Src1LoRF, CondARM32::EQ);
2609 } 2698 }
2610 *CondIfTrue = TableIcmp64[Index].C1; 2699 return CondWhenTrue(TableIcmp64[Index].C1);
2611 *CondIfFalse = TableIcmp64[Index].C2;
2612 return;
2613 } 2700 }
2614 2701
2615 // a=icmp cond b, c ==> 2702 // a=icmp cond b, c ==>
2616 // GCC does: 2703 // GCC does:
2617 // <u/s>xtb tb, b 2704 // <u/s>xtb tb, b
2618 // <u/s>xtb tc, c 2705 // <u/s>xtb tc, c
2619 // cmp tb, tc 2706 // cmp tb, tc
2620 // mov.C1 t, #0 2707 // mov.C1 t, #0
2621 // mov.C2 t, #1 2708 // mov.C2 t, #1
2622 // mov a, t 2709 // mov a, t
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
2654 } 2741 }
2655 if (ShiftAmt) { 2742 if (ShiftAmt) {
2656 Variable *Src1R = legalizeToReg(Src1); 2743 Variable *Src1R = legalizeToReg(Src1);
2657 OperandARM32FlexReg *Src1RShifted = OperandARM32FlexReg::create( 2744 OperandARM32FlexReg *Src1RShifted = OperandARM32FlexReg::create(
2658 Func, IceType_i32, Src1R, OperandARM32::LSL, ShiftConst); 2745 Func, IceType_i32, Src1R, OperandARM32::LSL, ShiftConst);
2659 _cmp(Src0R, Src1RShifted); 2746 _cmp(Src0R, Src1RShifted);
2660 } else { 2747 } else {
2661 Operand *Src1RF = legalize(Src1, Legal_Reg | Legal_Flex); 2748 Operand *Src1RF = legalize(Src1, Legal_Reg | Legal_Flex);
2662 _cmp(Src0R, Src1RF); 2749 _cmp(Src0R, Src1RF);
2663 } 2750 }
2664 *CondIfTrue = getIcmp32Mapping(Inst->getCondition()); 2751 return CondWhenTrue(getIcmp32Mapping(Inst->getCondition()));
2665 *CondIfFalse = InstARM32::getOppositeCondition(*CondIfTrue);
2666 } 2752 }
2667 2753
2668 void TargetARM32::lowerIcmp(const InstIcmp *Inst) { 2754 void TargetARM32::lowerIcmp(const InstIcmp *Inst) {
2669 Variable *Dest = Inst->getDest(); 2755 Variable *Dest = Inst->getDest();
2670 2756
2671 if (isVectorType(Dest->getType())) { 2757 if (isVectorType(Dest->getType())) {
2672 Variable *T = makeReg(Dest->getType()); 2758 Variable *T = makeReg(Dest->getType());
2673 Context.insert(InstFakeDef::create(Func, T)); 2759 Context.insert(InstFakeDef::create(Func, T));
2674 _mov(Dest, T); 2760 _mov(Dest, T);
2675 UnimplementedError(Func->getContext()->getFlags()); 2761 UnimplementedError(Func->getContext()->getFlags());
2676 return; 2762 return;
2677 } 2763 }
2678 2764
2679 Constant *_0 = Ctx->getConstantZero(IceType_i32); 2765 Operand *_0 =
2680 Constant *_1 = Ctx->getConstantInt32(1); 2766 legalize(Ctx->getConstantZero(IceType_i32), Legal_Reg | Legal_Flex);
2767 Operand *_1 = legalize(Ctx->getConstantInt32(1), Legal_Reg | Legal_Flex);
2681 Variable *T = makeReg(IceType_i1); 2768 Variable *T = makeReg(IceType_i1);
2682 2769
2683 CondARM32::Cond CondIfTrue, CondIfFalse; 2770 _mov(T, _0);
2684 lowerIcmpCond(Inst, &CondIfTrue, &CondIfFalse); 2771 CondWhenTrue Cond = lowerIcmpCond(Inst);
2772 _mov_redefined(T, _1, Cond.WhenTrue0);
2773 _mov(Dest, T);
2685 2774
2686 _mov(T, _0, CondIfFalse); 2775 assert(Cond.WhenTrue1 == CondARM32::kNone);
2687 _mov_redefined(T, _1, CondIfTrue);
2688 _mov(Dest, T);
2689 2776
2690 return; 2777 return;
2691 } 2778 }
2692 2779
2693 void TargetARM32::lowerInsertElement(const InstInsertElement *Inst) { 2780 void TargetARM32::lowerInsertElement(const InstInsertElement *Inst) {
2694 (void)Inst; 2781 (void)Inst;
2695 UnimplementedError(Func->getContext()->getFlags()); 2782 UnimplementedError(Func->getContext()->getFlags());
2696 } 2783 }
2697 2784
2698 namespace { 2785 namespace {
(...skipping 1197 matching lines...) Expand 10 before | Expand all | Expand 10 after
3896 Operand *Condition = Inst->getCondition(); 3983 Operand *Condition = Inst->getCondition();
3897 3984
3898 if (isVectorType(DestTy)) { 3985 if (isVectorType(DestTy)) {
3899 Variable *T = makeReg(DestTy); 3986 Variable *T = makeReg(DestTy);
3900 Context.insert(InstFakeDef::create(Func, T)); 3987 Context.insert(InstFakeDef::create(Func, T));
3901 _mov(Dest, T); 3988 _mov(Dest, T);
3902 UnimplementedError(Func->getContext()->getFlags()); 3989 UnimplementedError(Func->getContext()->getFlags());
3903 return; 3990 return;
3904 } 3991 }
3905 3992
3906 CondARM32::Cond CondIfTrue0, CondIfTrue1, CondIfFalse; 3993 lowerInt1ForSelect(Dest, Condition, legalizeUndef(SrcT), legalizeUndef(SrcF));
3907 if (!_mov_i1_to_flags(Condition, &CondIfTrue0, &CondIfTrue1, &CondIfFalse)) {
3908 // "Condition" was not fold.
3909 // cmp cond, #0; mov t, SrcF; mov_cond t, SrcT; mov dest, t
3910 Variable *CmpOpnd0 = legalizeToReg(Condition);
3911 Type CmpOpnd0Ty = CmpOpnd0->getType();
3912 Operand *CmpOpnd1 = Ctx->getConstantZero(IceType_i32);
3913 assert(CmpOpnd0Ty == IceType_i1);
3914 if (CmpOpnd0Ty != IceType_i32)
3915 _uxt(CmpOpnd0, CmpOpnd0);
3916 _cmp(CmpOpnd0, CmpOpnd1);
3917 CondIfTrue0 = CondARM32::NE;
3918 CondIfTrue1 = CondARM32::kNone;
3919 CondIfFalse = CondARM32::EQ;
3920 }
3921
3922 if (DestTy == IceType_i64) {
3923 SrcT = legalizeUndef(SrcT);
3924 SrcF = legalizeUndef(SrcF);
3925 // Set the low portion.
3926 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest));
3927 Operand *SrcTLo = legalize(loOperand(SrcT), Legal_Reg | Legal_Flex);
3928 Operand *SrcFLo = legalize(loOperand(SrcF), Legal_Reg | Legal_Flex);
3929 Variable *TLo = makeReg(SrcFLo->getType());
3930 bool RedefineTLo = false;
3931 if (CondIfFalse != CondARM32::kNone) {
3932 _mov(TLo, SrcFLo, CondIfFalse);
3933 RedefineTLo = true;
3934 }
3935 if (CondIfTrue0 != CondARM32::kNone) {
3936 if (!RedefineTLo)
3937 _mov(TLo, SrcTLo, CondIfTrue0);
3938 else
3939 _mov_redefined(TLo, SrcTLo, CondIfTrue0);
3940 RedefineTLo = true;
3941 }
3942 if (CondIfTrue1 != CondARM32::kNone) {
3943 assert(RedefineTLo);
3944 _mov_redefined(TLo, SrcTLo, CondIfTrue1);
3945 }
3946 _mov(DestLo, TLo);
3947
3948 // Set the high portion.
3949 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest));
3950 Operand *SrcTHi = legalize(hiOperand(SrcT), Legal_Reg | Legal_Flex);
3951 Operand *SrcFHi = legalize(hiOperand(SrcF), Legal_Reg | Legal_Flex);
3952 Variable *THi = makeReg(SrcFHi->getType());
3953 bool RedefineTHi = false;
3954 if (CondIfFalse != CondARM32::kNone) {
3955 _mov(THi, SrcFHi, CondIfFalse);
3956 RedefineTHi = true;
3957 }
3958 if (CondIfTrue0 != CondARM32::kNone) {
3959 if (!RedefineTHi)
3960 _mov(THi, SrcTHi, CondIfTrue0);
3961 else
3962 _mov_redefined(THi, SrcTHi, CondIfTrue0);
3963 RedefineTHi = true;
3964 }
3965 if (CondIfTrue1 != CondARM32::kNone) {
3966 assert(RedefineTHi);
3967 _mov_redefined(THi, SrcTHi, CondIfTrue1);
3968 }
3969 _mov(DestHi, THi);
3970 return;
3971 }
3972
3973 if (isFloatingType(DestTy)) {
3974 SrcT = legalizeToReg(SrcT);
3975 SrcF = legalizeToReg(SrcF);
3976 Variable *T = makeReg(DestTy);
3977 assert(DestTy == SrcF->getType());
3978 bool RedefineT = false;
3979 if (CondIfFalse != CondARM32::kNone) {
3980 _mov(T, SrcF, CondIfFalse);
3981 RedefineT = true;
3982 }
3983 if (CondIfTrue0 != CondARM32::kNone) {
3984 if (!RedefineT)
3985 _mov(T, SrcT, CondIfTrue0);
3986 else
3987 _mov_redefined(T, SrcT, CondIfTrue0);
3988 RedefineT = true;
3989 }
3990 if (CondIfTrue1 != CondARM32::kNone) {
3991 assert(RedefineT);
3992 _mov_redefined(T, SrcT, CondIfTrue1);
3993 }
3994 assert(DestTy == SrcT->getType());
3995 _mov(Dest, T);
3996 return;
3997 }
3998
3999 Variable *T = makeReg(SrcF->getType());
4000 SrcT = legalize(SrcT, Legal_Reg | Legal_Flex);
4001 SrcF = legalize(SrcF, Legal_Reg | Legal_Flex);
4002 bool RedefineT = false;
4003 if (CondIfFalse != CondARM32::kNone) {
4004 _mov(T, SrcF, CondIfFalse);
4005 RedefineT = true;
4006 }
4007 if (CondIfTrue0 != CondARM32::kNone) {
4008 if (!RedefineT)
4009 _mov(T, SrcT, CondIfTrue0);
4010 else
4011 _mov_redefined(T, SrcT, CondIfTrue0);
4012 RedefineT = true;
4013 }
4014 if (CondIfTrue1 != CondARM32::kNone) {
4015 assert(RedefineT);
4016 _mov_redefined(T, SrcT, CondIfTrue1);
4017 }
4018 _mov(Dest, T);
4019 } 3994 }
4020 3995
4021 void TargetARM32::lowerStore(const InstStore *Inst) { 3996 void TargetARM32::lowerStore(const InstStore *Inst) {
4022 Operand *Value = Inst->getData(); 3997 Operand *Value = Inst->getData();
4023 Operand *Addr = Inst->getAddr(); 3998 Operand *Addr = Inst->getAddr();
4024 OperandARM32Mem *NewAddr = formMemoryOperand(Addr, Value->getType()); 3999 OperandARM32Mem *NewAddr = formMemoryOperand(Addr, Value->getType());
4025 Type Ty = NewAddr->getType(); 4000 Type Ty = NewAddr->getType();
4026 4001
4027 if (Ty == IceType_i64) { 4002 if (Ty == IceType_i64) {
4028 Value = legalizeUndef(Value); 4003 Value = legalizeUndef(Value);
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after
4423 4398
4424 void TargetARM32::emit(const ConstantDouble *C) const { 4399 void TargetARM32::emit(const ConstantDouble *C) const {
4425 (void)C; 4400 (void)C;
4426 UnimplementedError(Ctx->getFlags()); 4401 UnimplementedError(Ctx->getFlags());
4427 } 4402 }
4428 4403
4429 void TargetARM32::emit(const ConstantUndef *) const { 4404 void TargetARM32::emit(const ConstantUndef *) const {
4430 llvm::report_fatal_error("undef value encountered by emitter."); 4405 llvm::report_fatal_error("undef value encountered by emitter.");
4431 } 4406 }
4432 4407
4433 void TargetARM32::lowerTruncToFlags(Operand *Src, CondARM32::Cond *CondIfTrue, 4408 void TargetARM32::lowerInt1ForSelect(Variable *Dest, Operand *Boolean,
4434 CondARM32::Cond *CondIfFalse) { 4409 Operand *TrueValue, Operand *FalseValue) {
4435 Operand *_1 = Ctx->getConstantInt32(1); 4410 Operand *_1 = legalize(Ctx->getConstantInt1(1), Legal_Reg | Legal_Flex);
4436 Variable *SrcR = 4411
4437 legalizeToReg(Src->getType() == IceType_i64 ? loOperand(Src) : Src); 4412 assert(Boolean->getType() == IceType_i1);
4438 _tst(SrcR, _1); 4413
4439 *CondIfTrue = CondARM32::NE; // NE <-> APSR.Z == 0 4414 bool NeedsAnd1 = false;
4440 *CondIfFalse = CondARM32::EQ; // EQ <-> APSR.Z == 1 4415 if (TrueValue->getType() == IceType_i1) {
4441 } 4416 assert(FalseValue->getType() == IceType_i1);
4442 4417
4443 bool TargetARM32::_mov_i1_to_flags(Operand *Boolean, 4418 Variable *TrueValueV = Func->makeVariable(IceType_i1);
4444 CondARM32::Cond *CondIfTrue0, 4419 SafeBoolChain Src0Safe = lowerInt1(TrueValueV, TrueValue);
4445 CondARM32::Cond *CondIfTrue1, 4420 TrueValue = TrueValueV;
4446 CondARM32::Cond *CondIfFalse) { 4421
4447 *CondIfTrue0 = CondARM32::kNone; 4422 Variable *FalseValueV = Func->makeVariable(IceType_i1);
4448 *CondIfTrue1 = CondARM32::kNone; 4423 SafeBoolChain Src1Safe = lowerInt1(FalseValueV, FalseValue);
4449 *CondIfFalse = CondARM32::AL; 4424 FalseValue = FalseValueV;
4450 bool FoldOK = false; 4425
4426 NeedsAnd1 = Src0Safe == SBC_No || Src1Safe == SBC_No;
4427 }
4428
4429 Variable *DestLo = (Dest->getType() == IceType_i64)
4430 ? llvm::cast<Variable>(loOperand(Dest))
4431 : Dest;
4432 Variable *DestHi = (Dest->getType() == IceType_i64)
4433 ? llvm::cast<Variable>(hiOperand(Dest))
4434 : nullptr;
4435 Operand *FalseValueLo = (FalseValue->getType() == IceType_i64)
4436 ? loOperand(FalseValue)
4437 : FalseValue;
4438 Operand *FalseValueHi =
4439 (FalseValue->getType() == IceType_i64) ? hiOperand(FalseValue) : nullptr;
4440
4441 Operand *TrueValueLo =
4442 (TrueValue->getType() == IceType_i64) ? loOperand(TrueValue) : TrueValue;
4443 Operand *TrueValueHi =
4444 (TrueValue->getType() == IceType_i64) ? hiOperand(TrueValue) : nullptr;
4445
4446 Variable *T_Lo = makeReg(DestLo->getType());
4447 Variable *T_Hi = (DestHi == nullptr) ? nullptr : makeReg(DestHi->getType());
4448
4449 _mov(T_Lo, legalize(FalseValueLo, Legal_Reg | Legal_Flex));
4450 if (DestHi) {
4451 _mov(T_Hi, legalize(FalseValueHi, Legal_Reg | Legal_Flex));
4452 }
4453
4454 CondWhenTrue Cond(CondARM32::kNone);
4455 // FlagsWereSet is used to determine wether Boolean was fold or not. If not,
Jim Stichnoth 2015/11/11 18:55:04 whether ... folded
John 2015/11/11 22:19:46 Done.
4456 // and explicit
Jim Stichnoth 2015/11/11 18:55:04 "and" is probably the wrong word here? Also, refl
John 2015/11/11 22:19:46 Done.
4457 // _tst instruction below.
4458 bool FlagsWereSet = false;
4451 if (const Inst *Producer = BoolComputations.getProducerOf(Boolean)) { 4459 if (const Inst *Producer = BoolComputations.getProducerOf(Boolean)) {
4452 if (const auto *IcmpProducer = llvm::dyn_cast<InstIcmp>(Producer)) { 4460 switch (Producer->getKind()) {
4453 lowerIcmpCond(IcmpProducer, CondIfTrue0, CondIfFalse); 4461 default:
4454 FoldOK = true; 4462 llvm_unreachable("Unexpected producer.");
4455 } else if (const auto *FcmpProducer = llvm::dyn_cast<InstFcmp>(Producer)) { 4463 case Inst::Icmp: {
4456 lowerFcmpCond(FcmpProducer, CondIfTrue0, CondIfTrue1, CondIfFalse); 4464 Cond = lowerIcmpCond(llvm::cast<InstIcmp>(Producer));
4457 FoldOK = true; 4465 FlagsWereSet = true;
4458 } else if (const auto *CastProducer = llvm::dyn_cast<InstCast>(Producer)) { 4466 } break;
4467 case Inst::Fcmp: {
4468 Cond = lowerFcmpCond(llvm::cast<InstFcmp>(Producer));
4469 FlagsWereSet = true;
4470 } break;
4471 case Inst::Cast: {
4472 const auto *CastProducer = llvm::cast<InstCast>(Producer);
4459 assert(CastProducer->getCastKind() == InstCast::Trunc); 4473 assert(CastProducer->getCastKind() == InstCast::Trunc);
4460 lowerTruncToFlags(CastProducer->getSrc(0), CondIfTrue0, CondIfFalse); 4474 Boolean = CastProducer->getSrc(0);
4461 FoldOK = true; 4475 // No flags were set, so a _tst(Src, 1) will be emitted below. Don't
4462 } 4476 // bother legalizing Src to a Reg because it will be legalized before
4463 } 4477 // emitting the tst instruction.
4464 return FoldOK; 4478 FlagsWereSet = false;
4479 } break;
4480 case Inst::Arithmetic: {
4481 // This is a special case: we eagerly assumed Producer could be fold, but
Jim Stichnoth 2015/11/11 18:55:04 folded ?
John 2015/11/11 22:19:46 Done.
4482 // in reality, it can't. No reason to panic: we just lower it using the
4483 // regular lowerArithmetic helper.
4484 const auto *ArithProducer = llvm::cast<InstArithmetic>(Producer);
4485 lowerArithmetic(ArithProducer);
4486 Boolean = ArithProducer->getDest();
4487 // No flags were set, so a _tst(Dest, 1) will be emitted below. Don't
4488 // bother legalizing Dest to a Reg because it will be legalized before
4489 // emitting the tst instruction.
Jim Stichnoth 2015/11/11 18:55:04 single space char between "emitting the"
John 2015/11/11 22:19:44 Done.
4490 FlagsWereSet = false;
4491 } break;
4492 }
4493 }
4494
4495 if (!FlagsWereSet) {
4496 // No flags have been set, so emit a tst Boolean, 1.
4497 Variable *Src = legalizeToReg(Boolean);
4498 _tst(Src, _1);
4499 Cond = CondWhenTrue(CondARM32::NE); // i.e., CondARM32::NotZero.
4500 }
4501
4502 if (Cond.WhenTrue0 == CondARM32::kNone) {
4503 assert(Cond.WhenTrue1 == CondARM32::kNone);
4504 } else {
4505 _mov_redefined(T_Lo, legalize(TrueValueLo, Legal_Reg | Legal_Flex),
4506 Cond.WhenTrue0);
4507 if (DestHi) {
4508 _mov_redefined(T_Hi, legalize(TrueValueHi, Legal_Reg | Legal_Flex),
4509 Cond.WhenTrue0);
4510 }
4511 }
4512
4513 if (Cond.WhenTrue1 != CondARM32::kNone) {
4514 _mov_redefined(T_Lo, legalize(TrueValueLo, Legal_Reg | Legal_Flex),
4515 Cond.WhenTrue1);
4516 if (DestHi) {
4517 _mov_redefined(T_Hi, legalize(TrueValueHi, Legal_Reg | Legal_Flex),
4518 Cond.WhenTrue1);
4519 }
4520 }
4521
4522 if (NeedsAnd1) {
4523 // We lowered something that is unsafe (i.e., can't provably be zero or
4524 // one). Truncate the result.
4525 _and(T_Lo, T_Lo, _1);
4526 }
4527
4528 _mov(DestLo, T_Lo);
4529 if (DestHi) {
4530 _mov(DestHi, T_Hi);
4531 }
4532 }
4533
4534 TargetARM32::SafeBoolChain TargetARM32::lowerInt1(Variable *Dest,
4535 Operand *Boolean) {
4536 assert(Boolean->getType() == IceType_i1);
4537 Variable *T = makeReg(IceType_i1);
4538 Operand *_0 =
4539 legalize(Ctx->getConstantZero(IceType_i1), Legal_Reg | Legal_Flex);
4540 Operand *_1 = legalize(Ctx->getConstantInt1(1), Legal_Reg | Legal_Flex);
4541
4542 SafeBoolChain Safe = SBC_Yes;
4543 if (const Inst *Producer = BoolComputations.getProducerOf(Boolean)) {
4544 switch (Producer->getKind()) {
4545 default:
4546 llvm_unreachable("Unexpected producer.");
4547 case Inst::Icmp: {
4548 _mov(T, _0);
4549 CondWhenTrue Cond = lowerIcmpCond(llvm::cast<InstIcmp>(Producer));
4550 assert(Cond.WhenTrue0 != CondARM32::AL);
4551 assert(Cond.WhenTrue0 != CondARM32::kNone);
4552 assert(Cond.WhenTrue1 == CondARM32::kNone);
4553 _mov_redefined(T, _1, Cond.WhenTrue0);
4554 } break;
4555 case Inst::Fcmp: {
4556 _mov(T, _0);
4557 Inst *MovZero = Context.getLastInserted();
4558 CondWhenTrue Cond = lowerFcmpCond(llvm::cast<InstFcmp>(Producer));
4559 if (Cond.WhenTrue0 == CondARM32::AL) {
4560 assert(Cond.WhenTrue1 == CondARM32::kNone);
4561 MovZero->setDeleted();
4562 _mov(T, _1);
4563 } else if (Cond.WhenTrue0 != CondARM32::kNone) {
4564 _mov_redefined(T, _1, Cond.WhenTrue0);
4565 }
4566 if (Cond.WhenTrue1 != CondARM32::kNone) {
4567 assert(Cond.WhenTrue0 != CondARM32::kNone);
4568 assert(Cond.WhenTrue0 != CondARM32::AL);
4569 _mov_redefined(T, _1, Cond.WhenTrue1);
4570 }
4571 } break;
4572 case Inst::Cast: {
4573 const auto *CastProducer = llvm::cast<InstCast>(Producer);
4574 assert(CastProducer->getCastKind() == InstCast::Trunc);
4575 Operand *Src = CastProducer->getSrc(0);
4576 if (Src->getType() == IceType_i64)
4577 Src = loOperand(Src);
4578 _mov(T, legalize(Src, Legal_Reg | Legal_Flex));
4579 Safe = SBC_No;
4580 } break;
4581 case Inst::Arithmetic: {
4582 const auto *ArithProducer = llvm::cast<InstArithmetic>(Producer);
4583 Safe = lowerInt1Arithmetic(ArithProducer);
4584 _mov(T, ArithProducer->getDest());
4585 } break;
4586 }
4587 } else {
4588 _mov(T, legalize(Boolean, Legal_Reg | Legal_Flex));
4589 }
4590
4591 _mov(Dest, T);
4592 return Safe;
4465 } 4593 }
4466 4594
4467 namespace { 4595 namespace {
4468 namespace BoolFolding { 4596 namespace BoolFolding {
4469 bool shouldTrackProducer(const Inst &Instr) { 4597 bool shouldTrackProducer(const Inst &Instr) {
4470 switch (static_cast<uint32_t>(Instr.getKind())) { 4598 switch (Instr.getKind()) {
4599 default:
4600 return false;
4471 case Inst::Icmp: 4601 case Inst::Icmp:
4472 return true;
4473 case Inst::Fcmp: 4602 case Inst::Fcmp:
4474 return true; 4603 return true;
4475 } 4604 case Inst::Cast: {
4476 if (const auto *Cast = llvm::dyn_cast<InstCast>(&Instr)) { 4605 switch (llvm::cast<InstCast>(&Instr)->getCastKind()) {
4477 switch (static_cast<uint32_t>(Cast->getCastKind())) { 4606 default:
4607 return false;
4478 case InstCast::Trunc: 4608 case InstCast::Trunc:
4479 return true; 4609 return true;
4480 } 4610 }
4481 } 4611 }
4482 return false; 4612 case Inst::Arithmetic: {
4613 switch (llvm::cast<InstArithmetic>(&Instr)->getOp()) {
4614 default:
4615 return false;
4616 case InstArithmetic::And:
4617 case InstArithmetic::Or:
4618 return true;
4619 }
4620 }
4621 }
4483 } 4622 }
4484 4623
4485 bool isValidConsumer(const Inst &Instr) { 4624 bool isValidConsumer(const Inst &Instr) {
4486 switch (static_cast<uint32_t>(Instr.getKind())) { 4625 switch (Instr.getKind()) {
4626 default:
4627 return false;
4487 case Inst::Br: 4628 case Inst::Br:
4488 return true; 4629 return true;
4489 case Inst::Select: 4630 case Inst::Select:
4490 return !isVectorType(Instr.getDest()->getType()); 4631 return !isVectorType(Instr.getDest()->getType());
4491 } 4632 case Inst::Cast: {
4492 if (const auto *Cast = llvm::dyn_cast<InstCast>(&Instr)) { 4633 switch (llvm::cast<InstCast>(&Instr)->getCastKind()) {
4493 switch (static_cast<uint32_t>(Cast->getCastKind())) { 4634 default:
4635 return false;
4494 case InstCast::Sext: 4636 case InstCast::Sext:
4495 return !isVectorType(Instr.getDest()->getType()); 4637 return !isVectorType(Instr.getDest()->getType());
4496 case InstCast::Zext: 4638 case InstCast::Zext:
4497 return !isVectorType(Instr.getDest()->getType()); 4639 return !isVectorType(Instr.getDest()->getType());
4498 } 4640 }
4499 } 4641 }
4500 return false; 4642 case Inst::Arithmetic: {
4643 switch (llvm::cast<InstArithmetic>(&Instr)->getOp()) {
4644 default:
4645 return false;
4646 case InstArithmetic::And:
4647 return !isVectorType(Instr.getDest()->getType());
4648 case InstArithmetic::Or:
4649 return !isVectorType(Instr.getDest()->getType());
4650 }
4651 }
4652 }
4501 } 4653 }
4502 } // end of namespace BoolFolding 4654 } // end of namespace BoolFolding
4503 } // end of anonymous namespace 4655 } // end of anonymous namespace
4504 4656
4505 void TargetARM32::BoolComputationTracker::recordProducers(CfgNode *Node) { 4657 void TargetARM32::BoolComputationTracker::recordProducers(CfgNode *Node) {
4506 for (Inst &Instr : Node->getInsts()) { 4658 for (Inst &Instr : Node->getInsts()) {
4507 // Check whether Instr is a valid producer. 4659 // Check whether Instr is a valid producer.
4508 Variable *Dest = Instr.getDest(); 4660 Variable *Dest = Instr.getDest();
4509 if (!Instr.isDeleted() // only consider non-deleted instructions; and 4661 if (!Instr.isDeleted() // only consider non-deleted instructions; and
4510 && Dest // only instructions with an actual dest var; and 4662 && Dest // only instructions with an actual dest var; and
4511 && Dest->getType() == IceType_i1 // only bool-type dest vars; and 4663 && Dest->getType() == IceType_i1 // only bool-type dest vars; and
4512 && BoolFolding::shouldTrackProducer(Instr)) { // white-listed instr. 4664 && BoolFolding::shouldTrackProducer(Instr)) { // white-listed instr.
4513 KnownComputations.emplace(Dest->getIndex(), BoolComputationEntry(&Instr)); 4665 KnownComputations.emplace(Dest->getIndex(), BoolComputationEntry(&Instr));
4514 } 4666 }
4515 // Check each src variable against the map. 4667 // Check each src variable against the map.
4516 FOREACH_VAR_IN_INST(Var, Instr) { 4668 FOREACH_VAR_IN_INST(Var, Instr) {
4517 SizeT VarNum = Var->getIndex(); 4669 SizeT VarNum = Var->getIndex();
4518 auto ComputationIter = KnownComputations.find(VarNum); 4670 auto ComputationIter = KnownComputations.find(VarNum);
4519 if (ComputationIter == KnownComputations.end()) { 4671 if (ComputationIter == KnownComputations.end()) {
4520 continue; 4672 continue;
4521 } 4673 }
4522 4674
4523 if (IndexOfVarOperandInInst(Var) != 0 || 4675 ++ComputationIter->second.NumUses;
4524 !BoolFolding::isValidConsumer(Instr)) { 4676 if (!BoolFolding::isValidConsumer(Instr)) {
4525 // All valid consumers use Var as the first source operand
4526 KnownComputations.erase(VarNum); 4677 KnownComputations.erase(VarNum);
4527 continue; 4678 continue;
4528 } 4679 }
4529 4680
4530 if (Instr.isLastUse(Var)) { 4681 if (Instr.isLastUse(Var)) {
4531 ComputationIter->second.IsLiveOut = false; 4682 ComputationIter->second.IsLiveOut = false;
4532 } 4683 }
4533 } 4684 }
4534 } 4685 }
4535 4686
4536 for (auto Iter = KnownComputations.begin(), End = KnownComputations.end(); 4687 for (auto Iter = KnownComputations.begin(), End = KnownComputations.end();
4537 Iter != End;) { 4688 Iter != End;) {
4538 // Disable the folding if its dest may be live beyond this block. 4689 // Disable the folding if its dest may be live beyond this block.
4539 if (Iter->second.IsLiveOut) { 4690 if (Iter->second.IsLiveOut || Iter->second.NumUses > 1) {
4540 Iter = KnownComputations.erase(Iter); 4691 Iter = KnownComputations.erase(Iter);
4541 continue; 4692 continue;
4542 } 4693 }
4543 4694
4544 // Mark as "dead" rather than outright deleting. This is so that other 4695 // Mark as "dead" rather than outright deleting. This is so that other
4545 // peephole style optimizations during or before lowering have access to 4696 // peephole style optimizations during or before lowering have access to
4546 // this instruction in undeleted form. See for example 4697 // this instruction in undeleted form. See for example
4547 // tryOptimizedCmpxchgCmpBr(). 4698 // tryOptimizedCmpxchgCmpBr().
4548 Iter->second.Instr->setDead(); 4699 Iter->second.Instr->setDead();
4549 ++Iter; 4700 ++Iter;
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
4738 // Technically R9 is used for TLS with Sandboxing, and we reserve it. 4889 // Technically R9 is used for TLS with Sandboxing, and we reserve it.
4739 // However, for compatibility with current NaCl LLVM, don't claim that. 4890 // However, for compatibility with current NaCl LLVM, don't claim that.
4740 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; 4891 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n";
4741 } 4892 }
4742 4893
4743 llvm::SmallBitVector TargetARM32::TypeToRegisterSet[IceType_NUM]; 4894 llvm::SmallBitVector TargetARM32::TypeToRegisterSet[IceType_NUM];
4744 llvm::SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; 4895 llvm::SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM];
4745 llvm::SmallBitVector TargetARM32::ScratchRegs; 4896 llvm::SmallBitVector TargetARM32::ScratchRegs;
4746 4897
4747 } // end of namespace Ice 4898 } // end of namespace Ice
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698