Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -53,6 +53,8 @@ using namespace llvm; +extern cl::opt EnablePPCFp128ConstantFold; + /// makeVTList - Return an instance of the SDVTList struct initialized with the /// specified members. static SDVTList makeVTList(const EVT *VTs, unsigned NumVTs) { @@ -3765,40 +3767,46 @@ if (N2CFP) { APFloat V1 = N1CFP->getValueAPF(), V2 = N2CFP->getValueAPF(); APFloat::opStatus s; - switch (Opcode) { - case ISD::FADD: - s = V1.add(V2, APFloat::rmNearestTiesToEven); - if (!HasFPExceptions || s != APFloat::opInvalidOp) - return getConstantFP(V1, DL, VT); - break; - case ISD::FSUB: - s = V1.subtract(V2, APFloat::rmNearestTiesToEven); - if (!HasFPExceptions || s!=APFloat::opInvalidOp) - return getConstantFP(V1, DL, VT); - break; - case ISD::FMUL: - s = V1.multiply(V2, APFloat::rmNearestTiesToEven); - if (!HasFPExceptions || s!=APFloat::opInvalidOp) - return getConstantFP(V1, DL, VT); - break; - case ISD::FDIV: - s = V1.divide(V2, APFloat::rmNearestTiesToEven); - if (!HasFPExceptions || (s!=APFloat::opInvalidOp && - s!=APFloat::opDivByZero)) { - return getConstantFP(V1, DL, VT); - } - break; - case ISD::FREM : - s = V1.mod(V2); - if (!HasFPExceptions || (s!=APFloat::opInvalidOp && - s!=APFloat::opDivByZero)) { + + if ((&V1.getSemantics() != &APFloat::PPCDoubleDouble && + &V2.getSemantics() != &APFloat::PPCDoubleDouble) || + EnablePPCFp128ConstantFold) { + switch (Opcode) { + case ISD::FADD: + s = V1.add(V2, APFloat::rmNearestTiesToEven); + if (!HasFPExceptions || s != APFloat::opInvalidOp) + return getConstantFP(V1, DL, VT); + break; + case ISD::FSUB: + s = V1.subtract(V2, APFloat::rmNearestTiesToEven); + if (!HasFPExceptions || s != APFloat::opInvalidOp) + return getConstantFP(V1, DL, VT); + break; + case ISD::FMUL: + s = V1.multiply(V2, APFloat::rmNearestTiesToEven); + if (!HasFPExceptions || s != APFloat::opInvalidOp) + return getConstantFP(V1, DL, VT); + break; + case ISD::FDIV: + s = V1.divide(V2, APFloat::rmNearestTiesToEven); + if (!HasFPExceptions || + (s != APFloat::opInvalidOp && s != APFloat::opDivByZero)) { + return getConstantFP(V1, DL, VT); + } + break; + case ISD::FREM: + s = V1.mod(V2); + if (!HasFPExceptions || + (s != APFloat::opInvalidOp && s != APFloat::opDivByZero)) { + return getConstantFP(V1, DL, VT); + } + break; + case ISD::FCOPYSIGN: + V1.copySign(V2); return getConstantFP(V1, DL, VT); + default: + break; } - break; - case ISD::FCOPYSIGN: - V1.copySign(V2); - return getConstantFP(V1, DL, VT); - default: break; } } Index: llvm/lib/IR/ConstantFold.cpp =================================================================== --- llvm/lib/IR/ConstantFold.cpp +++ llvm/lib/IR/ConstantFold.cpp @@ -34,6 +34,10 @@ using namespace llvm; using namespace llvm::PatternMatch; +cl::opt EnablePPCFp128ConstantFold( + "enable-ppcfp128-constant-fold", + cl::desc("Enable inaccurate ppcfp128 constant folding"), cl::init(true)); + //===----------------------------------------------------------------------===// // ConstantFold*Instruction Implementations //===----------------------------------------------------------------------===// @@ -1184,24 +1188,29 @@ const APFloat &C1V = CFP1->getValueAPF(); const APFloat &C2V = CFP2->getValueAPF(); APFloat C3V = C1V; // copy for modification - switch (Opcode) { - default: - break; - case Instruction::FAdd: - (void)C3V.add(C2V, APFloat::rmNearestTiesToEven); - return ConstantFP::get(C1->getContext(), C3V); - case Instruction::FSub: - (void)C3V.subtract(C2V, APFloat::rmNearestTiesToEven); - return ConstantFP::get(C1->getContext(), C3V); - case Instruction::FMul: - (void)C3V.multiply(C2V, APFloat::rmNearestTiesToEven); - return ConstantFP::get(C1->getContext(), C3V); - case Instruction::FDiv: - (void)C3V.divide(C2V, APFloat::rmNearestTiesToEven); - return ConstantFP::get(C1->getContext(), C3V); - case Instruction::FRem: - (void)C3V.mod(C2V); - return ConstantFP::get(C1->getContext(), C3V); + + if ((&C3V.getSemantics() != &APFloat::PPCDoubleDouble && + &C2V.getSemantics() != &APFloat::PPCDoubleDouble) || + EnablePPCFp128ConstantFold) { + switch (Opcode) { + default: + break; + case Instruction::FAdd: + (void)C3V.add(C2V, APFloat::rmNearestTiesToEven); + return ConstantFP::get(C1->getContext(), C3V); + case Instruction::FSub: + (void)C3V.subtract(C2V, APFloat::rmNearestTiesToEven); + return ConstantFP::get(C1->getContext(), C3V); + case Instruction::FMul: + (void)C3V.multiply(C2V, APFloat::rmNearestTiesToEven); + return ConstantFP::get(C1->getContext(), C3V); + case Instruction::FDiv: + (void)C3V.divide(C2V, APFloat::rmNearestTiesToEven); + return ConstantFP::get(C1->getContext(), C3V); + case Instruction::FRem: + (void)C3V.mod(C2V); + return ConstantFP::get(C1->getContext(), C3V); + } } } } else if (VectorType *VTy = dyn_cast(C1->getType())) { Index: llvm/test/CodeGen/PowerPC/ppc128-constant-folding.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/PowerPC/ppc128-constant-folding.ll @@ -0,0 +1,21 @@ +; RUN: llc -O0 -enable-ppcfp128-constant-fold=true < %s | FileCheck %s -check-prefix=ENABLE +; RUN: llc -O0 -enable-ppcfp128-constant-fold=false < %s | FileCheck %s -check-prefix=DISABLE +target triple = "powerpc64le-linux-gnu" + +; The code returns the second double in integer, which is able to be constant-folded. +; int64_t Foo() { +; long double sum = 1.0L + std::numeric_limits::epsilon(); +; return *((int64_t*)(&sum) + 1); +; } + +; ENABLE-NOT: __gcc_qadd +; DISABLE: __gcc_qadd +define i64 @Foo() { + %1 = alloca ppc_fp128, align 16 + %2 = fadd ppc_fp128 0xM3FF00000000000000000000000000000, 0xM00000000000000010000000000000000 + store ppc_fp128 %2, ppc_fp128* %1, align 16 + %3 = bitcast ppc_fp128* %1 to i64* + %4 = getelementptr inbounds i64, i64* %3, i64 1 + %5 = load i64, i64* %4, align 8 + ret i64 %5 +}