static bool is_always_false(compile_t* c, LLVMValueRef val) { if(!is_constant_i1(c, val)) return false; return LLVMConstIntGetZExtValue(val) == 0; }
static bool is_always_false(LLVMValueRef val) { if(!LLVMIsAConstantInt(val)) return false; return LLVMConstIntGetZExtValue(val) == 0; }
LLVMValueRef gen_init(struct node *ast) { LLVMValueRef var, array; char *name; int size; name = ast->one->val; var = LLVMBuildAlloca(builder, TYPE_INT, name); if (ast->two) { size = LLVMConstIntGetZExtValue(codegen(ast->two)); array = LLVMBuildAlloca(builder, TYPE_ARRAY(size), ""); LLVMBuildStore(builder, lvalue_to_rvalue(array), var); } symtab_enter(name, var); return NULL; }
LLVMValueRef gen_vecdef(struct node *ast) { LLVMValueRef global, array, init, *ival_list; struct node *n; int size, initsize, i; initsize = count_chain(ast->three); if (ast->two) size = LLVMConstIntGetZExtValue(codegen(ast->two)); else size = 0; if (initsize > size) size = initsize; ival_list = calloc(sizeof(LLVMValueRef), size); if (size > 0 && ival_list == NULL) generror("out of memory"); for (i = 0, n = ast->three; i < initsize; i++, n = n->two) /* TODO: handle NAMES (convert global pointer to int) */ ival_list[initsize - i - 1] = codegen(n->one); for (i = initsize; i < size; i++) ival_list[i] = CONST(0); global = find_or_add_global(ast->one->val); array = LLVMAddGlobal(module, TYPE_ARRAY(size), ".gvec"); LLVMSetLinkage(array, LLVMPrivateLinkage); if (initsize) init = LLVMConstArray(TYPE_INT, ival_list, size); else init = LLVMConstNull(TYPE_ARRAY(size)); LLVMSetInitializer(array, init); LLVMSetInitializer(global, LLVMBuildPtrToInt(builder, array, TYPE_INT, "")); return NULL; }
void ac_optimize_vs_outputs(struct ac_llvm_context *ctx, LLVMValueRef main_fn, uint8_t *vs_output_param_offset, uint32_t num_outputs, uint8_t *num_param_exports) { LLVMBasicBlockRef bb; bool removed_any = false; struct ac_vs_exports exports; exports.num = 0; /* Process all LLVM instructions. */ bb = LLVMGetFirstBasicBlock(main_fn); while (bb) { LLVMValueRef inst = LLVMGetFirstInstruction(bb); while (inst) { LLVMValueRef cur = inst; inst = LLVMGetNextInstruction(inst); struct ac_vs_exp_inst exp; if (LLVMGetInstructionOpcode(cur) != LLVMCall) continue; LLVMValueRef callee = ac_llvm_get_called_value(cur); if (!ac_llvm_is_function(callee)) continue; const char *name = LLVMGetValueName(callee); unsigned num_args = LLVMCountParams(callee); /* Check if this is an export instruction. */ if ((num_args != 9 && num_args != 8) || (strcmp(name, "llvm.SI.export") && strcmp(name, "llvm.amdgcn.exp.f32"))) continue; LLVMValueRef arg = LLVMGetOperand(cur, AC_EXP_TARGET); unsigned target = LLVMConstIntGetZExtValue(arg); if (target < V_008DFC_SQ_EXP_PARAM) continue; target -= V_008DFC_SQ_EXP_PARAM; /* Parse the instruction. */ memset(&exp, 0, sizeof(exp)); exp.offset = target; exp.inst = cur; for (unsigned i = 0; i < 4; i++) { LLVMValueRef v = LLVMGetOperand(cur, AC_EXP_OUT0 + i); exp.chan[i].value = v; if (LLVMIsUndef(v)) { exp.chan[i].type = AC_IR_UNDEF; } else if (LLVMIsAConstantFP(v)) { LLVMBool loses_info; exp.chan[i].type = AC_IR_CONST; exp.chan[i].const_float = LLVMConstRealGetDouble(v, &loses_info); } else { exp.chan[i].type = AC_IR_VALUE; } } /* Eliminate constant and duplicated PARAM exports. */ if (ac_eliminate_const_output(vs_output_param_offset, num_outputs, &exp) || ac_eliminate_duplicated_output(vs_output_param_offset, num_outputs, &exports, &exp)) { removed_any = true; } else { exports.exp[exports.num++] = exp; } } bb = LLVMGetNextBasicBlock(bb); } /* Remove holes in export memory due to removed PARAM exports. * This is done by renumbering all PARAM exports. */ if (removed_any) { uint8_t old_offset[VARYING_SLOT_MAX]; unsigned out, i; /* Make a copy of the offsets. We need the old version while * we are modifying some of them. */ memcpy(old_offset, vs_output_param_offset, sizeof(old_offset)); for (i = 0; i < exports.num; i++) { unsigned offset = exports.exp[i].offset; /* Update vs_output_param_offset. Multiple outputs can * have the same offset. */ for (out = 0; out < num_outputs; out++) { if (old_offset[out] == offset) vs_output_param_offset[out] = i; } /* Change the PARAM offset in the instruction. */ LLVMSetOperand(exports.exp[i].inst, AC_EXP_TARGET, LLVMConstInt(ctx->i32, V_008DFC_SQ_EXP_PARAM + i, 0)); } *num_param_exports = exports.num; } }
LLVMValueRef gen_if(compile_t* c, ast_t* ast) { bool needed = is_result_needed(ast); ast_t* type = ast_type(ast); AST_GET_CHILDREN(ast, cond, left, right); ast_t* left_type = ast_type(left); ast_t* right_type = ast_type(right); // We will have no type if both branches have return statements. reach_type_t* phi_type = NULL; if(!is_control_type(type)) phi_type = reach_type(c->reach, type); LLVMValueRef c_value = gen_expr(c, cond); if(c_value == NULL) return NULL; // If the conditional is constant, generate only one branch. bool gen_left = true; bool gen_right = true; if(LLVMIsAConstantInt(c_value)) { int value = (int)LLVMConstIntGetZExtValue(c_value); if(value == 0) gen_left = false; else gen_right = false; } LLVMBasicBlockRef then_block = codegen_block(c, "if_then"); LLVMBasicBlockRef else_block = codegen_block(c, "if_else"); LLVMBasicBlockRef post_block = NULL; // If both branches return, we have no post block. if(!is_control_type(type)) post_block = codegen_block(c, "if_post"); LLVMValueRef test = LLVMBuildTrunc(c->builder, c_value, c->i1, ""); LLVMBuildCondBr(c->builder, test, then_block, else_block); // Left branch. LLVMPositionBuilderAtEnd(c->builder, then_block); LLVMValueRef l_value; if(gen_left) { l_value = gen_expr(c, left); } else if(phi_type != NULL) { l_value = LLVMConstNull(phi_type->use_type); } else { LLVMBuildUnreachable(c->builder); l_value = GEN_NOVALUE; } if(l_value != GEN_NOVALUE) { if(needed) l_value = gen_assign_cast(c, phi_type->use_type, l_value, left_type); if(l_value == NULL) return NULL; then_block = LLVMGetInsertBlock(c->builder); LLVMBuildBr(c->builder, post_block); } // Right branch. LLVMPositionBuilderAtEnd(c->builder, else_block); LLVMValueRef r_value; if(gen_right) { r_value = gen_expr(c, right); } else if(phi_type != NULL) { r_value = LLVMConstNull(phi_type->use_type); } else { LLVMBuildUnreachable(c->builder); r_value = GEN_NOVALUE; } // If the right side returns, we don't branch to the post block. if(r_value != GEN_NOVALUE) { if(needed) r_value = gen_assign_cast(c, phi_type->use_type, r_value, right_type); if(r_value == NULL) return NULL; else_block = LLVMGetInsertBlock(c->builder); LLVMBuildBr(c->builder, post_block); } // If both sides return, we return a sentinal value. if(is_control_type(type)) return GEN_NOVALUE; // Continue in the post block. LLVMPositionBuilderAtEnd(c->builder, post_block); if(needed) { LLVMValueRef phi = LLVMBuildPhi(c->builder, phi_type->use_type, ""); if(l_value != GEN_NOVALUE) LLVMAddIncoming(phi, &l_value, &then_block, 1); if(r_value != GEN_NOVALUE) LLVMAddIncoming(phi, &r_value, &else_block, 1); return phi; } return GEN_NOTNEEDED; }