Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 //===- subzero/src/IceTargetLoweringARM32.cpp - ARM32 lowering ------------===// | 1 //===- subzero/src/IceTargetLoweringARM32.cpp - ARM32 lowering ------------===// |
| 2 // | 2 // |
| 3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
| 4 // | 4 // |
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 /// | 9 /// |
| 10 /// \file | 10 /// \file |
| (...skipping 1026 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |