Index: lib/Target/ARM/ARMAsmPrinter.h =================================================================== --- lib/Target/ARM/ARMAsmPrinter.h +++ lib/Target/ARM/ARMAsmPrinter.h @@ -92,9 +92,7 @@ void EmitInstruction(const MachineInstr *MI) override; bool runOnMachineFunction(MachineFunction &F) override; - void EmitConstantPool() override { - // we emit constant pools customly! - } + void EmitConstantPool() override; void EmitFunctionBodyEnd() override; void EmitFunctionEntryLabel() override; void EmitStartOfAsmFile(Module &M) override; Index: lib/Target/ARM/ARMAsmPrinter.cpp =================================================================== --- lib/Target/ARM/ARMAsmPrinter.cpp +++ lib/Target/ARM/ARMAsmPrinter.cpp @@ -61,6 +61,14 @@ : AsmPrinter(TM, std::move(Streamer)), AFI(nullptr), MCP(nullptr), InConstantPool(false), OptimizationGoals(-1) {} +// When generating execute-only code invoke the generic AsmPrinter +// in order to place the literals in the data section, otherwise +// handle Constant Pools in EmitInstruction. +void ARMAsmPrinter::EmitConstantPool() { + if (Subtarget->genExecuteOnly()) + AsmPrinter::EmitConstantPool(); +} + void ARMAsmPrinter::EmitFunctionBodyEnd() { // Make sure to terminate any constant pools that were at the end // of the function. @@ -1236,6 +1244,31 @@ case ARM::t2LEApcrel: { // FIXME: Need to also handle globals and externals MCSymbol *CPISymbol = GetCPISymbol(MI->getOperand(1).getIndex()); + + // When generating execute-only code use MOVW/MOVT to materialize the + // address of a Constant Pool. + if (Subtarget->genExecuteOnly()) { + const MCExpr *SymExpr = MCSymbolRefExpr::create(CPISymbol, OutContext); + EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::t2MOVi16) + .addReg(MI->getOperand(0).getReg()) + .addExpr(ARMMCExpr::createLower16(SymExpr, OutContext)) + // Add predicate operands. + .addImm(MI->getOperand(2).getImm()) + .addReg(MI->getOperand(3).getReg()) + // Add 's' bit operand (always reg0 for this) + .addReg(MI->getOperand(0).getReg())); + EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::t2MOVTi16) + .addReg(MI->getOperand(0).getReg()) + .addReg(MI->getOperand(0).getReg()) + .addExpr(ARMMCExpr::createUpper16(SymExpr, OutContext)) + // Add predicate operands. + .addImm(MI->getOperand(2).getImm()) + .addReg(MI->getOperand(3).getReg()) + // Add 's' bit operand (always reg0 for this) + .addReg(MI->getOperand(0).getReg())); + return; + } + EmitToStreamer(*OutStreamer, MCInstBuilder(MI->getOpcode() == ARM::t2LEApcrel ? ARM::t2ADR : (MI->getOpcode() == ARM::tLEApcrel ? ARM::tADR @@ -1504,6 +1537,10 @@ return; } case ARM::CONSTPOOL_ENTRY: { + // Handle this case in EmitConstantPool. + if (Subtarget->genExecuteOnly()) + return; + /// CONSTPOOL_ENTRY - This instruction represents a floating constant pool /// in the function. The first operand is the ID# for this instruction, the /// second is the index into the MachineConstantPool that this is, the third Index: lib/Target/ARM/ARMISelLowering.cpp =================================================================== --- lib/Target/ARM/ARMISelLowering.cpp +++ lib/Target/ARM/ARMISelLowering.cpp @@ -7634,10 +7634,7 @@ 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()) { Index: test/CodeGen/ARM/constantfp.ll =================================================================== --- test/CodeGen/ARM/constantfp.ll +++ test/CodeGen/ARM/constantfp.ll @@ -176,3 +176,37 @@ ; CHECK-XO-DOUBLE-BE-NOT: vldr ret double 3.140000e-01 } + +; This is a target independent optimization, performed by the +; DAG Combiner, which promotes floating point literals into +; constant pools: +; +; (a cond b) ? 1.0f : 2.0f -> load (ConstPoolAddr + ((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]+]], [[LABEL:.?LCPI[0-9]+_[0-9]+]] +; CHECK-NO-XO: vldr {{s[0-9]+}}, {{[[]}}[[REG]]{{[]]}} +; CHECK-NO-XO-NOT: .rodata +; CHECK-NO-XO: [[LABEL]]: +; CHECK-NO-XO: .long 1335165689 +; CHECK-NO-XO: .long 1307470632 + +; CHECK-XO-FLOAT: .rodata +; CHECK-XO-FLOAT: [[LABEL:.?LCPI[0-9]+_[0-9]+]]: +; CHECK-XO-FLOAT: .long 1335165689 +; CHECK-XO-FLOAT: .long 1307470632 +; CHECK-XO-FLOAT: .section .text,"axy",%progbits,unique,0 +; CHECK-XO-FLOAT: lower_fpconst_select: +; CHECK-XO-FLOAT: movw [[REG:r[0-9]+]], :lower16:[[LABEL]] +; CHECK-XO-FLOAT: movt [[REG]], :upper16:[[LABEL]] +; CHECK-XO-FLOAT: vldr {{s[0-9]+}}, {{[[]}}[[REG]]{{[]]}} + + %cmp = fcmp nnan oeq float %f, 0.000000e+00 + %sel = select i1 %cmp, float 5.000000e+08, float 5.000000e+09 + ret float %sel +}