The output scale/precision cannot be arbitrary values. The algo here depends on them to be the same as computed in DecimalTypeSql. TODO: enforce this.
| 270 | /// to be the same as computed in DecimalTypeSql. |
| 271 | /// TODO: enforce this. |
| 272 | Status DecimalIR::BuildAdd() { |
| 273 | // Create fn prototype : |
| 274 | // int128_t |
| 275 | // add_decimal128_decimal128(int128_t x_value, int32_t x_precision, int32_t x_scale, |
| 276 | // int128_t y_value, int32_t y_precision, int32_t y_scale |
| 277 | // int32_t out_precision, int32_t out_scale) |
| 278 | auto i32 = types()->i32_type(); |
| 279 | auto i128 = types()->i128_type(); |
| 280 | auto function = BuildFunction(kAddFunction, i128, |
| 281 | { |
| 282 | {"x_value", i128}, |
| 283 | {"x_precision", i32}, |
| 284 | {"x_scale", i32}, |
| 285 | {"y_value", i128}, |
| 286 | {"y_precision", i32}, |
| 287 | {"y_scale", i32}, |
| 288 | {"out_precision", i32}, |
| 289 | {"out_scale", i32}, |
| 290 | }); |
| 291 | |
| 292 | auto arg_iter = function->arg_begin(); |
| 293 | ValueFull x(&arg_iter[0], &arg_iter[1], &arg_iter[2]); |
| 294 | ValueFull y(&arg_iter[3], &arg_iter[4], &arg_iter[5]); |
| 295 | ValueFull out(nullptr, &arg_iter[6], &arg_iter[7]); |
| 296 | |
| 297 | auto entry = llvm::BasicBlock::Create(*context(), "entry", function); |
| 298 | ir_builder()->SetInsertPoint(entry); |
| 299 | |
| 300 | // CPP : |
| 301 | // if (out_precision < 38) { |
| 302 | // return AddFastPath(x, y) |
| 303 | // } else { |
| 304 | // ret = AddWithOverflowCheck(x, y) |
| 305 | // if (ret.overflow) |
| 306 | // return AddLarge(x, y) |
| 307 | // else |
| 308 | // return ret.value; |
| 309 | // } |
| 310 | llvm::Value* lt_max_precision = ir_builder()->CreateICmpSLT( |
| 311 | out.precision(), types()->i32_constant(DecimalTypeUtil::kMaxPrecision)); |
| 312 | auto then_lambda = [&] { |
| 313 | // fast-path add |
| 314 | return AddFastPath(x, y); |
| 315 | }; |
| 316 | auto else_lambda = [&] { |
| 317 | if (kUseOverflowIntrinsics) { |
| 318 | // do the add and check if there was overflow |
| 319 | auto ret = AddWithOverflowCheck(x, y, out); |
| 320 | |
| 321 | // if there is an overflow, switch to the AddLarge codepath. |
| 322 | return BuildIfElse( |
| 323 | ret.overflow(), types()->i128_type(), [&] { return AddLarge(x, y, out); }, |
| 324 | [&] { return ret.value(); }); |
| 325 | } else { |
| 326 | return AddLarge(x, y, out); |
| 327 | } |
| 328 | }; |
| 329 | auto value = |
no test coverage detected