| 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 regular |
| 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); |
| 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::report_fatal_error("Unhandled i1 Op"); |
| 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 code to perform (Boolean & 1) and |
| 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); |
| 2099 // Fall-through intended. |
| 1962 case IceType_i8: | 2100 case IceType_i8: |
| 1963 case IceType_i16: | 2101 case IceType_i16: |
| 1964 case IceType_i32: | 2102 case IceType_i32: |
| 1965 ReturnReg = makeReg(Dest->getType(), RegARM32::Reg_r0); | 2103 ReturnReg = makeReg(Dest->getType(), RegARM32::Reg_r0); |
| 1966 break; | 2104 break; |
| 1967 case IceType_i64: | 2105 case IceType_i64: |
| 1968 ReturnReg = makeReg(IceType_i32, RegARM32::Reg_r0); | 2106 ReturnReg = makeReg(IceType_i32, RegARM32::Reg_r0); |
| 1969 ReturnRegHi = makeReg(IceType_i32, RegARM32::Reg_r1); | 2107 ReturnRegHi = makeReg(IceType_i32, RegARM32::Reg_r1); |
| 1970 break; | 2108 break; |
| 1971 case IceType_f32: | 2109 case IceType_f32: |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2082 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 2220 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| 2083 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 2221 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| 2084 Variable *T_Lo = makeReg(DestLo->getType()); | 2222 Variable *T_Lo = makeReg(DestLo->getType()); |
| 2085 if (Src0->getType() == IceType_i32) { | 2223 if (Src0->getType() == IceType_i32) { |
| 2086 Operand *Src0RF = legalize(Src0, Legal_Reg | Legal_Flex); | 2224 Operand *Src0RF = legalize(Src0, Legal_Reg | Legal_Flex); |
| 2087 _mov(T_Lo, Src0RF); | 2225 _mov(T_Lo, Src0RF); |
| 2088 } else if (Src0->getType() != IceType_i1) { | 2226 } else if (Src0->getType() != IceType_i1) { |
| 2089 Variable *Src0R = legalizeToReg(Src0); | 2227 Variable *Src0R = legalizeToReg(Src0); |
| 2090 _sxt(T_Lo, Src0R); | 2228 _sxt(T_Lo, Src0R); |
| 2091 } else { | 2229 } else { |
| 2092 CondARM32::Cond CondTrue0, CondTrue1, CondFalse; | 2230 Operand *_0 = Ctx->getConstantZero(IceType_i32); |
| 2093 if (_mov_i1_to_flags(Src0, &CondTrue0, &CondTrue1, &CondFalse)) { | 2231 Operand *_m1 = Ctx->getConstantInt32(-1); |
| 2094 // Handle bool folding. | 2232 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 } | 2233 } |
| 2105 _mov(DestLo, T_Lo); | 2234 _mov(DestLo, T_Lo); |
| 2106 Variable *T_Hi = makeReg(DestHi->getType()); | 2235 Variable *T_Hi = makeReg(DestHi->getType()); |
| 2107 if (Src0->getType() != IceType_i1) { | 2236 if (Src0->getType() != IceType_i1) { |
| 2108 _mov(T_Hi, OperandARM32FlexReg::create(Func, IceType_i32, T_Lo, | 2237 _mov(T_Hi, OperandARM32FlexReg::create(Func, IceType_i32, T_Lo, |
| 2109 OperandARM32::ASR, ShiftAmt)); | 2238 OperandARM32::ASR, ShiftAmt)); |
| 2110 } else { | 2239 } else { |
| 2111 // For i1, the asr instruction is already done above. | 2240 // For i1, the asr instruction is already done above. |
| 2112 _mov(T_Hi, T_Lo); | 2241 _mov(T_Hi, T_Lo); |
| 2113 } | 2242 } |
| 2114 _mov(DestHi, T_Hi); | 2243 _mov(DestHi, T_Hi); |
| 2115 } else if (Src0->getType() != IceType_i1) { | 2244 } else if (Src0->getType() != IceType_i1) { |
| 2116 // t1 = sxt src; dst = t1 | 2245 // t1 = sxt src; dst = t1 |
| 2117 Variable *Src0R = legalizeToReg(Src0); | 2246 Variable *Src0R = legalizeToReg(Src0); |
| 2118 Variable *T = makeReg(Dest->getType()); | 2247 Variable *T = makeReg(Dest->getType()); |
| 2119 _sxt(T, Src0R); | 2248 _sxt(T, Src0R); |
| 2120 _mov(Dest, T); | 2249 _mov(Dest, T); |
| 2121 } else { | 2250 } else { |
| 2251 Constant *_0 = Ctx->getConstantZero(IceType_i32); |
| 2252 Operand *_m1 = Ctx->getConstantInt(Dest->getType(), -1); |
| 2122 Variable *T = makeReg(Dest->getType()); | 2253 Variable *T = makeReg(Dest->getType()); |
| 2123 CondARM32::Cond CondTrue0, CondTrue1, CondFalse; | 2254 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); | 2255 _mov(Dest, T); |
| 2141 } | 2256 } |
| 2142 break; | 2257 break; |
| 2143 } | 2258 } |
| 2144 case InstCast::Zext: { | 2259 case InstCast::Zext: { |
| 2145 if (isVectorType(Dest->getType())) { | 2260 if (isVectorType(Dest->getType())) { |
| 2146 Variable *T = makeReg(Dest->getType()); | 2261 Variable *T = makeReg(Dest->getType()); |
| 2147 Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0))); | 2262 Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0))); |
| 2148 _mov(Dest, T); | 2263 _mov(Dest, T); |
| 2149 UnimplementedError(Func->getContext()->getFlags()); | 2264 UnimplementedError(Func->getContext()->getFlags()); |
| 2150 } else if (Dest->getType() == IceType_i64) { | 2265 } else if (Dest->getType() == IceType_i64) { |
| 2151 // t1=uxtb src; dst.lo=t1; dst.hi=0 | 2266 // t1=uxtb src; dst.lo=t1; dst.hi=0 |
| 2152 Constant *_0 = Ctx->getConstantZero(IceType_i32); | 2267 Operand *_0 = |
| 2153 Constant *_1 = Ctx->getConstantInt32(1); | 2268 legalize(Ctx->getConstantZero(IceType_i32), Legal_Reg | Legal_Flex); |
| 2154 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 2269 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| 2155 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 2270 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| 2156 Variable *T_Lo = makeReg(DestLo->getType()); | 2271 Variable *T_Lo = makeReg(DestLo->getType()); |
| 2157 | 2272 |
| 2158 CondARM32::Cond CondTrue0, CondTrue1, CondFalse; | 2273 switch (Src0->getType()) { |
| 2159 if (_mov_i1_to_flags(Src0, &CondTrue0, &CondTrue1, &CondFalse)) { | 2274 default: { |
| 2160 // Handle folding opportunities. | 2275 assert(Src0->getType() != IceType_i64); |
| 2161 Variable *T_Hi = makeReg(DestLo->getType()); | 2276 _uxt(T_Lo, legalizeToReg(Src0)); |
| 2162 _mov(T_Hi, _0); | 2277 } break; |
| 2163 _mov(DestHi, T_Hi); | 2278 case IceType_i32: { |
| 2164 _cmov(T_Lo, _1, CondTrue0, CondTrue1, _0, CondFalse); | 2279 _mov(T_Lo, legalize(Src0, Legal_Reg | Legal_Flex)); |
| 2165 _mov(DestLo, T_Lo); | 2280 } break; |
| 2166 return; | 2281 case IceType_i1: { |
| 2282 SafeBoolChain Safe = lowerInt1(T_Lo, Src0); |
| 2283 if (Safe == SBC_No) { |
| 2284 Operand *_1 = |
| 2285 legalize(Ctx->getConstantInt1(1), Legal_Reg | Legal_Flex); |
| 2286 _and(T_Lo, T_Lo, _1); |
| 2287 } |
| 2288 } break; |
| 2167 } | 2289 } |
| 2168 | 2290 |
| 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); | 2291 _mov(DestLo, T_Lo); |
| 2292 |
| 2183 Variable *T_Hi = makeReg(DestLo->getType()); | 2293 Variable *T_Hi = makeReg(DestLo->getType()); |
| 2184 _mov(T_Hi, _0); | 2294 _mov(T_Hi, _0); |
| 2185 _mov(DestHi, T_Hi); | 2295 _mov(DestHi, T_Hi); |
| 2186 } else if (Src0->getType() == IceType_i1) { | 2296 } else if (Src0->getType() == IceType_i1) { |
| 2187 Constant *_1 = Ctx->getConstantInt32(1); | |
| 2188 Variable *T = makeReg(Dest->getType()); | 2297 Variable *T = makeReg(Dest->getType()); |
| 2189 | 2298 |
| 2190 CondARM32::Cond CondTrue0, CondTrue1, CondFalse; | 2299 SafeBoolChain Safe = lowerInt1(T, Src0); |
| 2191 if (_mov_i1_to_flags(Src0, &CondTrue0, &CondTrue1, &CondFalse)) { | 2300 if (Safe == SBC_No) { |
| 2192 // Handle folding opportunities. | 2301 Operand *_1 = legalize(Ctx->getConstantInt1(1), Legal_Reg | Legal_Flex); |
| 2193 Constant *_0 = Ctx->getConstantZero(IceType_i32); | 2302 _and(T, T, _1); |
| 2194 _cmov(T, _1, CondTrue0, CondTrue1, _0, CondFalse); | |
| 2195 _mov(Dest, T); | |
| 2196 return; | |
| 2197 } | 2303 } |
| 2198 | 2304 |
| 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); | 2305 _mov(Dest, T); |
| 2207 } else { | 2306 } else { |
| 2208 // t1 = uxt src; dst = t1 | 2307 // t1 = uxt src; dst = t1 |
| 2209 Variable *Src0R = legalizeToReg(Src0); | 2308 Variable *Src0R = legalizeToReg(Src0); |
| 2210 Variable *T = makeReg(Dest->getType()); | 2309 Variable *T = makeReg(Dest->getType()); |
| 2211 _uxt(T, Src0R); | 2310 _uxt(T, Src0R); |
| 2212 _mov(Dest, T); | 2311 _mov(Dest, T); |
| 2213 } | 2312 } |
| 2214 break; | 2313 break; |
| 2215 } | 2314 } |
| (...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2466 CondARM32::Cond CC1; | 2565 CondARM32::Cond CC1; |
| 2467 } TableFcmp[] = { | 2566 } TableFcmp[] = { |
| 2468 #define X(val, CC0, CC1) \ | 2567 #define X(val, CC0, CC1) \ |
| 2469 { CondARM32::CC0, CondARM32::CC1 } \ | 2568 { CondARM32::CC0, CondARM32::CC1 } \ |
| 2470 , | 2569 , |
| 2471 FCMPARM32_TABLE | 2570 FCMPARM32_TABLE |
| 2472 #undef X | 2571 #undef X |
| 2473 }; | 2572 }; |
| 2474 } // end of anonymous namespace | 2573 } // end of anonymous namespace |
| 2475 | 2574 |
| 2476 void TargetARM32::lowerFcmpCond(const InstFcmp *Instr, | 2575 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(); | 2576 InstFcmp::FCond Condition = Instr->getCondition(); |
| 2481 switch (Condition) { | 2577 switch (Condition) { |
| 2482 case InstFcmp::False: | 2578 case InstFcmp::False: |
| 2483 *CondIfFalse = CondARM32::AL; | 2579 return CondWhenTrue(CondARM32::kNone); |
| 2484 *CondIfTrue0 = *CondIfTrue1 = CondARM32::kNone; | |
| 2485 break; | |
| 2486 case InstFcmp::True: | 2580 case InstFcmp::True: |
| 2487 *CondIfFalse = *CondIfTrue1 = CondARM32::kNone; | 2581 return CondWhenTrue(CondARM32::AL); |
| 2488 *CondIfTrue0 = CondARM32::AL; | |
| 2489 break; | 2582 break; |
| 2490 default: { | 2583 default: { |
| 2491 Variable *Src0R = legalizeToReg(Instr->getSrc(0)); | 2584 Variable *Src0R = legalizeToReg(Instr->getSrc(0)); |
| 2492 Variable *Src1R = legalizeToReg(Instr->getSrc(1)); | 2585 Variable *Src1R = legalizeToReg(Instr->getSrc(1)); |
| 2493 _vcmp(Src0R, Src1R); | 2586 _vcmp(Src0R, Src1R); |
| 2494 _vmrs(); | 2587 _vmrs(); |
| 2495 assert(Condition < llvm::array_lengthof(TableFcmp)); | 2588 assert(Condition < llvm::array_lengthof(TableFcmp)); |
| 2496 *CondIfTrue0 = TableFcmp[Condition].CC0; | 2589 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 } | 2590 } |
| 2502 } | 2591 } |
| 2503 } | 2592 } |
| 2504 | 2593 |
| 2505 void TargetARM32::lowerFcmp(const InstFcmp *Instr) { | 2594 void TargetARM32::lowerFcmp(const InstFcmp *Instr) { |
| 2506 Variable *Dest = Instr->getDest(); | 2595 Variable *Dest = Instr->getDest(); |
| 2507 if (isVectorType(Dest->getType())) { | 2596 if (isVectorType(Dest->getType())) { |
| 2508 Variable *T = makeReg(Dest->getType()); | 2597 Variable *T = makeReg(Dest->getType()); |
| 2509 Context.insert(InstFakeDef::create(Func, T)); | 2598 Context.insert(InstFakeDef::create(Func, T)); |
| 2510 _mov(Dest, T); | 2599 _mov(Dest, T); |
| 2511 UnimplementedError(Func->getContext()->getFlags()); | 2600 UnimplementedError(Func->getContext()->getFlags()); |
| 2512 return; | 2601 return; |
| 2513 } | 2602 } |
| 2514 | 2603 |
| 2515 Variable *T = makeReg(IceType_i1); | 2604 Variable *T = makeReg(IceType_i1); |
| 2516 Operand *_1 = Ctx->getConstantInt32(1); | 2605 Operand *_1 = legalize(Ctx->getConstantInt32(1), Legal_Reg | Legal_Flex); |
| 2517 Operand *_0 = Ctx->getConstantZero(IceType_i32); | 2606 Operand *_0 = |
| 2607 legalize(Ctx->getConstantZero(IceType_i32), Legal_Reg | Legal_Flex); |
| 2518 | 2608 |
| 2519 CondARM32::Cond CondIfTrue0, CondIfTrue1, CondIfFalse; | 2609 CondWhenTrue Cond = lowerFcmpCond(Instr); |
| 2520 lowerFcmpCond(Instr, &CondIfTrue0, &CondIfTrue1, &CondIfFalse); | |
| 2521 | 2610 |
| 2522 bool RedefineT = false; | 2611 bool RedefineT = false; |
| 2523 if (CondIfFalse != CondARM32::kNone) { | 2612 if (Cond.WhenTrue0 != CondARM32::AL) { |
| 2524 assert(!RedefineT); | 2613 _mov(T, _0); |
| 2525 _mov(T, _0, CondIfFalse); | |
| 2526 RedefineT = true; | 2614 RedefineT = true; |
| 2527 } | 2615 } |
| 2528 | 2616 |
| 2529 if (CondIfTrue0 != CondARM32::kNone) { | 2617 if (Cond.WhenTrue0 == CondARM32::kNone) { |
| 2530 if (RedefineT) { | 2618 _mov(Dest, T); |
| 2531 _mov_redefined(T, _1, CondIfTrue0); | 2619 return; |
| 2532 } else { | |
| 2533 _mov(T, _1, CondIfTrue0); | |
| 2534 } | |
| 2535 RedefineT = true; | |
| 2536 } | 2620 } |
| 2537 | 2621 |
| 2538 if (CondIfTrue1 != CondARM32::kNone) { | 2622 if (RedefineT) { |
| 2539 assert(RedefineT); | 2623 _mov_redefined(T, _1, Cond.WhenTrue0); |
| 2540 _mov_redefined(T, _1, CondIfTrue1); | 2624 } else { |
| 2625 _mov(T, _1, Cond.WhenTrue0); |
| 2626 } |
| 2627 |
| 2628 if (Cond.WhenTrue1 != CondARM32::kNone) { |
| 2629 _mov_redefined(T, _1, Cond.WhenTrue1); |
| 2541 } | 2630 } |
| 2542 | 2631 |
| 2543 _mov(Dest, T); | 2632 _mov(Dest, T); |
| 2544 } | 2633 } |
| 2545 | 2634 |
| 2546 void TargetARM32::lowerIcmpCond(const InstIcmp *Inst, | 2635 TargetARM32::CondWhenTrue TargetARM32::lowerIcmpCond(const InstIcmp *Inst) { |
| 2547 CondARM32::Cond *CondIfTrue, | 2636 assert(Inst->getSrc(0)->getType() != IceType_i1); |
| 2548 CondARM32::Cond *CondIfFalse) { | 2637 assert(Inst->getSrc(1)->getType() != IceType_i1); |
| 2638 |
| 2549 Operand *Src0 = legalizeUndef(Inst->getSrc(0)); | 2639 Operand *Src0 = legalizeUndef(Inst->getSrc(0)); |
| 2550 Operand *Src1 = legalizeUndef(Inst->getSrc(1)); | 2640 Operand *Src1 = legalizeUndef(Inst->getSrc(1)); |
| 2551 | 2641 |
| 2552 // a=icmp cond, b, c ==> | 2642 // a=icmp cond, b, c ==> |
| 2553 // GCC does: | 2643 // GCC does: |
| 2554 // cmp b.hi, c.hi or cmp b.lo, c.lo | 2644 // cmp b.hi, c.hi or cmp b.lo, c.lo |
| 2555 // cmp.eq b.lo, c.lo sbcs t1, b.hi, c.hi | 2645 // cmp.eq b.lo, c.lo sbcs t1, b.hi, c.hi |
| 2556 // mov.<C1> t, #1 mov.<C1> t, #1 | 2646 // mov.<C1> t, #1 mov.<C1> t, #1 |
| 2557 // mov.<C2> t, #0 mov.<C2> t, #0 | 2647 // mov.<C2> t, #0 mov.<C2> t, #0 |
| 2558 // mov a, t mov a, t | 2648 // 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); | 2690 Variable *ScratchReg = makeReg(IceType_i32); |
| 2601 _cmp(Src0Lo, Src1LoRF); | 2691 _cmp(Src0Lo, Src1LoRF); |
| 2602 _sbcs(ScratchReg, Src0Hi, Src1HiRF); | 2692 _sbcs(ScratchReg, Src0Hi, Src1HiRF); |
| 2603 // ScratchReg isn't going to be used, but we need the side-effect of | 2693 // ScratchReg isn't going to be used, but we need the side-effect of |
| 2604 // setting flags from this operation. | 2694 // setting flags from this operation. |
| 2605 Context.insert(InstFakeUse::create(Func, ScratchReg)); | 2695 Context.insert(InstFakeUse::create(Func, ScratchReg)); |
| 2606 } else { | 2696 } else { |
| 2607 _cmp(Src0Hi, Src1HiRF); | 2697 _cmp(Src0Hi, Src1HiRF); |
| 2608 _cmp(Src0Lo, Src1LoRF, CondARM32::EQ); | 2698 _cmp(Src0Lo, Src1LoRF, CondARM32::EQ); |
| 2609 } | 2699 } |
| 2610 *CondIfTrue = TableIcmp64[Index].C1; | 2700 return CondWhenTrue(TableIcmp64[Index].C1); |
| 2611 *CondIfFalse = TableIcmp64[Index].C2; | |
| 2612 return; | |
| 2613 } | 2701 } |
| 2614 | 2702 |
| 2615 // a=icmp cond b, c ==> | 2703 // a=icmp cond b, c ==> |
| 2616 // GCC does: | 2704 // GCC does: |
| 2617 // <u/s>xtb tb, b | 2705 // <u/s>xtb tb, b |
| 2618 // <u/s>xtb tc, c | 2706 // <u/s>xtb tc, c |
| 2619 // cmp tb, tc | 2707 // cmp tb, tc |
| 2620 // mov.C1 t, #0 | 2708 // mov.C1 t, #0 |
| 2621 // mov.C2 t, #1 | 2709 // mov.C2 t, #1 |
| 2622 // mov a, t | 2710 // mov a, t |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2654 } | 2742 } |
| 2655 if (ShiftAmt) { | 2743 if (ShiftAmt) { |
| 2656 Variable *Src1R = legalizeToReg(Src1); | 2744 Variable *Src1R = legalizeToReg(Src1); |
| 2657 OperandARM32FlexReg *Src1RShifted = OperandARM32FlexReg::create( | 2745 OperandARM32FlexReg *Src1RShifted = OperandARM32FlexReg::create( |
| 2658 Func, IceType_i32, Src1R, OperandARM32::LSL, ShiftConst); | 2746 Func, IceType_i32, Src1R, OperandARM32::LSL, ShiftConst); |
| 2659 _cmp(Src0R, Src1RShifted); | 2747 _cmp(Src0R, Src1RShifted); |
| 2660 } else { | 2748 } else { |
| 2661 Operand *Src1RF = legalize(Src1, Legal_Reg | Legal_Flex); | 2749 Operand *Src1RF = legalize(Src1, Legal_Reg | Legal_Flex); |
| 2662 _cmp(Src0R, Src1RF); | 2750 _cmp(Src0R, Src1RF); |
| 2663 } | 2751 } |
| 2664 *CondIfTrue = getIcmp32Mapping(Inst->getCondition()); | 2752 return CondWhenTrue(getIcmp32Mapping(Inst->getCondition())); |
| 2665 *CondIfFalse = InstARM32::getOppositeCondition(*CondIfTrue); | |
| 2666 } | 2753 } |
| 2667 | 2754 |
| 2668 void TargetARM32::lowerIcmp(const InstIcmp *Inst) { | 2755 void TargetARM32::lowerIcmp(const InstIcmp *Inst) { |
| 2669 Variable *Dest = Inst->getDest(); | 2756 Variable *Dest = Inst->getDest(); |
| 2670 | 2757 |
| 2671 if (isVectorType(Dest->getType())) { | 2758 if (isVectorType(Dest->getType())) { |
| 2672 Variable *T = makeReg(Dest->getType()); | 2759 Variable *T = makeReg(Dest->getType()); |
| 2673 Context.insert(InstFakeDef::create(Func, T)); | 2760 Context.insert(InstFakeDef::create(Func, T)); |
| 2674 _mov(Dest, T); | 2761 _mov(Dest, T); |
| 2675 UnimplementedError(Func->getContext()->getFlags()); | 2762 UnimplementedError(Func->getContext()->getFlags()); |
| 2676 return; | 2763 return; |
| 2677 } | 2764 } |
| 2678 | 2765 |
| 2679 Constant *_0 = Ctx->getConstantZero(IceType_i32); | 2766 Operand *_0 = |
| 2680 Constant *_1 = Ctx->getConstantInt32(1); | 2767 legalize(Ctx->getConstantZero(IceType_i32), Legal_Reg | Legal_Flex); |
| 2768 Operand *_1 = legalize(Ctx->getConstantInt32(1), Legal_Reg | Legal_Flex); |
| 2681 Variable *T = makeReg(IceType_i1); | 2769 Variable *T = makeReg(IceType_i1); |
| 2682 | 2770 |
| 2683 CondARM32::Cond CondIfTrue, CondIfFalse; | 2771 _mov(T, _0); |
| 2684 lowerIcmpCond(Inst, &CondIfTrue, &CondIfFalse); | 2772 CondWhenTrue Cond = lowerIcmpCond(Inst); |
| 2773 _mov_redefined(T, _1, Cond.WhenTrue0); |
| 2774 _mov(Dest, T); |
| 2685 | 2775 |
| 2686 _mov(T, _0, CondIfFalse); | 2776 assert(Cond.WhenTrue1 == CondARM32::kNone); |
| 2687 _mov_redefined(T, _1, CondIfTrue); | |
| 2688 _mov(Dest, T); | |
| 2689 | 2777 |
| 2690 return; | 2778 return; |
| 2691 } | 2779 } |
| 2692 | 2780 |
| 2693 void TargetARM32::lowerInsertElement(const InstInsertElement *Inst) { | 2781 void TargetARM32::lowerInsertElement(const InstInsertElement *Inst) { |
| 2694 (void)Inst; | 2782 (void)Inst; |
| 2695 UnimplementedError(Func->getContext()->getFlags()); | 2783 UnimplementedError(Func->getContext()->getFlags()); |
| 2696 } | 2784 } |
| 2697 | 2785 |
| 2698 namespace { | 2786 namespace { |
| (...skipping 1197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3896 Operand *Condition = Inst->getCondition(); | 3984 Operand *Condition = Inst->getCondition(); |
| 3897 | 3985 |
| 3898 if (isVectorType(DestTy)) { | 3986 if (isVectorType(DestTy)) { |
| 3899 Variable *T = makeReg(DestTy); | 3987 Variable *T = makeReg(DestTy); |
| 3900 Context.insert(InstFakeDef::create(Func, T)); | 3988 Context.insert(InstFakeDef::create(Func, T)); |
| 3901 _mov(Dest, T); | 3989 _mov(Dest, T); |
| 3902 UnimplementedError(Func->getContext()->getFlags()); | 3990 UnimplementedError(Func->getContext()->getFlags()); |
| 3903 return; | 3991 return; |
| 3904 } | 3992 } |
| 3905 | 3993 |
| 3906 CondARM32::Cond CondIfTrue0, CondIfTrue1, CondIfFalse; | 3994 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 } | 3995 } |
| 4020 | 3996 |
| 4021 void TargetARM32::lowerStore(const InstStore *Inst) { | 3997 void TargetARM32::lowerStore(const InstStore *Inst) { |
| 4022 Operand *Value = Inst->getData(); | 3998 Operand *Value = Inst->getData(); |
| 4023 Operand *Addr = Inst->getAddr(); | 3999 Operand *Addr = Inst->getAddr(); |
| 4024 OperandARM32Mem *NewAddr = formMemoryOperand(Addr, Value->getType()); | 4000 OperandARM32Mem *NewAddr = formMemoryOperand(Addr, Value->getType()); |
| 4025 Type Ty = NewAddr->getType(); | 4001 Type Ty = NewAddr->getType(); |
| 4026 | 4002 |
| 4027 if (Ty == IceType_i64) { | 4003 if (Ty == IceType_i64) { |
| 4028 Value = legalizeUndef(Value); | 4004 Value = legalizeUndef(Value); |
| (...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4423 | 4399 |
| 4424 void TargetARM32::emit(const ConstantDouble *C) const { | 4400 void TargetARM32::emit(const ConstantDouble *C) const { |
| 4425 (void)C; | 4401 (void)C; |
| 4426 UnimplementedError(Ctx->getFlags()); | 4402 UnimplementedError(Ctx->getFlags()); |
| 4427 } | 4403 } |
| 4428 | 4404 |
| 4429 void TargetARM32::emit(const ConstantUndef *) const { | 4405 void TargetARM32::emit(const ConstantUndef *) const { |
| 4430 llvm::report_fatal_error("undef value encountered by emitter."); | 4406 llvm::report_fatal_error("undef value encountered by emitter."); |
| 4431 } | 4407 } |
| 4432 | 4408 |
| 4433 void TargetARM32::lowerTruncToFlags(Operand *Src, CondARM32::Cond *CondIfTrue, | 4409 void TargetARM32::lowerInt1ForSelect(Variable *Dest, Operand *Boolean, |
| 4434 CondARM32::Cond *CondIfFalse) { | 4410 Operand *TrueValue, Operand *FalseValue) { |
| 4435 Operand *_1 = Ctx->getConstantInt32(1); | 4411 Operand *_1 = legalize(Ctx->getConstantInt1(1), Legal_Reg | Legal_Flex); |
| 4436 Variable *SrcR = | 4412 |
| 4437 legalizeToReg(Src->getType() == IceType_i64 ? loOperand(Src) : Src); | 4413 assert(Boolean->getType() == IceType_i1); |
| 4438 _tst(SrcR, _1); | 4414 |
| 4439 *CondIfTrue = CondARM32::NE; // NE <-> APSR.Z == 0 | 4415 bool NeedsAnd1 = false; |
| 4440 *CondIfFalse = CondARM32::EQ; // EQ <-> APSR.Z == 1 | 4416 if (TrueValue->getType() == IceType_i1) { |
| 4441 } | 4417 assert(FalseValue->getType() == IceType_i1); |
| 4442 | 4418 |
| 4443 bool TargetARM32::_mov_i1_to_flags(Operand *Boolean, | 4419 Variable *TrueValueV = Func->makeVariable(IceType_i1); |
| 4444 CondARM32::Cond *CondIfTrue0, | 4420 SafeBoolChain Src0Safe = lowerInt1(TrueValueV, TrueValue); |
| 4445 CondARM32::Cond *CondIfTrue1, | 4421 TrueValue = TrueValueV; |
| 4446 CondARM32::Cond *CondIfFalse) { | 4422 |
| 4447 *CondIfTrue0 = CondARM32::kNone; | 4423 Variable *FalseValueV = Func->makeVariable(IceType_i1); |
| 4448 *CondIfTrue1 = CondARM32::kNone; | 4424 SafeBoolChain Src1Safe = lowerInt1(FalseValueV, FalseValue); |
| 4449 *CondIfFalse = CondARM32::AL; | 4425 FalseValue = FalseValueV; |
| 4450 bool FoldOK = false; | 4426 |
| 4427 NeedsAnd1 = Src0Safe == SBC_No || Src1Safe == SBC_No; |
| 4428 } |
| 4429 |
| 4430 Variable *DestLo = (Dest->getType() == IceType_i64) |
| 4431 ? llvm::cast<Variable>(loOperand(Dest)) |
| 4432 : Dest; |
| 4433 Variable *DestHi = (Dest->getType() == IceType_i64) |
| 4434 ? llvm::cast<Variable>(hiOperand(Dest)) |
| 4435 : nullptr; |
| 4436 Operand *FalseValueLo = (FalseValue->getType() == IceType_i64) |
| 4437 ? loOperand(FalseValue) |
| 4438 : FalseValue; |
| 4439 Operand *FalseValueHi = |
| 4440 (FalseValue->getType() == IceType_i64) ? hiOperand(FalseValue) : nullptr; |
| 4441 |
| 4442 Operand *TrueValueLo = |
| 4443 (TrueValue->getType() == IceType_i64) ? loOperand(TrueValue) : TrueValue; |
| 4444 Operand *TrueValueHi = |
| 4445 (TrueValue->getType() == IceType_i64) ? hiOperand(TrueValue) : nullptr; |
| 4446 |
| 4447 Variable *T_Lo = makeReg(DestLo->getType()); |
| 4448 Variable *T_Hi = (DestHi == nullptr) ? nullptr : makeReg(DestHi->getType()); |
| 4449 |
| 4450 _mov(T_Lo, legalize(FalseValueLo, Legal_Reg | Legal_Flex)); |
| 4451 if (DestHi) { |
| 4452 _mov(T_Hi, legalize(FalseValueHi, Legal_Reg | Legal_Flex)); |
| 4453 } |
| 4454 |
| 4455 CondWhenTrue Cond(CondARM32::kNone); |
| 4456 // FlagsWereSet is used to determine wether Boolean was folded or not. If not, |
| 4457 // add an explicit _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 folded, |
| 4482 // but in reality, it can't. No reason to panic: we just lower it using |
| 4483 // the 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. |
| 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 |