|
39 | 39 | #include "llvm/Support/raw_ostream.h"
|
40 | 40 | #include "llvm/Target/TargetLibraryInfo.h"
|
41 | 41 | #include "llvm/Target/TargetLowering.h"
|
| 42 | +#include "llvm/Target/TargetSubtargetInfo.h" |
42 | 43 | #include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
43 | 44 | #include "llvm/Transforms/Utils/BuildLibCalls.h"
|
44 | 45 | #include "llvm/Transforms/Utils/BypassSlowDivision.h"
|
@@ -70,6 +71,10 @@ static cl::opt<bool> DisableSelectToBranch(
|
70 | 71 | "disable-cgp-select2branch", cl::Hidden, cl::init(false),
|
71 | 72 | cl::desc("Disable select to branch conversion."));
|
72 | 73 |
|
| 74 | +static cl::opt<bool> AddrSinkUsingGEPs( |
| 75 | + "addr-sink-using-gep", cl::Hidden, cl::init(false), |
| 76 | + cl::desc("Address sinking in CGP using GEPs.")); |
| 77 | + |
73 | 78 | static cl::opt<bool> EnableAndCmpSinking(
|
74 | 79 | "enable-andcmp-sinking", cl::Hidden, cl::init(true),
|
75 | 80 | cl::desc("Enable sinkinig and/cmp into branches."));
|
@@ -2423,6 +2428,127 @@ bool CodeGenPrepare::OptimizeMemoryInst(Instruction *MemoryInst, Value *Addr,
|
2423 | 2428 | << *MemoryInst);
|
2424 | 2429 | if (SunkAddr->getType() != Addr->getType())
|
2425 | 2430 | SunkAddr = Builder.CreateBitCast(SunkAddr, Addr->getType());
|
| 2431 | + } else if (AddrSinkUsingGEPs || (!AddrSinkUsingGEPs.getNumOccurrences() && |
| 2432 | + TM && TM->getSubtarget<TargetSubtargetInfo>().useAA())) { |
| 2433 | + // By default, we use the GEP-based method when AA is used later. This |
| 2434 | + // prevents new inttoptr/ptrtoint pairs from degrading AA capabilities. |
| 2435 | + DEBUG(dbgs() << "CGP: SINKING nonlocal addrmode: " << AddrMode << " for " |
| 2436 | + << *MemoryInst); |
| 2437 | + Type *IntPtrTy = TLI->getDataLayout()->getIntPtrType(Addr->getType()); |
| 2438 | + Value *ResultPtr = 0, *ResultIndex = 0; |
| 2439 | + |
| 2440 | + // First, find the pointer. |
| 2441 | + if (AddrMode.BaseReg && AddrMode.BaseReg->getType()->isPointerTy()) { |
| 2442 | + ResultPtr = AddrMode.BaseReg; |
| 2443 | + AddrMode.BaseReg = 0; |
| 2444 | + } |
| 2445 | + |
| 2446 | + if (AddrMode.Scale && AddrMode.ScaledReg->getType()->isPointerTy()) { |
| 2447 | + // We can't add more than one pointer together, nor can we scale a |
| 2448 | + // pointer (both of which seem meaningless). |
| 2449 | + if (ResultPtr || AddrMode.Scale != 1) |
| 2450 | + return false; |
| 2451 | + |
| 2452 | + ResultPtr = AddrMode.ScaledReg; |
| 2453 | + AddrMode.Scale = 0; |
| 2454 | + } |
| 2455 | + |
| 2456 | + if (AddrMode.BaseGV) { |
| 2457 | + if (ResultPtr) |
| 2458 | + return false; |
| 2459 | + |
| 2460 | + ResultPtr = AddrMode.BaseGV; |
| 2461 | + } |
| 2462 | + |
| 2463 | + // If the real base value actually came from an inttoptr, then the matcher |
| 2464 | + // will look through it and provide only the integer value. In that case, |
| 2465 | + // use it here. |
| 2466 | + if (!ResultPtr && AddrMode.BaseReg) { |
| 2467 | + ResultPtr = |
| 2468 | + Builder.CreateIntToPtr(AddrMode.BaseReg, Addr->getType(), "sunkaddr"); |
| 2469 | + AddrMode.BaseReg = 0; |
| 2470 | + } else if (!ResultPtr && AddrMode.Scale == 1) { |
| 2471 | + ResultPtr = |
| 2472 | + Builder.CreateIntToPtr(AddrMode.ScaledReg, Addr->getType(), "sunkaddr"); |
| 2473 | + AddrMode.Scale = 0; |
| 2474 | + } |
| 2475 | + |
| 2476 | + if (!ResultPtr && |
| 2477 | + !AddrMode.BaseReg && !AddrMode.Scale && !AddrMode.BaseOffs) { |
| 2478 | + SunkAddr = Constant::getNullValue(Addr->getType()); |
| 2479 | + } else if (!ResultPtr) { |
| 2480 | + return false; |
| 2481 | + } else { |
| 2482 | + Type *I8PtrTy = |
| 2483 | + Builder.getInt8PtrTy(Addr->getType()->getPointerAddressSpace()); |
| 2484 | + |
| 2485 | + // Start with the base register. Do this first so that subsequent address |
| 2486 | + // matching finds it last, which will prevent it from trying to match it |
| 2487 | + // as the scaled value in case it happens to be a mul. That would be |
| 2488 | + // problematic if we've sunk a different mul for the scale, because then |
| 2489 | + // we'd end up sinking both muls. |
| 2490 | + if (AddrMode.BaseReg) { |
| 2491 | + Value *V = AddrMode.BaseReg; |
| 2492 | + if (V->getType() != IntPtrTy) |
| 2493 | + V = Builder.CreateIntCast(V, IntPtrTy, /*isSigned=*/true, "sunkaddr"); |
| 2494 | + |
| 2495 | + ResultIndex = V; |
| 2496 | + } |
| 2497 | + |
| 2498 | + // Add the scale value. |
| 2499 | + if (AddrMode.Scale) { |
| 2500 | + Value *V = AddrMode.ScaledReg; |
| 2501 | + if (V->getType() == IntPtrTy) { |
| 2502 | + // done. |
| 2503 | + } else if (cast<IntegerType>(IntPtrTy)->getBitWidth() < |
| 2504 | + cast<IntegerType>(V->getType())->getBitWidth()) { |
| 2505 | + V = Builder.CreateTrunc(V, IntPtrTy, "sunkaddr"); |
| 2506 | + } else { |
| 2507 | + // It is only safe to sign extend the BaseReg if we know that the math |
| 2508 | + // required to create it did not overflow before we extend it. Since |
| 2509 | + // the original IR value was tossed in favor of a constant back when |
| 2510 | + // the AddrMode was created we need to bail out gracefully if widths |
| 2511 | + // do not match instead of extending it. |
| 2512 | + Instruction *I = dyn_cast_or_null<Instruction>(ResultIndex); |
| 2513 | + if (I && (ResultIndex != AddrMode.BaseReg)) |
| 2514 | + I->eraseFromParent(); |
| 2515 | + return false; |
| 2516 | + } |
| 2517 | + |
| 2518 | + if (AddrMode.Scale != 1) |
| 2519 | + V = Builder.CreateMul(V, ConstantInt::get(IntPtrTy, AddrMode.Scale), |
| 2520 | + "sunkaddr"); |
| 2521 | + if (ResultIndex) |
| 2522 | + ResultIndex = Builder.CreateAdd(ResultIndex, V, "sunkaddr"); |
| 2523 | + else |
| 2524 | + ResultIndex = V; |
| 2525 | + } |
| 2526 | + |
| 2527 | + // Add in the Base Offset if present. |
| 2528 | + if (AddrMode.BaseOffs) { |
| 2529 | + Value *V = ConstantInt::get(IntPtrTy, AddrMode.BaseOffs); |
| 2530 | + if (ResultIndex) { |
| 2531 | + // We need to add this separately from the scale above to help with |
| 2532 | + // SDAG consecutive load/store merging. |
| 2533 | + if (ResultPtr->getType() != I8PtrTy) |
| 2534 | + ResultPtr = Builder.CreateBitCast(ResultPtr, I8PtrTy); |
| 2535 | + ResultPtr = Builder.CreateGEP(ResultPtr, ResultIndex, "sunkaddr"); |
| 2536 | + } |
| 2537 | + |
| 2538 | + ResultIndex = V; |
| 2539 | + } |
| 2540 | + |
| 2541 | + if (!ResultIndex) { |
| 2542 | + SunkAddr = ResultPtr; |
| 2543 | + } else { |
| 2544 | + if (ResultPtr->getType() != I8PtrTy) |
| 2545 | + ResultPtr = Builder.CreateBitCast(ResultPtr, I8PtrTy); |
| 2546 | + SunkAddr = Builder.CreateGEP(ResultPtr, ResultIndex, "sunkaddr"); |
| 2547 | + } |
| 2548 | + |
| 2549 | + if (SunkAddr->getType() != Addr->getType()) |
| 2550 | + SunkAddr = Builder.CreateBitCast(SunkAddr, Addr->getType()); |
| 2551 | + } |
2426 | 2552 | } else {
|
2427 | 2553 | DEBUG(dbgs() << "CGP: SINKING nonlocal addrmode: " << AddrMode << " for "
|
2428 | 2554 | << *MemoryInst);
|
|
0 commit comments