1 /* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef LIBLLVMBACKEND_LOWERING_LLVM_IR_CONSTRUCTOR_H 17 #define LIBLLVMBACKEND_LOWERING_LLVM_IR_CONSTRUCTOR_H 18 19 #include "optimizer/ir/graph.h" 20 #include "optimizer/ir/graph_visitor.h" 21 #include "optimizer/ir/inst.h" 22 23 #include "debug_data_builder.h" 24 #include "llvm_ark_interface.h" 25 26 #include <llvm/IR/Function.h> 27 #include <llvm/IR/IRBuilder.h> 28 29 namespace panda::compiler { 30 31 class LLVMIrConstructor : public GraphVisitor { 32 using RuntimeCallId = std::variant<RuntimeInterface::EntrypointId, RuntimeInterface::IntrinsicId>; 33 34 bool TryEmitIntrinsic(Inst *inst, RuntimeInterface::IntrinsicId arkId); 35 36 private: 37 // Specific intrinsic Emitters 38 bool EmitUnreachable(); 39 bool EmitSlowPathEntry(Inst *inst); 40 bool EmitExclusiveLoadWithAcquire(Inst *inst); 41 bool EmitExclusiveStoreWithRelease(Inst *inst); 42 bool EmitInterpreterReturn(); 43 bool EmitTailCall(Inst *inst); 44 bool EmitMemoryFence(memory_order::Order order); 45 template <uint32_t VECTOR_SIZE> 46 bool EmitCompressUtf16ToUtf8CharsUsingSimd(Inst *inst); 47 48 public: 49 llvm::Value *GetMappedValue(Inst *inst, DataType::Type type); 50 llvm::Value *GetInputValue(Inst *inst, size_t index, bool skipCoerce = false); 51 llvm::Value *GetInputValueFromConstant(ConstantInst *constant, DataType::Type pandaType); 52 GetGraph()53 Graph *GetGraph() const 54 { 55 return graph_; 56 } 57 GetFunc()58 llvm::Function *GetFunc() 59 { 60 return func_; 61 } 62 GetBlocksToVisit()63 const ArenaVector<BasicBlock *> &GetBlocksToVisit() const override 64 { 65 return graph_->GetBlocksRPO(); 66 } 67 68 private: 69 // Initializers. BuildIr calls them 70 void BuildBasicBlocks(); 71 void BuildInstructions(); 72 void FillPhiInputs(); 73 74 // Creator functions for internal usage 75 76 void CreateInterpreterReturnRestoreRegs(RegMask ®Mask, size_t offset, bool fp); 77 llvm::Value *CreateBinaryOp(Inst *inst, llvm::Instruction::BinaryOps opcode); 78 llvm::Value *CreateBinaryImmOp(Inst *inst, llvm::Instruction::BinaryOps opcode, uint64_t c); 79 llvm::Value *CreateShiftOp(Inst *inst, llvm::Instruction::BinaryOps opcode); 80 llvm::Value *CreateSignDivMod(Inst *inst, llvm::Instruction::BinaryOps opcode); 81 llvm::Value *CreateAArch64SignDivMod(Inst *inst, llvm::Instruction::BinaryOps opcode, llvm::Value *x, 82 llvm::Value *y); 83 llvm::Value *CreateFloatComparison(CmpInst *cmpInst, llvm::Value *x, llvm::Value *y); 84 llvm::Value *CreateIntegerComparison(CmpInst *inst, llvm::Value *x, llvm::Value *y); 85 llvm::Value *CreateCastToInt(Inst *inst); 86 llvm::Value *CreateLoadWithOrdering(Inst *inst, llvm::Value *value, llvm::AtomicOrdering ordering, 87 const llvm::Twine &name = ""); 88 llvm::Value *CreateStoreWithOrdering(llvm::Value *value, llvm::Value *ptr, llvm::AtomicOrdering ordering); 89 void CreatePreWRB(Inst *inst, llvm::Value *mem); 90 void CreatePostWRB(Inst *inst, llvm::Value *mem, llvm::Value *offset, llvm::Value *value); 91 llvm::Value *CreateMemoryFence(memory_order::Order order); 92 llvm::Value *CreateCondition(ConditionCode cc, llvm::Value *x, llvm::Value *y); 93 void CreateIf(Inst *inst, llvm::Value *cond, bool likely, bool unlikely); 94 llvm::CallInst *CreateTailCallFastPath(Inst *inst); 95 llvm::CallInst *CreateTailCallInterpreter(Inst *inst); 96 97 // Getters 98 llvm::FunctionType *GetEntryFunctionType(); 99 100 llvm::StringRef GetRuntimeFunctionName(RuntimeCallId id); 101 102 llvm::Value *GetThreadRegValue(); 103 llvm::Value *GetRealFrameRegValue(); 104 GetArgument(size_t index)105 llvm::Argument *GetArgument(size_t index) 106 { 107 ASSERT(func_ != nullptr); 108 auto offset = 0; 109 return func_->arg_begin() + offset + index; 110 } 111 112 llvm::Type *GetType(DataType::Type pandaType); 113 llvm::Type *GetExactType(DataType::Type targetType); 114 115 llvm::Instruction::CastOps GetCastOp(DataType::Type from, DataType::Type to); 116 117 llvm::Value *CoerceValue(llvm::Value *value, DataType::Type sourceType, DataType::Type targetType); 118 llvm::Value *CoerceValue(llvm::Value *value, llvm::Type *targetType); 119 120 void ValueMapAdd(Inst *inst, llvm::Value *value, bool setName = true); 121 void FillValueMapForUsers(Inst *inst, llvm::Value *value, DataType::Type type, 122 ArenaUnorderedMap<DataType::Type, llvm::Value *> *typeMap); 123 AddBlock(BasicBlock * pb,llvm::BasicBlock * lb)124 void AddBlock(BasicBlock *pb, llvm::BasicBlock *lb) 125 { 126 ASSERT(blockTailMap_.count(pb) == 0); 127 blockTailMap_.insert({pb, lb}); 128 blockHeadMap_.insert({pb, lb}); 129 } 130 SetCurrentBasicBlock(llvm::BasicBlock * block)131 void SetCurrentBasicBlock(llvm::BasicBlock *block) 132 { 133 builder_.SetInsertPoint(block); 134 } 135 GetCurrentBasicBlock()136 llvm::BasicBlock *GetCurrentBasicBlock() 137 { 138 return builder_.GetInsertBlock(); 139 } 140 ReplaceTailBlock(BasicBlock * pandaBlock,llvm::BasicBlock * llvmBlock)141 void ReplaceTailBlock(BasicBlock *pandaBlock, llvm::BasicBlock *llvmBlock) 142 { 143 auto it = blockTailMap_.find(pandaBlock); 144 ASSERT(it != blockTailMap_.end()); 145 it->second = llvmBlock; 146 } 147 GetHeadBlock(BasicBlock * block)148 llvm::BasicBlock *GetHeadBlock(BasicBlock *block) 149 { 150 ASSERT(blockHeadMap_.count(block) == 1); 151 auto result = blockHeadMap_.at(block); 152 ASSERT(result != nullptr); 153 return result; 154 } 155 GetTailBlock(BasicBlock * block)156 llvm::BasicBlock *GetTailBlock(BasicBlock *block) 157 { 158 ASSERT(blockTailMap_.count(block) == 1); 159 auto result = blockTailMap_.at(block); 160 ASSERT(result != nullptr); 161 return result; 162 } 163 164 protected: 165 // Instruction Visitors 166 167 static void VisitConstant(GraphVisitor *v, Inst *inst); 168 static void VisitNullPtr(GraphVisitor *v, Inst *inst); 169 static void VisitLiveIn(GraphVisitor *v, Inst *inst); 170 static void VisitParameter(GraphVisitor *v, Inst *inst); 171 static void VisitReturnVoid(GraphVisitor *v, Inst *inst); 172 static void VisitReturn(GraphVisitor *v, Inst *inst); 173 static void VisitLiveOut(GraphVisitor *v, Inst *inst); 174 static void VisitLoad(GraphVisitor *v, Inst *inst); 175 static void VisitStore(GraphVisitor *v, Inst *inst); 176 static void VisitLoadI(GraphVisitor *v, Inst *inst); 177 static void VisitStoreI(GraphVisitor *v, Inst *inst); 178 static void VisitBitcast(GraphVisitor *v, Inst *inst); 179 static void VisitCast(GraphVisitor *v, Inst *inst); 180 static void VisitAnd(GraphVisitor *v, Inst *inst); 181 static void VisitAndI(GraphVisitor *v, Inst *inst); 182 static void VisitOr(GraphVisitor *v, Inst *inst); 183 static void VisitOrI(GraphVisitor *v, Inst *inst); 184 static void VisitXor(GraphVisitor *v, Inst *inst); 185 static void VisitXorI(GraphVisitor *v, Inst *inst); 186 static void VisitShl(GraphVisitor *v, Inst *inst); 187 static void VisitShlI(GraphVisitor *v, Inst *inst); 188 static void VisitShr(GraphVisitor *v, Inst *inst); 189 static void VisitShrI(GraphVisitor *v, Inst *inst); 190 static void VisitAShr(GraphVisitor *v, Inst *inst); 191 static void VisitAShrI(GraphVisitor *v, Inst *inst); 192 static void VisitAdd(GraphVisitor *v, Inst *inst); 193 static void VisitAddI(GraphVisitor *v, Inst *inst); 194 static void VisitSub(GraphVisitor *v, Inst *inst); 195 static void VisitSubI(GraphVisitor *v, Inst *inst); 196 static void VisitMul(GraphVisitor *v, Inst *inst); 197 static void VisitMulI(GraphVisitor *v, Inst *inst); 198 static void VisitDiv(GraphVisitor *v, Inst *inst); 199 static void VisitMod(GraphVisitor *v, Inst *inst); 200 static void VisitCompare(GraphVisitor *v, Inst *inst); 201 static void VisitCmp(GraphVisitor *v, Inst *inst); 202 static void VisitNeg(GraphVisitor *v, Inst *inst); 203 static void VisitNot(GraphVisitor *v, Inst *inst); 204 static void VisitIfImm(GraphVisitor *v, Inst *inst); 205 static void VisitIf(GraphVisitor *v, Inst *inst); 206 static void VisitCallIndirect(GraphVisitor *v, Inst *inst); 207 static void VisitCall(GraphVisitor *v, Inst *inst); 208 static void VisitPhi(GraphVisitor *v, Inst *inst); 209 static void VisitIntrinsic(GraphVisitor *v, Inst *inst); 210 211 void VisitDefault(Inst *inst) override; 212 213 public: 214 explicit LLVMIrConstructor(Graph *graph, llvm::Module *module, llvm::LLVMContext *context, 215 llvmbackend::LLVMArkInterface *arkInterface, 216 const std::unique_ptr<llvmbackend::DebugDataBuilder> &debugData); 217 218 bool BuildIr(); 219 220 static Expected<bool, std::string> CanCompile(Graph *graph); 221 static bool CanCompile(Inst *inst); 222 223 #include "optimizer/ir/visitor.inc" 224 225 private: 226 Graph *graph_ {nullptr}; 227 llvm::Function *func_; 228 llvm::IRBuilder<> builder_; 229 ArenaDoubleUnorderedMap<Inst *, DataType::Type, llvm::Value *> inputMap_; 230 ArenaUnorderedMap<BasicBlock *, llvm::BasicBlock *> blockTailMap_; 231 ArenaUnorderedMap<BasicBlock *, llvm::BasicBlock *> blockHeadMap_; 232 llvmbackend::LLVMArkInterface *arkInterface_; 233 const std::unique_ptr<llvmbackend::DebugDataBuilder> &debugData_; 234 ArenaVector<uint8_t> cc_; 235 ArenaVector<llvm::Value *> ccValues_; 236 }; 237 238 } // namespace panda::compiler 239 240 #endif // LIBLLVMBACKEND_LOWERING_LLVM_IR_CONSTRUCTOR_H 241