3434#include " llvm/Analysis/InstructionPrecedenceTracking.h"
3535#include " llvm/Analysis/InstructionSimplify.h"
3636#include " llvm/Analysis/Loads.h"
37- #include " llvm/Analysis/LoopInfo.h"
3837#include " llvm/Analysis/MemoryBuiltins.h"
3938#include " llvm/Analysis/MemoryDependenceAnalysis.h"
4039#include " llvm/Analysis/MemorySSA.h"
@@ -3334,31 +3333,64 @@ void GVNPass::assignValNumForDeadCode() {
33343333 }
33353334}
33363335
3336+ // Hoist the chain of operations for the second load to preheader.
3337+ // In this transformation, we hoist the redundant load to the preheader,
3338+ // caching the first value of the iteration. This value is used to compare with
3339+ // the current value of the iteration and update the minimum value.
3340+ // The comparison is done in the loop body using the new select instruction.
3341+ //
3342+ // *** Before transformation ***
3343+ //
3344+ // preheader:
3345+ // ...
3346+ // loop:
3347+ // ...
3348+ // ...
3349+ // %val.first = load <TYPE>, ptr %ptr.first.load, align 4
3350+ // %min.idx.ext = sext i32 %min.idx to i64
3351+ // %ptr.<TYPE>.min = getelementptr <TYPE>, ptr %0, i64 %min.idx.ext
3352+ // %ptr.second.load = getelementptr i8, ptr %ptr.<TYPE>.min, i64 -4
3353+ // %val.current.min = load <TYPE>, ptr %ptr.second.load, align 4
3354+ // ...
3355+ // ...
3356+ // br i1 %cond, label %loop, label %exit
3357+ //
3358+ // *** After transformation ***
3359+ //
3360+ // preheader:
3361+ // %min.idx.ext = sext i32 %min.idx.ext to i64
3362+ // %hoist_gep1 = getelementptr <TYPE>, ptr %0, i64 %min.idx.ext
3363+ // %hoist_gep2 = getelementptr i8, ptr %hoist_gep1, i64 -4
3364+ // %hoisted_load = load <TYPE>, ptr %hoist_gep2, align 4
3365+ // br label %loop
3366+ //
3367+ // loop:
3368+ // %val.first = load <TYPE>, ptr %ptr.first.load, align 4
3369+ // ...
3370+ // (new) %val.current.min = select i1 %cond, <TYPE> %hoisted_load, <TYPE>
3371+ // %val.current.min
3372+ // ...
3373+ // ...
3374+ // br i1 %cond, label %loop, label %exit
33373375bool GVNPass::transformMinFindingSelectPattern (
33383376 Loop *L, Type *LoadType, BasicBlock *Preheader, BasicBlock *BB, Value *LHS,
3339- Value *RHS , CmpInst *Comparison, SelectInst *Select, Value *BasePtr,
3377+ Value *LoadVal , CmpInst *Comparison, SelectInst *Select, Value *BasePtr,
33403378 Value *IndexVal, Value *OffsetVal) {
3341- // Hoist the chain of operations for the second load to preheader.
3342- // %min.idx.ext = sext i32 %min.idx to i64
3343- // %ptr.float.min = getelementptr float, ptr %0, i64 %min.idx.ext
3344- // %ptr.second.load = getelementptr i8, ptr %ptr.float.min, i64 -4
3345- // %val.current.min = load float, ptr %ptr.second.load, align 4
3346- IRBuilder<> Builder (Preheader->getTerminator ());
33473379
3348- PHINode *Phi = dyn_cast<PHINode>(IndexVal);
3349- if (!Phi) {
3350- LLVM_DEBUG (dbgs () << " GVN: IndexVal is not a PHI node\n " );
3351- return false ;
3352- }
3380+ assert (IndexVal && " IndexVal is null" );
3381+ AAResults *AA = VN.getAliasAnalysis ();
3382+ assert (AA && " AA is null" );
33533383
3354- Value *InitialMinIndex = Phi->getIncomingValueForBlock (Preheader);
3384+ IRBuilder<> Builder (Preheader->getTerminator ());
3385+ Value *InitialMinIndex =
3386+ dyn_cast<PHINode>(IndexVal)->getIncomingValueForBlock (Preheader);
33553387
33563388 // Insert PHI node at the top of this block.
33573389 // This PHI node will be used to memoize the current minimum value so far.
33583390 PHINode *KnownMinPhi = PHINode::Create (LoadType, 2 , " known_min" , BB->begin ());
33593391
33603392 // Hoist the load and build the necessary operations.
3361- // 1. hoist_0 = sext i32 to i64
3393+ // 1. hoist_0 = sext i32 1 to i64
33623394 Value *HoistedSExt =
33633395 Builder.CreateSExt (InitialMinIndex, Builder.getInt64Ty (), " hoist_sext" );
33643396
@@ -3370,12 +3402,40 @@ bool GVNPass::transformMinFindingSelectPattern(
33703402 Value *HoistedGEP2 = Builder.CreateGEP (Builder.getInt8Ty (), HoistedGEP1,
33713403 OffsetVal, " hoist_gep2" );
33723404
3405+ MemoryLocation NewLoc = MemoryLocation (
3406+ HoistedGEP2,
3407+ LocationSize::precise (
3408+ L->getHeader ()->getDataLayout ().getTypeStoreSize (LoadType)));
3409+ // Check if any instruction in the loop clobbers this location.
3410+ bool CanHoist = true ;
3411+ for (BasicBlock *BB : L->blocks ()) {
3412+ for (Instruction &I : *BB) {
3413+ if (I.mayWriteToMemory ()) {
3414+ // Check if this instruction may clobber our hoisted load.
3415+ ModRefInfo MRI = AA->getModRefInfo (&I, NewLoc);
3416+ if (isModOrRefSet (MRI)) {
3417+ LLVM_DEBUG (dbgs () << " GVN: Cannot hoist - may be clobbered by: " << I
3418+ << " \n " );
3419+ CanHoist = false ;
3420+ break ;
3421+ }
3422+ }
3423+ }
3424+ if (!CanHoist)
3425+ break ;
3426+ }
3427+ if (!CanHoist) {
3428+ LLVM_DEBUG (dbgs () << " GVN: Cannot hoist - may be clobbered by some "
3429+ " instruction in the loop.\n " );
3430+ return false ;
3431+ }
3432+
33733433 // 4. hoisted_load = load float, ptr HoistedGEP2
33743434 LoadInst *NewLoad = Builder.CreateLoad (LoadType, HoistedGEP2, " hoisted_load" );
33753435
33763436 // Let the new load now take the place of the old load.
3377- RHS ->replaceAllUsesWith (NewLoad);
3378- dyn_cast<LoadInst>(RHS )->eraseFromParent ();
3437+ LoadVal ->replaceAllUsesWith (NewLoad);
3438+ dyn_cast<LoadInst>(LoadVal )->eraseFromParent ();
33793439
33803440 // Comparison should now compare the current value and the newly inserted
33813441 // PHI node.
@@ -3390,16 +3450,42 @@ bool GVNPass::transformMinFindingSelectPattern(
33903450 // with (hoisted) NewLoad from the preheader and CurrentMinSelect.
33913451 KnownMinPhi->addIncoming (NewLoad, Preheader);
33923452 KnownMinPhi->addIncoming (CurrentMinSelect, BB);
3393- LLVM_DEBUG (dbgs () << " Transformed the code\n " );
3453+
3454+ if (MSSAU) {
3455+ auto *OrigUse =
3456+ MSSAU->getMemorySSA ()->getMemoryAccess (dyn_cast<Instruction>(LoadVal));
3457+ if (OrigUse) {
3458+ MemoryAccess *DefiningAccess = OrigUse->getDefiningAccess ();
3459+ MSSAU->createMemoryAccessInBB (NewLoad, DefiningAccess, Preheader,
3460+ MemorySSA::BeforeTerminator);
3461+ }
3462+ }
3463+ LLVM_DEBUG (
3464+ dbgs () << " GVN: Transformed the code for minimum finding pattern.\n " );
33943465 return true ;
33953466}
33963467
3468+ // We are looking for the following pattern:
3469+ // loop:
3470+ // ...
3471+ // ...
3472+ // %min.idx = phi i32 [ %initial_min_idx, %entry ], [ %min.idx.next, %loop ]
3473+ // ...
3474+ // %val.first = load <TYPE>, ptr %ptr.first.load, align 4
3475+ // %min.idx.ext = sext i32 %min.idx to i64
3476+ // %ptr.<TYPE>.min = getelementptr <TYPE>, ptr %0, i64 %min.idx.ext
3477+ // %ptr.second.load = getelementptr i8, ptr %ptr.<TYPE>.min, i64 -4
3478+ // %val.current.min = load <TYPE>, ptr %ptr.second.load, align 4
3479+ // %cmp = <CMP_INST> <TYPE> %val.first, %val.current.min
3480+ // ...
3481+ // %min.idx.next = select i1 %cmp, ..., i32 %min.idx
3482+ // ...
3483+ // ...
3484+ // br i1 ..., label %loop, ...
33973485bool GVNPass::recognizeMinFindingSelectPattern (SelectInst *Select) {
3398- Value *BasePtr = nullptr , *IndexVal = nullptr , *OffsetVal = nullptr ;
3399- LLVM_DEBUG (
3400- dbgs ()
3401- << " GVN: Analyzing select instruction for minimum finding pattern.\n " );
3402- LLVM_DEBUG (dbgs () << " GVN: Select: " << *Select << " \n " );
3486+ IRBuilder<> Builder (Select);
3487+ Value *BasePtr = nullptr , *IndexVal = nullptr , *OffsetVal = nullptr ,
3488+ *SExt = nullptr ;
34033489 BasicBlock *BB = Select->getParent ();
34043490
34053491 // If the block is not in a loop, bail out.
@@ -3439,21 +3525,41 @@ bool GVNPass::recognizeMinFindingSelectPattern(SelectInst *Select) {
34393525 return false ;
34403526 }
34413527
3442- if (!match (RHS,
3443- m_Load (m_GEP (m_GEP (m_Value (BasePtr), m_SExt (m_Value (IndexVal))),
3444- m_Value (OffsetVal))))) {
3528+ if (!match (RHS, m_Load (m_GEP (m_GEP (m_Value (BasePtr), m_Value (SExt)),
3529+ m_Value (OffsetVal))))) {
34453530 LLVM_DEBUG (dbgs () << " GVN: Not a required load pattern.\n " );
34463531 return false ;
34473532 }
3533+ // Check if the SExt instruction is a sext instruction.
3534+ SExtInst *SEInst = dyn_cast<SExtInst>(SExt);
3535+ if (!SEInst) {
3536+ LLVM_DEBUG (dbgs () << " GVN: not a sext instruction.\n " );
3537+ return false ;
3538+ }
3539+ // Check if the "To" and "from" type of the sext instruction are i64 and i32
3540+ // respectively.
3541+ if (SEInst->getType () != Builder.getInt64Ty () ||
3542+ SEInst->getOperand (0 )->getType () != Builder.getInt32Ty ()) {
3543+ LLVM_DEBUG (
3544+ dbgs ()
3545+ << " GVN: Not matching the required type for sext instruction.\n " );
3546+ return false ;
3547+ }
3548+
3549+ IndexVal = SEInst->getOperand (0 );
3550+ // Check if the IndexVal is a PHI node.
3551+ PHINode *Phi = dyn_cast<PHINode>(IndexVal);
3552+ if (!Phi) {
3553+ LLVM_DEBUG (dbgs () << " GVN: IndexVal is not a PHI node\n " );
3554+ return false ;
3555+ }
3556+
34483557 LLVM_DEBUG (dbgs () << " GVN: Found minimum finding pattern in Block: "
34493558 << Select->getParent ()->getName () << " .\n " );
34503559
3451- // Get type of load.
3452- Type *LoadType = dyn_cast<LoadInst>(LHS)->getType ();
3453- LLVM_DEBUG (dbgs () << " GVN: Transforming minimum finding pattern.\n " );
3454- return transformMinFindingSelectPattern (L, LoadType, Preheader, BB, LHS, RHS,
3455- Comparison, Select, BasePtr, IndexVal,
3456- OffsetVal);
3560+ return transformMinFindingSelectPattern (L, dyn_cast<LoadInst>(LHS)->getType (),
3561+ Preheader, BB, LHS, RHS, Comparison,
3562+ Select, BasePtr, IndexVal, OffsetVal);
34573563}
34583564
34593565class llvm ::gvn::GVNLegacyPass : public FunctionPass {
0 commit comments