From 357f1be2ca5a835045643cb488f18bb152925795 Mon Sep 17 00:00:00 2001 From: Tim Northover Date: Wed, 10 Aug 2016 23:02:41 +0000 Subject: [PATCH] GlobalISel: support same ConstantExprs as Instructions. It's more than just inttoptr, but the others can't be tested until we have support for non-trivial constants (they currently get unavoidably folded to a ConstantInt). llvm-svn: 278303 --- .../include/llvm/CodeGen/GlobalISel/IRTranslator.h | 107 ++++++++++++++++--- llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 116 ++++++++------------- .../AArch64/GlobalISel/arm64-irtranslator.ll | 8 ++ 3 files changed, 143 insertions(+), 88 deletions(-) diff --git a/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h b/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h index 74aa09b..73f43175 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h @@ -109,47 +109,128 @@ private: /// Translate an LLVM bitcast into generic IR. Either a COPY or a G_BITCAST is /// emitted. - bool translateBitCast(const CastInst &CI); + bool translateBitCast(const User &U); /// Translate an LLVM load instruction into generic IR. - bool translateLoad(const LoadInst &LI); + bool translateLoad(const User &U); /// Translate an LLVM store instruction into generic IR. - bool translateStore(const StoreInst &SI); + bool translateStore(const User &U); /// Translate call instruction. - /// \pre \p Inst is a call instruction. - bool translateCall(const CallInst &Inst); + /// \pre \p U is a call instruction. + bool translateCall(const User &U); /// Translate one of LLVM's cast instructions into MachineInstrs, with the /// given generic Opcode. - bool translateCast(unsigned Opcode, const CastInst &CI); + bool translateCast(unsigned Opcode, const User &U); /// Translate static alloca instruction (i.e. one of constant size and in the /// first basic block). bool translateStaticAlloca(const AllocaInst &Inst); /// Translate a phi instruction. - bool translatePhi(const PHINode &PI); + bool translatePHI(const User &U); /// Add remaining operands onto phis we've translated. Executed after all /// MachineBasicBlocks for the function have been created. void finishPendingPhis(); /// Translate \p Inst into a binary operation \p Opcode. - /// \pre \p Inst is a binary operation. - bool translateBinaryOp(unsigned Opcode, const BinaryOperator &Inst); + /// \pre \p U is a binary operation. + bool translateBinaryOp(unsigned Opcode, const User &U); /// Translate branch (br) instruction. - /// \pre \p Inst is a branch instruction. - bool translateBr(const BranchInst &Inst); + /// \pre \p U is a branch instruction. + bool translateBr(const User &U); + bool translateAdd(const User &U) { + return translateBinaryOp(TargetOpcode::G_ADD, U); + } + bool translateSub(const User &U) { + return translateBinaryOp(TargetOpcode::G_SUB, U); + } + bool translateAnd(const User &U) { + return translateBinaryOp(TargetOpcode::G_AND, U); + } + bool translateMul(const User &U) { + return translateBinaryOp(TargetOpcode::G_MUL, U); + } + bool translateOr(const User &U) { + return translateBinaryOp(TargetOpcode::G_OR, U); + } + bool translateXor(const User &U) { + return translateBinaryOp(TargetOpcode::G_XOR, U); + } + bool translateAlloca(const User &U) { + return translateStaticAlloca(cast(U)); + } + bool translateIntToPtr(const User &U) { + return translateCast(TargetOpcode::G_INTTOPTR, U); + } + bool translatePtrToInt(const User &U) { + return translateCast(TargetOpcode::G_PTRTOINT, U); + } + bool translateTrunc(const User &U) { + return translateCast(TargetOpcode::G_TRUNC, U); + } + bool translateUnreachable(const User &U) { return true; } /// Translate return (ret) instruction. /// The target needs to implement CallLowering::lowerReturn for /// this to succeed. - /// \pre \p Inst is a return instruction. - bool translateReturn(const ReturnInst &Inst); + /// \pre \p U is a return instruction. + bool translateRet(const User &U); + + // Stubs to keep the compiler happy while we implement the rest of the + // translation. + bool translateSwitch(const User &U) { return false; } + bool translateIndirectBr(const User &U) { return false; } + bool translateInvoke(const User &U) { return false; } + bool translateResume(const User &U) { return false; } + bool translateCleanupRet(const User &U) { return false; } + bool translateCatchRet(const User &U) { return false; } + bool translateCatchSwitch(const User &U) { return false; } + bool translateFAdd(const User &U) { return false; } + bool translateFSub(const User &U) { return false; } + bool translateFMul(const User &U) { return false; } + bool translateUDiv(const User &U) { return false; } + bool translateSDiv(const User &U) { return false; } + bool translateFDiv(const User &U) { return false; } + bool translateURem(const User &U) { return false; } + bool translateSRem(const User &U) { return false; } + bool translateFRem(const User &U) { return false; } + bool translateShl(const User &U) { return false; } + bool translateLShr(const User &U) { return false; } + bool translateAShr(const User &U) { return false; } + bool translateGetElementPtr(const User &U) { return false; } + bool translateFence(const User &U) { return false; } + bool translateAtomicCmpXchg(const User &U) { return false; } + bool translateAtomicRMW(const User &U) { return false; } + bool translateSExt(const User &U) { return false; } + bool translateZExt(const User &U) { return false; } + bool translateFPToUI(const User &U) { return false; } + bool translateFPToSI(const User &U) { return false; } + bool translateUIToFP(const User &U) { return false; } + bool translateSIToFP(const User &U) { return false; } + bool translateFPTrunc(const User &U) { return false; } + bool translateFPExt(const User &U) { return false; } + bool translateAddrSpaceCast(const User &U) { return false; } + bool translateCleanupPad(const User &U) { return false; } + bool translateCatchPad(const User &U) { return false; } + bool translateICmp(const User &U) { return false; } + bool translateFCmp(const User &U) { return false; } + bool translateSelect(const User &U) { return false; } + bool translateUserOp1(const User &U) { return false; } + bool translateUserOp2(const User &U) { return false; } + bool translateVAArg(const User &U) { return false; } + bool translateExtractElement(const User &U) { return false; } + bool translateInsertElement(const User &U) { return false; } + bool translateShuffleVector(const User &U) { return false; } + bool translateExtractValue(const User &U) { return false; } + bool translateInsertValue(const User &U) { return false; } + bool translateLandingPad(const User &U) { return false; } + /// @} // Builder for machine instruction a la IRBuilder. diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp index 788823d..0f06b54 100644 --- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -84,25 +84,25 @@ MachineBasicBlock &IRTranslator::getOrCreateBB(const BasicBlock &BB) { return *MBB; } -bool IRTranslator::translateBinaryOp(unsigned Opcode, - const BinaryOperator &Inst) { +bool IRTranslator::translateBinaryOp(unsigned Opcode, const User &U) { // FIXME: handle signed/unsigned wrapping flags. // Get or create a virtual register for each value. // Unless the value is a Constant => loadimm cst? // or inline constant each time? // Creation of a virtual register needs to have a size. - unsigned Op0 = getOrCreateVReg(*Inst.getOperand(0)); - unsigned Op1 = getOrCreateVReg(*Inst.getOperand(1)); - unsigned Res = getOrCreateVReg(Inst); - MIRBuilder.buildInstr(Opcode, LLT{*Inst.getType()}) + unsigned Op0 = getOrCreateVReg(*U.getOperand(0)); + unsigned Op1 = getOrCreateVReg(*U.getOperand(1)); + unsigned Res = getOrCreateVReg(U); + MIRBuilder.buildInstr(Opcode, LLT{*U.getType()}) .addDef(Res) .addUse(Op0) .addUse(Op1); return true; } -bool IRTranslator::translateReturn(const ReturnInst &RI) { +bool IRTranslator::translateRet(const User &U) { + const ReturnInst &RI = cast(U); const Value *Ret = RI.getReturnValue(); // The target may mess up with the insertion point, but // this is not important as a return is the last instruction @@ -110,7 +110,8 @@ bool IRTranslator::translateReturn(const ReturnInst &RI) { return CLI->lowerReturn(MIRBuilder, Ret, !Ret ? 0 : getOrCreateVReg(*Ret)); } -bool IRTranslator::translateBr(const BranchInst &BrInst) { +bool IRTranslator::translateBr(const User &U) { + const BranchInst &BrInst = cast(U); unsigned Succ = 0; if (!BrInst.isUnconditional()) { // We want a G_BRCOND to the true BB followed by an unconditional branch. @@ -131,7 +132,8 @@ bool IRTranslator::translateBr(const BranchInst &BrInst) { return true; } -bool IRTranslator::translateLoad(const LoadInst &LI) { +bool IRTranslator::translateLoad(const User &U) { + const LoadInst &LI = cast(U); assert(LI.isSimple() && "only simple loads are supported at the moment"); MachineFunction &MF = MIRBuilder.getMF(); @@ -147,7 +149,8 @@ bool IRTranslator::translateLoad(const LoadInst &LI) { return true; } -bool IRTranslator::translateStore(const StoreInst &SI) { +bool IRTranslator::translateStore(const User &U) { + const StoreInst &SI = cast(U); assert(SI.isSimple() && "only simple loads are supported at the moment"); MachineFunction &MF = MIRBuilder.getMF(); @@ -164,28 +167,30 @@ bool IRTranslator::translateStore(const StoreInst &SI) { return true; } -bool IRTranslator::translateBitCast(const CastInst &CI) { - if (LLT{*CI.getDestTy()} == LLT{*CI.getSrcTy()}) { - unsigned &Reg = ValToVReg[&CI]; +bool IRTranslator::translateBitCast(const User &U) { + if (LLT{*U.getOperand(0)->getType()} == LLT{*U.getType()}) { + unsigned &Reg = ValToVReg[&U]; if (Reg) - MIRBuilder.buildCopy(Reg, getOrCreateVReg(*CI.getOperand(0))); + MIRBuilder.buildCopy(Reg, getOrCreateVReg(*U.getOperand(0))); else - Reg = getOrCreateVReg(*CI.getOperand(0)); + Reg = getOrCreateVReg(*U.getOperand(0)); return true; } - return translateCast(TargetOpcode::G_BITCAST, CI); + return translateCast(TargetOpcode::G_BITCAST, U); } -bool IRTranslator::translateCast(unsigned Opcode, const CastInst &CI) { - unsigned Op = getOrCreateVReg(*CI.getOperand(0)); - unsigned Res = getOrCreateVReg(CI); - MIRBuilder.buildInstr(Opcode, {LLT{*CI.getDestTy()}, LLT{*CI.getSrcTy()}}) +bool IRTranslator::translateCast(unsigned Opcode, const User &U) { + unsigned Op = getOrCreateVReg(*U.getOperand(0)); + unsigned Res = getOrCreateVReg(U); + MIRBuilder + .buildInstr(Opcode, {LLT{*U.getType()}, LLT{*U.getOperand(0)->getType()}}) .addDef(Res) .addUse(Op); return true; } -bool IRTranslator::translateCall(const CallInst &CI) { +bool IRTranslator::translateCall(const User &U) { + const CallInst &CI = cast(U); auto TII = MIRBuilder.getMF().getTarget().getIntrinsicInfo(); const Function *F = CI.getCalledFunction(); @@ -246,7 +251,8 @@ bool IRTranslator::translateStaticAlloca(const AllocaInst &AI) { return true; } -bool IRTranslator::translatePhi(const PHINode &PI) { +bool IRTranslator::translatePHI(const User &U) { + const PHINode &PI = cast(U); MachineInstrBuilder MIB = MIRBuilder.buildInstr(TargetOpcode::PHI); MIB.addDef(getOrCreateVReg(PI)); @@ -277,59 +283,11 @@ void IRTranslator::finishPendingPhis() { bool IRTranslator::translate(const Instruction &Inst) { MIRBuilder.setDebugLoc(Inst.getDebugLoc()); switch(Inst.getOpcode()) { - // Arithmetic operations. - case Instruction::Add: - return translateBinaryOp(TargetOpcode::G_ADD, cast(Inst)); - case Instruction::Sub: - return translateBinaryOp(TargetOpcode::G_SUB, cast(Inst)); - - // Bitwise operations. - case Instruction::And: - return translateBinaryOp(TargetOpcode::G_AND, cast(Inst)); - case Instruction::Mul: - return translateBinaryOp(TargetOpcode::G_MUL, cast(Inst)); - case Instruction::Or: - return translateBinaryOp(TargetOpcode::G_OR, cast(Inst)); - case Instruction::Xor: - return translateBinaryOp(TargetOpcode::G_XOR, cast(Inst)); - - // Branch operations. - case Instruction::Br: - return translateBr(cast(Inst)); - case Instruction::Ret: - return translateReturn(cast(Inst)); - - // Calls - case Instruction::Call: - return translateCall(cast(Inst)); - - // Casts and allied operations - case Instruction::BitCast: - return translateBitCast(cast(Inst)); - case Instruction::IntToPtr: - return translateCast(TargetOpcode::G_INTTOPTR, cast(Inst)); - case Instruction::PtrToInt: - return translateCast(TargetOpcode::G_PTRTOINT, cast(Inst)); - case Instruction::Trunc: - return translateCast(TargetOpcode::G_TRUNC, cast(Inst)); - - // Memory ops. - case Instruction::Load: - return translateLoad(cast(Inst)); - case Instruction::Store: - return translateStore(cast(Inst)); - - case Instruction::Alloca: - return translateStaticAlloca(cast(Inst)); - - case Instruction::PHI: - return translatePhi(cast(Inst)); - - case Instruction::Unreachable: - return true; - +#define HANDLE_INST(NUM, OPCODE, CLASS) \ + case Instruction::OPCODE: return translate##OPCODE(Inst); +#include "llvm/IR/Instruction.def" default: - llvm_unreachable("Opcode not supported"); + llvm_unreachable("unknown opcode"); } } @@ -338,7 +296,15 @@ bool IRTranslator::translate(const Constant &C, unsigned Reg) { EntryBuilder.buildConstant(LLT{*CI->getType()}, Reg, CI->getZExtValue()); else if (isa(C)) EntryBuilder.buildInstr(TargetOpcode::IMPLICIT_DEF).addDef(Reg); - else + else if (auto CE = dyn_cast(&C)) { + switch(CE->getOpcode()) { +#define HANDLE_INST(NUM, OPCODE, CLASS) \ + case Instruction::OPCODE: return translate##OPCODE(*CE); +#include "llvm/IR/Instruction.def" + default: + llvm_unreachable("unknown opcode"); + } + } else llvm_unreachable("unhandled constant kind"); return true; diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll b/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll index f036d12..a164c7a 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll +++ b/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll @@ -389,3 +389,11 @@ define i32 @constant_int_start() { define i32 @test_undef() { ret i32 undef } + +; CHECK-LABEL: name: test_constant_inttoptr +; CHECK: [[ONE:%[0-9]+]](64) = G_CONSTANT s64 1 +; CHECK: [[PTR:%[0-9]+]](64) = G_INTTOPTR { p0, s64 } [[ONE]] +; CHECK: %x0 = COPY [[PTR]] +define i8* @test_constant_inttoptr() { + ret i8* inttoptr(i64 1 to i8*) +} -- 2.7.4