Index: lib/Target/ARM/ARMISelLowering.h =================================================================== --- lib/Target/ARM/ARMISelLowering.h +++ lib/Target/ARM/ARMISelLowering.h @@ -601,6 +601,8 @@ SDValue LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget) const; SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; SDValue LowerGlobalAddressDarwin(SDValue Op, SelectionDAG &DAG) const; SDValue LowerGlobalAddressELF(SDValue Op, SelectionDAG &DAG) const; SDValue LowerGlobalAddressWindows(SDValue Op, SelectionDAG &DAG) const; Index: lib/Target/ARM/ARMISelLowering.cpp =================================================================== --- lib/Target/ARM/ARMISelLowering.cpp +++ lib/Target/ARM/ARMISelLowering.cpp @@ -2670,12 +2670,32 @@ // Select(N) returns N. So the raw TargetGlobalAddress nodes, etc. can only // be used to form addressing mode. These wrapped nodes will be selected // into MOVi. -static SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) { +SDValue ARMTargetLowering::LowerConstantPool(SDValue Op, + SelectionDAG &DAG) const { EVT PtrVT = Op.getValueType(); // FIXME there is no actual debug info here SDLoc dl(Op); ConstantPoolSDNode *CP = cast(Op); SDValue Res; + + // When generating execute-only code, Constant Pools + // must be promoted to the global data section. + if (Subtarget->genExecuteOnly()) { + ARMFunctionInfo *AFI = DAG.getMachineFunction().getInfo(); + unsigned LID = AFI->createPICLabelUId(); + + auto T = const_cast(CP->getType()); + auto C = const_cast(CP->getConstVal()); + auto M = const_cast(DAG.getMachineFunction(). + getFunction()->getParent()); + auto GV = new GlobalVariable(*M, T, /*isConstant=*/true, + GlobalVariable::InternalLinkage, C, + std::string(".LCPI.XO.")+std::to_string(LID)); + SDValue GA = DAG.getTargetGlobalAddress(dyn_cast(GV), + dl, PtrVT); + return LowerGlobalAddress(GA, DAG); + } + if (CP->isMachineConstantPoolEntry()) Res = DAG.getTargetConstantPool(CP->getMachineCPVal(), PtrVT, CP->getAlignment()); @@ -3119,6 +3139,19 @@ isa(GV); } +SDValue ARMTargetLowering::LowerGlobalAddress(SDValue Op, + SelectionDAG &DAG) const { + switch (Subtarget->getTargetTriple().getObjectFormat()) { + default: llvm_unreachable("unknown object format"); + case Triple::COFF: + return LowerGlobalAddressWindows(Op, DAG); + case Triple::ELF: + return LowerGlobalAddressELF(Op, DAG); + case Triple::MachO: + return LowerGlobalAddressDarwin(Op, DAG); + } +} + SDValue ARMTargetLowering::LowerGlobalAddressELF(SDValue Op, SelectionDAG &DAG) const { EVT PtrVT = getPointerTy(DAG.getDataLayout()); @@ -7635,21 +7668,9 @@ switch (Op.getOpcode()) { default: llvm_unreachable("Don't know how to custom lower this!"); case ISD::WRITE_REGISTER: return LowerWRITE_REGISTER(Op, DAG); - case ISD::ConstantPool: - if (Subtarget->genExecuteOnly()) - llvm_unreachable("execute-only should not generate constant pools"); - return LowerConstantPool(Op, DAG); + case ISD::ConstantPool: return LowerConstantPool(Op, DAG); case ISD::BlockAddress: return LowerBlockAddress(Op, DAG); - case ISD::GlobalAddress: - switch (Subtarget->getTargetTriple().getObjectFormat()) { - default: llvm_unreachable("unknown object format"); - case Triple::COFF: - return LowerGlobalAddressWindows(Op, DAG); - case Triple::ELF: - return LowerGlobalAddressELF(Op, DAG); - case Triple::MachO: - return LowerGlobalAddressDarwin(Op, DAG); - } + case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG); case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG); case ISD::SELECT: return LowerSELECT(Op, DAG); case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG); Index: test/CodeGen/ARM/constantfp.ll =================================================================== --- test/CodeGen/ARM/constantfp.ll +++ test/CodeGen/ARM/constantfp.ll @@ -176,3 +176,34 @@ ; CHECK-XO-DOUBLE-BE-NOT: vldr ret double 3.140000e-01 } + +; This is a target independant optimization, performed by the +; DAG Combiner, which promotes floating point literals into +; constant pools: +; +; (a cond b) ? 1.0f : 2.0f -> load (tmp + ((a cond b) ? 0 : 4) +; +; We need to make sure that the constant pools are placed in +; the data section when generating execute-only code: + +define arm_aapcs_vfpcc float @lower_fpconst_select(float %f) { + +; CHECK-NO-XO-LABEL: lower_fpconst_select +; CHECK-NO-XO: adr [[REG:r[0-9]+]], {{.?LCPI[0-9]+_[0-9]+}} +; CHECK-NO-XO: vldr {{s[0-9]+}}, {{[[]}}[[REG]]{{[]]}} + +; CHECK-XO-FLOAT-LABEL: lower_fpconst_select +; CHECK-XO-FLOAT: movw [[REG:r[0-9]+]], :lower16:[[LABEL:.LCPI.XO.[0-9]+]] +; CHECK-XO-FLOAT: movt [[REG]], :upper16:[[LABEL]] +; CHECK-XO-FLOAT: vldr {{s[0-9]+}}, {{[[]}}[[REG]]{{[]]}} +; CHECK-XO-FLOAT: .section .rodata +; CHECK-XO-FLOAT-NEXT: .p2align 2 +; CHECK-XO-FLOAT-NEXT: [[LABEL]]: +; CHECK-XO-FLOAT-NEXT: .long 1335165689 +; CHECK-XO-FLOAT-NEXT: .long 1307470632 +; CHECK-XO-FLOAT-NEXT: .size [[LABEL]], 8 + + %cmp = fcmp nnan oeq float %f, 0.000000e+00 + %sel = select i1 %cmp, float 5.000000e+08, float 5.000000e+09 + ret float %sel +}