From 36eeb25bcd0d8a4b85489413bc1b1757d89e988d Mon Sep 17 00:00:00 2001 From: John Lu Date: Wed, 16 Apr 2025 06:39:59 -0500 Subject: [PATCH 01/14] Extend Sink pass to allow loads to be sunk to non-immediate successor blocks Signed-off-by: John Lu --- llvm/lib/Transforms/Scalar/Sink.cpp | 76 +++++++++---- llvm/test/Transforms/Sink/loadsink.ll | 152 ++++++++++++++++++++++++++ 2 files changed, 204 insertions(+), 24 deletions(-) create mode 100644 llvm/test/Transforms/Sink/loadsink.ll diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp index 1a48a59c4189e..57ce0c8990f4a 100644 --- a/llvm/lib/Transforms/Scalar/Sink.cpp +++ b/llvm/lib/Transforms/Scalar/Sink.cpp @@ -27,43 +27,71 @@ using namespace llvm; STATISTIC(NumSunk, "Number of instructions sunk"); STATISTIC(NumSinkIter, "Number of sinking iterations"); -static bool isSafeToMove(Instruction *Inst, AliasAnalysis &AA, - SmallPtrSetImpl &Stores) { - - if (Inst->mayWriteToMemory()) { - Stores.insert(Inst); - return false; - } - +static bool hasStoreConflict(Instruction *Inst, AliasAnalysis &AA, + SmallPtrSetImpl &Stores) { if (LoadInst *L = dyn_cast(Inst)) { MemoryLocation Loc = MemoryLocation::get(L); for (Instruction *S : Stores) if (isModSet(AA.getModRefInfo(S, Loc))) - return false; + return true; + } else if (auto *Call = dyn_cast(Inst)) { + for (Instruction *S : Stores) + if (isModSet(AA.getModRefInfo(S, Call))) + return true; } + return false; +} +static bool isSafeToMove(Instruction *Inst, AliasAnalysis &AA, + SmallPtrSetImpl &Stores) { + if (Inst->mayWriteToMemory()) { + Stores.insert(Inst); + return false; + } if (Inst->isTerminator() || isa(Inst) || Inst->isEHPad() || Inst->mayThrow() || !Inst->willReturn()) return false; - - if (auto *Call = dyn_cast(Inst)) { - // Convergent operations cannot be made control-dependent on additional - // values. + // Convergent operations cannot be made control-dependent on additional + // values. + if (auto *Call = dyn_cast(Inst)) if (Call->isConvergent()) return false; + if (hasStoreConflict(Inst, AA, Stores)) + return false; + return true; +} - for (Instruction *S : Stores) - if (isModSet(AA.getModRefInfo(S, Call))) - return false; - } +typedef SmallPtrSet BlocksSet; +static void findStores(SmallPtrSetImpl &Stores, + BasicBlock *LoadBB, BasicBlock *BB, + BlocksSet &VisitedBlocksSet) { + if (BB == LoadBB || VisitedBlocksSet.contains(BB)) + return; + VisitedBlocksSet.insert(BB); + + for (Instruction &Inst : *BB) + if (Inst.mayWriteToMemory()) + Stores.insert(&Inst); + for (BasicBlock *Pred : predecessors(BB)) + findStores(Stores, LoadBB, Pred, VisitedBlocksSet); +} - return true; +static bool hasConflictingStoreBeforeSuccToSinkTo(AliasAnalysis &AA, + Instruction *ReadMemInst, + BasicBlock *SuccToSinkTo) { + BlocksSet VisitedBlocksSet; + SmallPtrSet Stores; + BasicBlock *LoadBB = ReadMemInst->getParent(); + for (BasicBlock *Pred : predecessors(SuccToSinkTo)) + findStores(Stores, LoadBB, Pred, VisitedBlocksSet); + return hasStoreConflict(ReadMemInst, AA, Stores); } /// IsAcceptableTarget - Return true if it is possible to sink the instruction /// in the specified basic block. -static bool IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo, - DominatorTree &DT, LoopInfo &LI) { +static bool IsAcceptableTarget(AliasAnalysis &AA, Instruction *Inst, + BasicBlock *SuccToSinkTo, DominatorTree &DT, + LoopInfo &LI) { assert(Inst && "Instruction to be sunk is null"); assert(SuccToSinkTo && "Candidate sink target is null"); @@ -76,10 +104,10 @@ static bool IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo, // just punt. // FIXME: Split critical edges if not backedges. if (SuccToSinkTo->getUniquePredecessor() != Inst->getParent()) { - // We cannot sink a load across a critical edge - there may be stores in - // other code paths. + // Ensure that there is no conflicting store on any path to SuccToSinkTo. if (Inst->mayReadFromMemory() && - !Inst->hasMetadata(LLVMContext::MD_invariant_load)) + !Inst->hasMetadata(LLVMContext::MD_invariant_load) && + hasConflictingStoreBeforeSuccToSinkTo(AA, Inst, SuccToSinkTo)) return false; // We don't want to sink across a critical edge if we don't dominate the @@ -153,7 +181,7 @@ static bool SinkInstruction(Instruction *Inst, // The nearest common dominator may be in a parent loop of BB, which may not // be beneficial. Find an ancestor. while (SuccToSinkTo != BB && - !IsAcceptableTarget(Inst, SuccToSinkTo, DT, LI)) + !IsAcceptableTarget(AA, Inst, SuccToSinkTo, DT, LI)) SuccToSinkTo = DT.getNode(SuccToSinkTo)->getIDom()->getBlock(); if (SuccToSinkTo == BB) SuccToSinkTo = nullptr; diff --git a/llvm/test/Transforms/Sink/loadsink.ll b/llvm/test/Transforms/Sink/loadsink.ll new file mode 100644 index 0000000000000..d1fbf740250f6 --- /dev/null +++ b/llvm/test/Transforms/Sink/loadsink.ll @@ -0,0 +1,152 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -S < %s -passes=sink | FileCheck %s + +; Test that loads can be sunk to a non-immediate successor block by analyzing +; paths for conflicting stores. + +declare void @readfunc() readonly willreturn +declare void @maywritefunc() willreturn + +; Load can be sunk to non-immediate successor +define void @load_can_sink(i1 %condA, i1 %condB, ptr %a, ptr %b) { +; CHECK-LABEL: @load_can_sink( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[MERGEA:%.*]] +; CHECK: mergeA: +; CHECK-NEXT: br i1 [[CONDA:%.*]], label [[THENA:%.*]], label [[MERGEB:%.*]] +; CHECK: thenA: +; CHECK-NEXT: call void @readfunc() +; CHECK-NEXT: br label [[MERGEB]] +; CHECK: mergeB: +; CHECK-NEXT: br i1 [[CONDB:%.*]], label [[THENB:%.*]], label [[MERGEC:%.*]] +; CHECK: thenB: +; CHECK-NEXT: [[VALUE:%.*]] = load i32, ptr [[A:%.*]], align 4 +; CHECK-NEXT: store i32 [[VALUE]], ptr [[B:%.*]], align 4 +; CHECK-NEXT: br label [[MERGEC]] +; CHECK: mergeC: +; CHECK-NEXT: ret void +; +entry: + %value = load i32, ptr %a, align 4 + br label %mergeA +mergeA: + br i1 %condA, label %thenA, label %mergeB +thenA: + call void @readfunc() + br label %mergeB +mergeB: + br i1 %condB, label %thenB, label %mergeC +thenB: + store i32 %value, ptr %b + br label %mergeC +mergeC: + ret void +} + +; Call may store so load cannot be sunk +define void @load_cannot_sink(i1 %condA, i1 %condB, ptr %a, ptr %b) { +; CHECK-LABEL: @load_cannot_sink( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[MERGEA:%.*]] +; CHECK: mergeA: +; CHECK-NEXT: [[VALUE:%.*]] = load i32, ptr [[A:%.*]], align 4 +; CHECK-NEXT: br i1 [[CONDA:%.*]], label [[THENA:%.*]], label [[MERGEB:%.*]] +; CHECK: thenA: +; CHECK-NEXT: call void @maywritefunc() +; CHECK-NEXT: br label [[MERGEB]] +; CHECK: mergeB: +; CHECK-NEXT: br i1 [[CONDB:%.*]], label [[THENB:%.*]], label [[MERGEC:%.*]] +; CHECK: thenB: +; CHECK-NEXT: store i32 [[VALUE]], ptr [[B:%.*]], align 4 +; CHECK-NEXT: br label [[MERGEC]] +; CHECK: mergeC: +; CHECK-NEXT: ret void +; +entry: + %value = load i32, ptr %a, align 4 + br label %mergeA +mergeA: + br i1 %condA, label %thenA, label %mergeB +thenA: + call void @maywritefunc() + br label %mergeB +mergeB: + br i1 %condB, label %thenB, label %mergeC +thenB: + store i32 %value, ptr %b + br label %mergeC +mergeC: + ret void +} + +; Load can be sunk to non-immediate successor because load ptr is noalias +define void @load_can_sink_noalias(i1 %condA, i1 %condB, ptr noalias %a, ptr %b) { +; CHECK-LABEL: @load_can_sink_noalias( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[MERGEA:%.*]] +; CHECK: mergeA: +; CHECK-NEXT: br i1 [[CONDA:%.*]], label [[THENA:%.*]], label [[MERGEB:%.*]] +; CHECK: thenA: +; CHECK-NEXT: store i32 0, ptr [[B:%.*]], align 4 +; CHECK-NEXT: br label [[MERGEB]] +; CHECK: mergeB: +; CHECK-NEXT: br i1 [[CONDB:%.*]], label [[THENB:%.*]], label [[MERGEC:%.*]] +; CHECK: thenB: +; CHECK-NEXT: [[VALUE:%.*]] = load i32, ptr [[A:%.*]], align 4 +; CHECK-NEXT: store i32 [[VALUE]], ptr [[B]], align 4 +; CHECK-NEXT: br label [[MERGEC]] +; CHECK: mergeC: +; CHECK-NEXT: ret void +; +entry: + %value = load i32, ptr %a, align 4 + br label %mergeA +mergeA: + br i1 %condA, label %thenA, label %mergeB +thenA: + store i32 0, ptr %b + br label %mergeB +mergeB: + br i1 %condB, label %thenB, label %mergeC +thenB: + store i32 %value, ptr %b + br label %mergeC +mergeC: + ret void +} + +; Load cannot be sunk to non-immediate successor because load ptr may alias +define void @load_cannot_sink_alias(i1 %condA, i1 %condB, ptr %a, ptr %b) { +; CHECK-LABEL: @load_cannot_sink_alias( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[MERGEA:%.*]] +; CHECK: mergeA: +; CHECK-NEXT: [[VALUE:%.*]] = load i32, ptr [[A:%.*]], align 4 +; CHECK-NEXT: br i1 [[CONDA:%.*]], label [[THENA:%.*]], label [[MERGEB:%.*]] +; CHECK: thenA: +; CHECK-NEXT: store i32 0, ptr [[B:%.*]], align 4 +; CHECK-NEXT: br label [[MERGEB]] +; CHECK: mergeB: +; CHECK-NEXT: br i1 [[CONDB:%.*]], label [[THENB:%.*]], label [[MERGEC:%.*]] +; CHECK: thenB: +; CHECK-NEXT: store i32 [[VALUE]], ptr [[B]], align 4 +; CHECK-NEXT: br label [[MERGEC]] +; CHECK: mergeC: +; CHECK-NEXT: ret void +; +entry: + %value = load i32, ptr %a, align 4 + br label %mergeA +mergeA: + br i1 %condA, label %thenA, label %mergeB +thenA: + store i32 0, ptr %b + br label %mergeB +mergeB: + br i1 %condB, label %thenB, label %mergeC +thenB: + store i32 %value, ptr %b + br label %mergeC +mergeC: + ret void +} From f9fc4a87fbf92dc4268edbab85db6103c2318767 Mon Sep 17 00:00:00 2001 From: John Lu Date: Wed, 16 Apr 2025 06:41:41 -0500 Subject: [PATCH 02/14] Update tests Signed-off-by: John Lu --- .../AMDGPU/GlobalISel/llvm.amdgcn.div.fmas.ll | 86 ++++++++++--------- ...ne-sink-temporal-divergence-swdev407790.ll | 27 +++--- llvm/test/CodeGen/AMDGPU/set-wave-priority.ll | 3 +- .../AMDGPU/vgpr-spill-emergency-stack-slot.ll | 5 +- llvm/test/CodeGen/AMDGPU/wave32.ll | 40 ++++----- 5 files changed, 82 insertions(+), 79 deletions(-) diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.div.fmas.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.div.fmas.ll index 074272f7bed86..28ade94040688 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.div.fmas.ll +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.div.fmas.ll @@ -1330,13 +1330,7 @@ define amdgpu_kernel void @test_div_fmas_f32_logical_cond_to_vcc(ptr addrspace(1 define amdgpu_kernel void @test_div_fmas_f32_i1_phi_vcc(ptr addrspace(1) %out, [8 x i32], ptr addrspace(1) %in, [8 x i32], ptr addrspace(1) %dummy) { ; GFX7-LABEL: test_div_fmas_f32_i1_phi_vcc: ; GFX7: ; %bb.0: ; %entry -; GFX7-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0xa -; GFX7-NEXT: v_lshlrev_b32_e32 v1, 2, v0 -; GFX7-NEXT: v_mov_b32_e32 v2, 0 ; GFX7-NEXT: s_mov_b32 s2, 0 -; GFX7-NEXT: s_mov_b32 s3, 0xf000 -; GFX7-NEXT: s_waitcnt lgkmcnt(0) -; GFX7-NEXT: buffer_load_dwordx3 v[1:3], v[1:2], s[0:3], 0 addr64 ; GFX7-NEXT: v_cmp_eq_u32_e64 s[0:1], 0, v0 ; GFX7-NEXT: s_mov_b64 vcc, 0 ; GFX7-NEXT: s_and_saveexec_b64 s[6:7], s[0:1] @@ -1355,24 +1349,22 @@ define amdgpu_kernel void @test_div_fmas_f32_i1_phi_vcc(ptr addrspace(1) %out, [ ; GFX7-NEXT: s_or_b64 vcc, s[8:9], s[0:1] ; GFX7-NEXT: .LBB13_2: ; %exit ; GFX7-NEXT: s_or_b64 exec, exec, s[6:7] +; GFX7-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0xa +; GFX7-NEXT: v_lshlrev_b32_e32 v0, 2, v0 +; GFX7-NEXT: v_mov_b32_e32 v1, 0 +; GFX7-NEXT: s_mov_b32 s3, 0xf000 +; GFX7-NEXT: s_waitcnt lgkmcnt(0) +; GFX7-NEXT: buffer_load_dwordx3 v[0:2], v[0:1], s[0:3], 0 addr64 ; GFX7-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x0 -; GFX7-NEXT: s_waitcnt vmcnt(0) -; GFX7-NEXT: v_div_fmas_f32 v0, v1, v2, v3 ; GFX7-NEXT: s_mov_b32 s2, -1 +; GFX7-NEXT: s_waitcnt vmcnt(0) +; GFX7-NEXT: v_div_fmas_f32 v0, v0, v1, v2 ; GFX7-NEXT: s_waitcnt lgkmcnt(0) ; GFX7-NEXT: buffer_store_dword v0, off, s[0:3], 0 offset:8 ; GFX7-NEXT: s_endpgm ; ; GFX8-LABEL: test_div_fmas_f32_i1_phi_vcc: ; GFX8: ; %bb.0: ; %entry -; GFX8-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x28 -; GFX8-NEXT: v_lshlrev_b32_e32 v3, 2, v0 -; GFX8-NEXT: s_waitcnt lgkmcnt(0) -; GFX8-NEXT: v_mov_b32_e32 v2, s1 -; GFX8-NEXT: v_mov_b32_e32 v1, s0 -; GFX8-NEXT: v_add_u32_e32 v1, vcc, v1, v3 -; GFX8-NEXT: v_addc_u32_e32 v2, vcc, 0, v2, vcc -; GFX8-NEXT: flat_load_dwordx3 v[1:3], v[1:2] ; GFX8-NEXT: v_cmp_eq_u32_e64 s[0:1], 0, v0 ; GFX8-NEXT: s_mov_b64 vcc, 0 ; GFX8-NEXT: s_and_saveexec_b64 s[2:3], s[0:1] @@ -1391,12 +1383,20 @@ define amdgpu_kernel void @test_div_fmas_f32_i1_phi_vcc(ptr addrspace(1) %out, [ ; GFX8-NEXT: s_or_b64 vcc, s[6:7], s[0:1] ; GFX8-NEXT: .LBB13_2: ; %exit ; GFX8-NEXT: s_or_b64 exec, exec, s[2:3] -; GFX8-NEXT: s_waitcnt vmcnt(0) -; GFX8-NEXT: v_div_fmas_f32 v2, v1, v2, v3 +; GFX8-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x28 +; GFX8-NEXT: v_lshlrev_b32_e32 v2, 2, v0 +; GFX8-NEXT: s_waitcnt lgkmcnt(0) +; GFX8-NEXT: v_mov_b32_e32 v0, s0 +; GFX8-NEXT: v_mov_b32_e32 v1, s1 +; GFX8-NEXT: v_add_u32_e64 v0, s[0:1], v0, v2 +; GFX8-NEXT: v_addc_u32_e64 v1, s[0:1], 0, v1, s[0:1] +; GFX8-NEXT: flat_load_dwordx3 v[0:2], v[0:1] ; GFX8-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x0 ; GFX8-NEXT: s_waitcnt lgkmcnt(0) ; GFX8-NEXT: s_add_u32 s0, s0, 8 ; GFX8-NEXT: s_addc_u32 s1, s1, 0 +; GFX8-NEXT: s_waitcnt vmcnt(0) +; GFX8-NEXT: v_div_fmas_f32 v2, v0, v1, v2 ; GFX8-NEXT: v_mov_b32_e32 v0, s0 ; GFX8-NEXT: v_mov_b32_e32 v1, s1 ; GFX8-NEXT: flat_store_dword v[0:1], v2 @@ -1404,12 +1404,8 @@ define amdgpu_kernel void @test_div_fmas_f32_i1_phi_vcc(ptr addrspace(1) %out, [ ; ; GFX10_W32-LABEL: test_div_fmas_f32_i1_phi_vcc: ; GFX10_W32: ; %bb.0: ; %entry -; GFX10_W32-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x28 -; GFX10_W32-NEXT: v_lshlrev_b32_e32 v1, 2, v0 -; GFX10_W32-NEXT: s_mov_b32 vcc_lo, 0 -; GFX10_W32-NEXT: s_waitcnt lgkmcnt(0) -; GFX10_W32-NEXT: global_load_dwordx3 v[1:3], v1, s[0:1] ; GFX10_W32-NEXT: v_cmp_eq_u32_e64 s0, 0, v0 +; GFX10_W32-NEXT: s_mov_b32 vcc_lo, 0 ; GFX10_W32-NEXT: s_and_saveexec_b32 s1, s0 ; GFX10_W32-NEXT: s_cbranch_execz .LBB13_2 ; GFX10_W32-NEXT: ; %bb.1: ; %bb @@ -1426,9 +1422,14 @@ define amdgpu_kernel void @test_div_fmas_f32_i1_phi_vcc(ptr addrspace(1) %out, [ ; GFX10_W32-NEXT: s_or_b32 vcc_lo, s2, s0 ; GFX10_W32-NEXT: .LBB13_2: ; %exit ; GFX10_W32-NEXT: s_or_b32 exec_lo, exec_lo, s1 +; GFX10_W32-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x28 +; GFX10_W32-NEXT: v_lshlrev_b32_e32 v0, 2, v0 +; GFX10_W32-NEXT: s_waitcnt lgkmcnt(0) +; GFX10_W32-NEXT: global_load_dwordx3 v[0:2], v0, s[0:1] +; GFX10_W32-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10_W32-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x0 ; GFX10_W32-NEXT: s_waitcnt vmcnt(0) -; GFX10_W32-NEXT: v_div_fmas_f32 v0, v1, v2, v3 +; GFX10_W32-NEXT: v_div_fmas_f32 v0, v0, v1, v2 ; GFX10_W32-NEXT: v_mov_b32_e32 v1, 0 ; GFX10_W32-NEXT: s_waitcnt lgkmcnt(0) ; GFX10_W32-NEXT: global_store_dword v1, v0, s[0:1] offset:8 @@ -1436,12 +1437,8 @@ define amdgpu_kernel void @test_div_fmas_f32_i1_phi_vcc(ptr addrspace(1) %out, [ ; ; GFX10_W64-LABEL: test_div_fmas_f32_i1_phi_vcc: ; GFX10_W64: ; %bb.0: ; %entry -; GFX10_W64-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x28 -; GFX10_W64-NEXT: v_lshlrev_b32_e32 v1, 2, v0 -; GFX10_W64-NEXT: s_mov_b64 vcc, 0 -; GFX10_W64-NEXT: s_waitcnt lgkmcnt(0) -; GFX10_W64-NEXT: global_load_dwordx3 v[1:3], v1, s[0:1] ; GFX10_W64-NEXT: v_cmp_eq_u32_e64 s[0:1], 0, v0 +; GFX10_W64-NEXT: s_mov_b64 vcc, 0 ; GFX10_W64-NEXT: s_and_saveexec_b64 s[2:3], s[0:1] ; GFX10_W64-NEXT: s_cbranch_execz .LBB13_2 ; GFX10_W64-NEXT: ; %bb.1: ; %bb @@ -1458,9 +1455,14 @@ define amdgpu_kernel void @test_div_fmas_f32_i1_phi_vcc(ptr addrspace(1) %out, [ ; GFX10_W64-NEXT: s_or_b64 vcc, s[6:7], s[0:1] ; GFX10_W64-NEXT: .LBB13_2: ; %exit ; GFX10_W64-NEXT: s_or_b64 exec, exec, s[2:3] +; GFX10_W64-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x28 +; GFX10_W64-NEXT: v_lshlrev_b32_e32 v0, 2, v0 +; GFX10_W64-NEXT: s_waitcnt lgkmcnt(0) +; GFX10_W64-NEXT: global_load_dwordx3 v[0:2], v0, s[0:1] +; GFX10_W64-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10_W64-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x0 ; GFX10_W64-NEXT: s_waitcnt vmcnt(0) -; GFX10_W64-NEXT: v_div_fmas_f32 v0, v1, v2, v3 +; GFX10_W64-NEXT: v_div_fmas_f32 v0, v0, v1, v2 ; GFX10_W64-NEXT: v_mov_b32_e32 v1, 0 ; GFX10_W64-NEXT: s_waitcnt lgkmcnt(0) ; GFX10_W64-NEXT: global_store_dword v1, v0, s[0:1] offset:8 @@ -1468,14 +1470,10 @@ define amdgpu_kernel void @test_div_fmas_f32_i1_phi_vcc(ptr addrspace(1) %out, [ ; ; GFX11_W32-LABEL: test_div_fmas_f32_i1_phi_vcc: ; GFX11_W32: ; %bb.0: ; %entry -; GFX11_W32-NEXT: s_load_b64 s[0:1], s[4:5], 0x28 -; GFX11_W32-NEXT: v_and_b32_e32 v3, 0x3ff, v0 +; GFX11_W32-NEXT: v_and_b32_e32 v0, 0x3ff, v0 ; GFX11_W32-NEXT: s_mov_b32 vcc_lo, 0 -; GFX11_W32-NEXT: v_lshlrev_b32_e32 v0, 2, v3 -; GFX11_W32-NEXT: s_waitcnt lgkmcnt(0) -; GFX11_W32-NEXT: global_load_b96 v[0:2], v0, s[0:1] ; GFX11_W32-NEXT: s_mov_b32 s1, exec_lo -; GFX11_W32-NEXT: v_cmpx_eq_u32_e32 0, v3 +; GFX11_W32-NEXT: v_cmpx_eq_u32_e32 0, v0 ; GFX11_W32-NEXT: s_cbranch_execz .LBB13_2 ; GFX11_W32-NEXT: ; %bb.1: ; %bb ; GFX11_W32-NEXT: s_load_b64 s[2:3], s[4:5], 0x50 @@ -1491,6 +1489,10 @@ define amdgpu_kernel void @test_div_fmas_f32_i1_phi_vcc(ptr addrspace(1) %out, [ ; GFX11_W32-NEXT: s_or_b32 vcc_lo, s2, s0 ; GFX11_W32-NEXT: .LBB13_2: ; %exit ; GFX11_W32-NEXT: s_or_b32 exec_lo, exec_lo, s1 +; GFX11_W32-NEXT: s_load_b64 s[0:1], s[4:5], 0x28 +; GFX11_W32-NEXT: v_lshlrev_b32_e32 v0, 2, v0 +; GFX11_W32-NEXT: s_waitcnt lgkmcnt(0) +; GFX11_W32-NEXT: global_load_b96 v[0:2], v0, s[0:1] ; GFX11_W32-NEXT: s_load_b64 s[0:1], s[4:5], 0x0 ; GFX11_W32-NEXT: s_waitcnt vmcnt(0) ; GFX11_W32-NEXT: v_div_fmas_f32 v0, v0, v1, v2 @@ -1501,14 +1503,10 @@ define amdgpu_kernel void @test_div_fmas_f32_i1_phi_vcc(ptr addrspace(1) %out, [ ; ; GFX11_W64-LABEL: test_div_fmas_f32_i1_phi_vcc: ; GFX11_W64: ; %bb.0: ; %entry -; GFX11_W64-NEXT: s_load_b64 s[0:1], s[4:5], 0x28 -; GFX11_W64-NEXT: v_and_b32_e32 v3, 0x3ff, v0 +; GFX11_W64-NEXT: v_and_b32_e32 v0, 0x3ff, v0 ; GFX11_W64-NEXT: s_mov_b64 vcc, 0 ; GFX11_W64-NEXT: s_mov_b64 s[2:3], exec -; GFX11_W64-NEXT: v_lshlrev_b32_e32 v0, 2, v3 -; GFX11_W64-NEXT: s_waitcnt lgkmcnt(0) -; GFX11_W64-NEXT: global_load_b96 v[0:2], v0, s[0:1] -; GFX11_W64-NEXT: v_cmpx_eq_u32_e32 0, v3 +; GFX11_W64-NEXT: v_cmpx_eq_u32_e32 0, v0 ; GFX11_W64-NEXT: s_cbranch_execz .LBB13_2 ; GFX11_W64-NEXT: ; %bb.1: ; %bb ; GFX11_W64-NEXT: s_load_b64 s[0:1], s[4:5], 0x50 @@ -1524,6 +1522,10 @@ define amdgpu_kernel void @test_div_fmas_f32_i1_phi_vcc(ptr addrspace(1) %out, [ ; GFX11_W64-NEXT: s_or_b64 vcc, s[6:7], s[0:1] ; GFX11_W64-NEXT: .LBB13_2: ; %exit ; GFX11_W64-NEXT: s_or_b64 exec, exec, s[2:3] +; GFX11_W64-NEXT: s_load_b64 s[0:1], s[4:5], 0x28 +; GFX11_W64-NEXT: v_lshlrev_b32_e32 v0, 2, v0 +; GFX11_W64-NEXT: s_waitcnt lgkmcnt(0) +; GFX11_W64-NEXT: global_load_b96 v[0:2], v0, s[0:1] ; GFX11_W64-NEXT: s_load_b64 s[0:1], s[4:5], 0x0 ; GFX11_W64-NEXT: s_waitcnt vmcnt(0) ; GFX11_W64-NEXT: v_div_fmas_f32 v0, v0, v1, v2 diff --git a/llvm/test/CodeGen/AMDGPU/machine-sink-temporal-divergence-swdev407790.ll b/llvm/test/CodeGen/AMDGPU/machine-sink-temporal-divergence-swdev407790.ll index 4a6b2ebd3d203..500659ea0ca86 100644 --- a/llvm/test/CodeGen/AMDGPU/machine-sink-temporal-divergence-swdev407790.ll +++ b/llvm/test/CodeGen/AMDGPU/machine-sink-temporal-divergence-swdev407790.ll @@ -877,14 +877,11 @@ define protected amdgpu_kernel void @kernel_round1_short(ptr addrspace(1) nocapt ; CHECK-NEXT: ; =>This Loop Header: Depth=1 ; CHECK-NEXT: ; Child Loop BB1_3 Depth 2 ; CHECK-NEXT: ; Child Loop BB1_8 Depth 2 -; CHECK-NEXT: v_add_nc_u32_e32 v0, s4, v44 ; CHECK-NEXT: s_lshl_b32 s5, s4, 5 ; CHECK-NEXT: s_add_i32 s53, s4, 1 ; CHECK-NEXT: s_add_i32 s6, s4, 5 -; CHECK-NEXT: v_or3_b32 v47, s5, v42, s53 -; CHECK-NEXT: s_waitcnt lgkmcnt(0) -; CHECK-NEXT: ds_read_u8 v46, v0 -; CHECK-NEXT: v_mov_b32_e32 v56, s53 +; CHECK-NEXT: v_or3_b32 v46, s5, v42, s53 +; CHECK-NEXT: v_mov_b32_e32 v47, s53 ; CHECK-NEXT: s_mov_b32 s5, exec_lo ; CHECK-NEXT: v_cmpx_lt_u32_e64 s6, v41 ; CHECK-NEXT: s_cbranch_execz .LBB1_5 @@ -898,46 +895,48 @@ define protected amdgpu_kernel void @kernel_round1_short(ptr addrspace(1) nocapt ; CHECK-NEXT: s_add_i32 s7, s7, 4 ; CHECK-NEXT: v_add_nc_u32_e32 v43, 1, v43 ; CHECK-NEXT: s_add_i32 s8, s4, s7 -; CHECK-NEXT: v_add_nc_u32_e32 v0, s7, v47 +; CHECK-NEXT: v_add_nc_u32_e32 v0, s7, v46 ; CHECK-NEXT: s_add_i32 s9, s8, 5 ; CHECK-NEXT: s_add_i32 s8, s8, 1 ; CHECK-NEXT: v_cmp_ge_u32_e32 vcc_lo, s9, v41 -; CHECK-NEXT: v_mov_b32_e32 v56, s8 +; CHECK-NEXT: v_mov_b32_e32 v47, s8 ; CHECK-NEXT: s_or_b32 s6, vcc_lo, s6 ; CHECK-NEXT: s_andn2_b32 exec_lo, exec_lo, s6 ; CHECK-NEXT: s_cbranch_execnz .LBB1_3 ; CHECK-NEXT: ; %bb.4: ; %Flow3 ; CHECK-NEXT: ; in Loop: Header=BB1_1 Depth=1 ; CHECK-NEXT: s_or_b32 exec_lo, exec_lo, s6 -; CHECK-NEXT: v_mov_b32_e32 v47, v0 +; CHECK-NEXT: v_mov_b32_e32 v46, v0 ; CHECK-NEXT: .LBB1_5: ; %Flow4 ; CHECK-NEXT: ; in Loop: Header=BB1_1 Depth=1 ; CHECK-NEXT: s_or_b32 exec_lo, exec_lo, s5 ; CHECK-NEXT: s_mov_b32 s54, exec_lo -; CHECK-NEXT: v_cmpx_lt_u32_e64 v56, v41 +; CHECK-NEXT: v_cmpx_lt_u32_e64 v47, v41 ; CHECK-NEXT: s_cbranch_execz .LBB1_11 ; CHECK-NEXT: ; %bb.6: ; %.103.preheader ; CHECK-NEXT: ; in Loop: Header=BB1_1 Depth=1 +; CHECK-NEXT: v_add_nc_u32_e32 v0, s4, v44 ; CHECK-NEXT: s_mov_b32 s55, 0 +; CHECK-NEXT: ds_read_u8 v56, v0 ; CHECK-NEXT: s_inst_prefetch 0x1 ; CHECK-NEXT: s_branch .LBB1_8 ; CHECK-NEXT: .p2align 6 ; CHECK-NEXT: .LBB1_7: ; %.114 ; CHECK-NEXT: ; in Loop: Header=BB1_8 Depth=2 ; CHECK-NEXT: s_or_b32 exec_lo, exec_lo, s64 -; CHECK-NEXT: v_add_nc_u32_e32 v56, 1, v56 ; CHECK-NEXT: v_add_nc_u32_e32 v47, 1, v47 -; CHECK-NEXT: v_cmp_ge_u32_e32 vcc_lo, v56, v41 +; CHECK-NEXT: v_add_nc_u32_e32 v46, 1, v46 +; CHECK-NEXT: v_cmp_ge_u32_e32 vcc_lo, v47, v41 ; CHECK-NEXT: s_or_b32 s55, vcc_lo, s55 ; CHECK-NEXT: s_andn2_b32 exec_lo, exec_lo, s55 ; CHECK-NEXT: s_cbranch_execz .LBB1_10 ; CHECK-NEXT: .LBB1_8: ; %.103 ; CHECK-NEXT: ; Parent Loop BB1_1 Depth=1 ; CHECK-NEXT: ; => This Inner Loop Header: Depth=2 -; CHECK-NEXT: v_add_nc_u32_e32 v0, v44, v56 +; CHECK-NEXT: v_add_nc_u32_e32 v0, v44, v47 ; CHECK-NEXT: ds_read_u8 v0, v0 ; CHECK-NEXT: s_waitcnt lgkmcnt(0) -; CHECK-NEXT: v_cmp_eq_u16_sdwa s4, v46, v0 src0_sel:BYTE_0 src1_sel:DWORD +; CHECK-NEXT: v_cmp_eq_u16_sdwa s4, v56, v0 src0_sel:BYTE_0 src1_sel:DWORD ; CHECK-NEXT: s_and_saveexec_b32 s64, s4 ; CHECK-NEXT: s_cbranch_execz .LBB1_7 ; CHECK-NEXT: ; %bb.9: ; %.110 @@ -958,7 +957,7 @@ define protected amdgpu_kernel void @kernel_round1_short(ptr addrspace(1) nocapt ; CHECK-NEXT: v_add_nc_u32_e32 v43, 1, v43 ; CHECK-NEXT: s_swappc_b64 s[30:31], s[16:17] ; CHECK-NEXT: v_lshlrev_b32_e32 v0, 2, v0 -; CHECK-NEXT: ds_write_b32 v0, v47 +; CHECK-NEXT: ds_write_b32 v0, v46 ; CHECK-NEXT: s_branch .LBB1_7 ; CHECK-NEXT: .LBB1_10: ; %Flow ; CHECK-NEXT: ; in Loop: Header=BB1_1 Depth=1 diff --git a/llvm/test/CodeGen/AMDGPU/set-wave-priority.ll b/llvm/test/CodeGen/AMDGPU/set-wave-priority.ll index a27d1217031ca..0e30b4bb5925c 100644 --- a/llvm/test/CodeGen/AMDGPU/set-wave-priority.ll +++ b/llvm/test/CodeGen/AMDGPU/set-wave-priority.ll @@ -72,13 +72,14 @@ entry: a: %v2 = call <2 x float> @llvm.amdgcn.struct.ptr.buffer.load.v2f32(ptr addrspace(8) %p, i32 0, i32 0, i32 1, i32 0) + %v3 = fadd <2 x float> %v1, %v2 %v20 = extractelement <2 x float> %v2, i32 0 %v21 = extractelement <2 x float> %v2, i32 1 %cond2 = fcmp ult float %v20, %v21 br i1 %cond2, label %b, label %c b: - ret <2 x float> %v2 + ret <2 x float> %v3 c: %v4 = fadd <2 x float> %v1, %v1 diff --git a/llvm/test/CodeGen/AMDGPU/vgpr-spill-emergency-stack-slot.ll b/llvm/test/CodeGen/AMDGPU/vgpr-spill-emergency-stack-slot.ll index 8dfd841671730..7426ecca7301a 100644 --- a/llvm/test/CodeGen/AMDGPU/vgpr-spill-emergency-stack-slot.ll +++ b/llvm/test/CodeGen/AMDGPU/vgpr-spill-emergency-stack-slot.ll @@ -41,7 +41,8 @@ bb: %tmp20 = extractelement <4 x float> %tmp18, i32 1 %tmp21 = extractelement <4 x float> %tmp18, i32 2 %tmp22 = extractelement <4 x float> %tmp18, i32 3 - %tmp23 = bitcast float %tmp14 to i32 + %tmp23 = fadd float %tmp14, %tmp22 + %tmp24 = bitcast float %tmp23 to i32 br label %bb24 bb24: ; preds = %bb157, %bb @@ -218,7 +219,7 @@ bb156: ; preds = %bb24 bb157: ; preds = %bb24 %tmp158 = bitcast float %tmp107 to i32 %tmp159 = bitcast float %tmp107 to i32 - %tmp160 = add i32 %tmp23, %tmp159 + %tmp160 = add i32 %tmp24, %tmp159 %tmp161 = bitcast i32 %tmp160 to float %tmp162 = insertelement <128 x float> poison, float %tmp103, i32 0 %tmp163 = insertelement <128 x float> %tmp162, float %tmp102, i32 1 diff --git a/llvm/test/CodeGen/AMDGPU/wave32.ll b/llvm/test/CodeGen/AMDGPU/wave32.ll index 4212fd3b35cd8..396c06cfbc540 100644 --- a/llvm/test/CodeGen/AMDGPU/wave32.ll +++ b/llvm/test/CodeGen/AMDGPU/wave32.ll @@ -1266,26 +1266,26 @@ define amdgpu_kernel void @test_div_fmas_f32_i1_phi_vcc(ptr addrspace(1) %out, p ; GFX1032-NEXT: s_clause 0x1 ; GFX1032-NEXT: s_load_dwordx4 s[8:11], s[4:5], 0x24 ; GFX1032-NEXT: s_load_dwordx2 s[2:3], s[4:5], 0x34 -; GFX1032-NEXT: v_lshlrev_b32_e32 v1, 2, v0 ; GFX1032-NEXT: v_cmp_eq_u32_e64 s0, 0, v0 ; GFX1032-NEXT: s_mov_b32 vcc_lo, 0 -; GFX1032-NEXT: s_waitcnt lgkmcnt(0) -; GFX1032-NEXT: global_load_dwordx3 v[1:3], v1, s[10:11] ; GFX1032-NEXT: s_and_saveexec_b32 s1, s0 ; GFX1032-NEXT: s_cbranch_execz .LBB22_2 ; GFX1032-NEXT: ; %bb.1: ; %bb -; GFX1032-NEXT: v_mov_b32_e32 v0, 0 -; GFX1032-NEXT: global_load_dword v0, v0, s[2:3] glc dlc +; GFX1032-NEXT: v_mov_b32_e32 v1, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: global_load_dword v1, v1, s[2:3] glc dlc ; GFX1032-NEXT: s_waitcnt vmcnt(0) -; GFX1032-NEXT: v_cmp_ne_u32_e32 vcc_lo, 0, v0 +; GFX1032-NEXT: v_cmp_ne_u32_e32 vcc_lo, 0, v1 ; GFX1032-NEXT: s_and_b32 vcc_lo, vcc_lo, exec_lo ; GFX1032-NEXT: .LBB22_2: ; %exit -; GFX1032-NEXT: s_waitcnt_depctr 0xffe3 ; GFX1032-NEXT: s_or_b32 exec_lo, exec_lo, s1 -; GFX1032-NEXT: v_mov_b32_e32 v0, 0 +; GFX1032-NEXT: v_lshlrev_b32_e32 v0, 2, v0 +; GFX1032-NEXT: v_mov_b32_e32 v3, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: global_load_dwordx3 v[0:2], v0, s[10:11] ; GFX1032-NEXT: s_waitcnt vmcnt(0) -; GFX1032-NEXT: v_div_fmas_f32 v1, v1, v2, v3 -; GFX1032-NEXT: global_store_dword v0, v1, s[8:9] offset:8 +; GFX1032-NEXT: v_div_fmas_f32 v0, v0, v1, v2 +; GFX1032-NEXT: global_store_dword v3, v0, s[8:9] offset:8 ; GFX1032-NEXT: s_endpgm ; ; GFX1064-LABEL: test_div_fmas_f32_i1_phi_vcc: @@ -1293,26 +1293,26 @@ define amdgpu_kernel void @test_div_fmas_f32_i1_phi_vcc(ptr addrspace(1) %out, p ; GFX1064-NEXT: s_clause 0x1 ; GFX1064-NEXT: s_load_dwordx4 s[8:11], s[4:5], 0x24 ; GFX1064-NEXT: s_load_dwordx2 s[6:7], s[4:5], 0x34 -; GFX1064-NEXT: v_lshlrev_b32_e32 v1, 2, v0 ; GFX1064-NEXT: v_cmp_eq_u32_e64 s[0:1], 0, v0 ; GFX1064-NEXT: s_mov_b64 vcc, 0 -; GFX1064-NEXT: s_waitcnt lgkmcnt(0) -; GFX1064-NEXT: global_load_dwordx3 v[1:3], v1, s[10:11] ; GFX1064-NEXT: s_and_saveexec_b64 s[2:3], s[0:1] ; GFX1064-NEXT: s_cbranch_execz .LBB22_2 ; GFX1064-NEXT: ; %bb.1: ; %bb -; GFX1064-NEXT: v_mov_b32_e32 v0, 0 -; GFX1064-NEXT: global_load_dword v0, v0, s[6:7] glc dlc +; GFX1064-NEXT: v_mov_b32_e32 v1, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: global_load_dword v1, v1, s[6:7] glc dlc ; GFX1064-NEXT: s_waitcnt vmcnt(0) -; GFX1064-NEXT: v_cmp_ne_u32_e32 vcc, 0, v0 +; GFX1064-NEXT: v_cmp_ne_u32_e32 vcc, 0, v1 ; GFX1064-NEXT: s_and_b64 vcc, vcc, exec ; GFX1064-NEXT: .LBB22_2: ; %exit -; GFX1064-NEXT: s_waitcnt_depctr 0xffe3 ; GFX1064-NEXT: s_or_b64 exec, exec, s[2:3] -; GFX1064-NEXT: v_mov_b32_e32 v0, 0 +; GFX1064-NEXT: v_lshlrev_b32_e32 v0, 2, v0 +; GFX1064-NEXT: v_mov_b32_e32 v3, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: global_load_dwordx3 v[0:2], v0, s[10:11] ; GFX1064-NEXT: s_waitcnt vmcnt(0) -; GFX1064-NEXT: v_div_fmas_f32 v1, v1, v2, v3 -; GFX1064-NEXT: global_store_dword v0, v1, s[8:9] offset:8 +; GFX1064-NEXT: v_div_fmas_f32 v0, v0, v1, v2 +; GFX1064-NEXT: global_store_dword v3, v0, s[8:9] offset:8 ; GFX1064-NEXT: s_endpgm entry: %tid = call i32 @llvm.amdgcn.workitem.id.x() nounwind readnone From e78335e482c9563b7f4d20cf82955cbd4167fb02 Mon Sep 17 00:00:00 2001 From: John Lu Date: Wed, 16 Apr 2025 11:21:03 -0500 Subject: [PATCH 03/14] Update NumSgprs for GCN Trackers test Signed-off-by: John Lu --- llvm/test/CodeGen/AMDGPU/schedule-amdgpu-trackers.ll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/test/CodeGen/AMDGPU/schedule-amdgpu-trackers.ll b/llvm/test/CodeGen/AMDGPU/schedule-amdgpu-trackers.ll index c5732531f5423..ec95a7ed03b95 100644 --- a/llvm/test/CodeGen/AMDGPU/schedule-amdgpu-trackers.ll +++ b/llvm/test/CodeGen/AMDGPU/schedule-amdgpu-trackers.ll @@ -73,8 +73,8 @@ define amdgpu_kernel void @constant_zextload_v64i16_to_v64i32(ptr addrspace(1) % } ; CHECK-LABEL: {{^}}excess_soft_clause_reg_pressure: -; GFX908: NumSgprs: 64 -; GFX908-GCNTRACKERS: NumSgprs: 64 +; GFX908: NumSgprs: 56 +; GFX908-GCNTRACKERS: NumSgprs: 56 ; GFX908: NumVgprs: 43 ; GFX908-GCNTRACKERS: NumVgprs: 39 ; GFX908: Occupancy: 5 From 54807132163ec97e2e3f3ffedb2e3513424b985d Mon Sep 17 00:00:00 2001 From: John Lu Date: Wed, 16 Apr 2025 11:41:53 -0500 Subject: [PATCH 04/14] Add test that sinks part of the way to the use Signed-off-by: John Lu --- llvm/test/Transforms/Sink/loadsink.ll | 46 +++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/llvm/test/Transforms/Sink/loadsink.ll b/llvm/test/Transforms/Sink/loadsink.ll index d1fbf740250f6..9a9c106559d44 100644 --- a/llvm/test/Transforms/Sink/loadsink.ll +++ b/llvm/test/Transforms/Sink/loadsink.ll @@ -150,3 +150,49 @@ thenB: mergeC: ret void } + +; Load can be sunk, but not all the way to the use. +define void @load_can_sink_part_of_the_way(i1 %condA, i1 %condB, i1 %condC, ptr noalias %a, ptr %b) { +; CHECK-LABEL: @load_can_sink_part_of_the_way( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[MERGEA:%.*]] +; CHECK: mergeA: +; CHECK-NEXT: br i1 [[CONDA:%.*]], label [[THENA:%.*]], label [[MERGEB:%.*]] +; CHECK: thenA: +; CHECK-NEXT: store i32 0, ptr [[B:%.*]], align 4 +; CHECK-NEXT: br label [[MERGEB]] +; CHECK: mergeB: +; CHECK-NEXT: [[VALUE:%.*]] = load i32, ptr [[A:%.*]], align 4 +; CHECK-NEXT: br i1 [[CONDB:%.*]], label [[THENB:%.*]], label [[MERGEC:%.*]] +; CHECK: thenB: +; CHECK-NEXT: call void @maywritefunc() +; CHECK-NEXT: br label [[MERGEC]] +; CHECK: mergeC: +; CHECK-NEXT: br i1 [[CONDC:%.*]], label [[THENC:%.*]], label [[MERGED:%.*]] +; CHECK: thenC: +; CHECK-NEXT: store i32 [[VALUE]], ptr [[B]], align 4 +; CHECK-NEXT: br label [[MERGEC]] +; CHECK: mergeD: +; CHECK-NEXT: ret void +; +entry: + %value = load i32, ptr %a, align 4 + br label %mergeA +mergeA: + br i1 %condA, label %thenA, label %mergeB +thenA: + store i32 0, ptr %b + br label %mergeB +mergeB: + br i1 %condB, label %thenB, label %mergeC +thenB: + call void @maywritefunc() + br label %mergeC +mergeC: + br i1 %condC, label %thenC, label %mergeD +thenC: + store i32 %value, ptr %b + br label %mergeC +mergeD: + ret void +} From 1543488b3ec26503770cd0f2ed9c49003efe3fc7 Mon Sep 17 00:00:00 2001 From: John Lu Date: Thu, 17 Apr 2025 13:23:29 -0500 Subject: [PATCH 05/14] Undo changes in isSafeToMove. Save for later PR Signed-off-by: John Lu --- llvm/lib/Transforms/Scalar/Sink.cpp | 24 +- llvm/lib/Transforms/Scalar/f | 4043 +++++++++++++++++++++++++++ 2 files changed, 4062 insertions(+), 5 deletions(-) create mode 100644 llvm/lib/Transforms/Scalar/f diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp index 57ce0c8990f4a..9f0a7fddeb01a 100644 --- a/llvm/lib/Transforms/Scalar/Sink.cpp +++ b/llvm/lib/Transforms/Scalar/Sink.cpp @@ -44,20 +44,34 @@ static bool hasStoreConflict(Instruction *Inst, AliasAnalysis &AA, static bool isSafeToMove(Instruction *Inst, AliasAnalysis &AA, SmallPtrSetImpl &Stores) { + if (Inst->mayWriteToMemory()) { Stores.insert(Inst); return false; } + + if (LoadInst *L = dyn_cast(Inst)) { + MemoryLocation Loc = MemoryLocation::get(L); + for (Instruction *S : Stores) + if (isModSet(AA.getModRefInfo(S, Loc))) + return false; + } + if (Inst->isTerminator() || isa(Inst) || Inst->isEHPad() || Inst->mayThrow() || !Inst->willReturn()) return false; - // Convergent operations cannot be made control-dependent on additional - // values. - if (auto *Call = dyn_cast(Inst)) + + if (auto *Call = dyn_cast(Inst)) { + // Convergent operations cannot be made control-dependent on additional + // values. if (Call->isConvergent()) return false; - if (hasStoreConflict(Inst, AA, Stores)) - return false; + + for (Instruction *S : Stores) + if (isModSet(AA.getModRefInfo(S, Call))) + return false; + } + return true; } diff --git a/llvm/lib/Transforms/Scalar/f b/llvm/lib/Transforms/Scalar/f new file mode 100644 index 0000000000000..67810a3ca0a45 --- /dev/null +++ b/llvm/lib/Transforms/Scalar/f @@ -0,0 +1,4043 @@ +commit 36eeb25bcd0d8a4b85489413bc1b1757d89e988d +Author: John Lu +Date: Wed Apr 16 06:39:59 2025 -0500 + + Extend Sink pass to allow loads to be sunk to non-immediate successor blocks + + Signed-off-by: John Lu + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 1a48a59c4189..57ce0c8990f4 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -27,43 +27,71 @@ using namespace llvm; + STATISTIC(NumSunk, "Number of instructions sunk"); + STATISTIC(NumSinkIter, "Number of sinking iterations"); + +-static bool isSafeToMove(Instruction *Inst, AliasAnalysis &AA, +- SmallPtrSetImpl &Stores) { +- +- if (Inst->mayWriteToMemory()) { +- Stores.insert(Inst); +- return false; +- } +- ++static bool hasStoreConflict(Instruction *Inst, AliasAnalysis &AA, ++ SmallPtrSetImpl &Stores) { + if (LoadInst *L = dyn_cast(Inst)) { + MemoryLocation Loc = MemoryLocation::get(L); + for (Instruction *S : Stores) + if (isModSet(AA.getModRefInfo(S, Loc))) +- return false; ++ return true; ++ } else if (auto *Call = dyn_cast(Inst)) { ++ for (Instruction *S : Stores) ++ if (isModSet(AA.getModRefInfo(S, Call))) ++ return true; + } ++ return false; ++} + ++static bool isSafeToMove(Instruction *Inst, AliasAnalysis &AA, ++ SmallPtrSetImpl &Stores) { ++ if (Inst->mayWriteToMemory()) { ++ Stores.insert(Inst); ++ return false; ++ } + if (Inst->isTerminator() || isa(Inst) || Inst->isEHPad() || + Inst->mayThrow() || !Inst->willReturn()) + return false; +- +- if (auto *Call = dyn_cast(Inst)) { +- // Convergent operations cannot be made control-dependent on additional +- // values. ++ // Convergent operations cannot be made control-dependent on additional ++ // values. ++ if (auto *Call = dyn_cast(Inst)) + if (Call->isConvergent()) + return false; ++ if (hasStoreConflict(Inst, AA, Stores)) ++ return false; ++ return true; ++} + +- for (Instruction *S : Stores) +- if (isModSet(AA.getModRefInfo(S, Call))) +- return false; +- } ++typedef SmallPtrSet BlocksSet; ++static void findStores(SmallPtrSetImpl &Stores, ++ BasicBlock *LoadBB, BasicBlock *BB, ++ BlocksSet &VisitedBlocksSet) { ++ if (BB == LoadBB || VisitedBlocksSet.contains(BB)) ++ return; ++ VisitedBlocksSet.insert(BB); ++ ++ for (Instruction &Inst : *BB) ++ if (Inst.mayWriteToMemory()) ++ Stores.insert(&Inst); ++ for (BasicBlock *Pred : predecessors(BB)) ++ findStores(Stores, LoadBB, Pred, VisitedBlocksSet); ++} + +- return true; ++static bool hasConflictingStoreBeforeSuccToSinkTo(AliasAnalysis &AA, ++ Instruction *ReadMemInst, ++ BasicBlock *SuccToSinkTo) { ++ BlocksSet VisitedBlocksSet; ++ SmallPtrSet Stores; ++ BasicBlock *LoadBB = ReadMemInst->getParent(); ++ for (BasicBlock *Pred : predecessors(SuccToSinkTo)) ++ findStores(Stores, LoadBB, Pred, VisitedBlocksSet); ++ return hasStoreConflict(ReadMemInst, AA, Stores); + } + + /// IsAcceptableTarget - Return true if it is possible to sink the instruction + /// in the specified basic block. +-static bool IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo, +- DominatorTree &DT, LoopInfo &LI) { ++static bool IsAcceptableTarget(AliasAnalysis &AA, Instruction *Inst, ++ BasicBlock *SuccToSinkTo, DominatorTree &DT, ++ LoopInfo &LI) { + assert(Inst && "Instruction to be sunk is null"); + assert(SuccToSinkTo && "Candidate sink target is null"); + +@@ -76,10 +104,10 @@ static bool IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo, + // just punt. + // FIXME: Split critical edges if not backedges. + if (SuccToSinkTo->getUniquePredecessor() != Inst->getParent()) { +- // We cannot sink a load across a critical edge - there may be stores in +- // other code paths. ++ // Ensure that there is no conflicting store on any path to SuccToSinkTo. + if (Inst->mayReadFromMemory() && +- !Inst->hasMetadata(LLVMContext::MD_invariant_load)) ++ !Inst->hasMetadata(LLVMContext::MD_invariant_load) && ++ hasConflictingStoreBeforeSuccToSinkTo(AA, Inst, SuccToSinkTo)) + return false; + + // We don't want to sink across a critical edge if we don't dominate the +@@ -153,7 +181,7 @@ static bool SinkInstruction(Instruction *Inst, + // The nearest common dominator may be in a parent loop of BB, which may not + // be beneficial. Find an ancestor. + while (SuccToSinkTo != BB && +- !IsAcceptableTarget(Inst, SuccToSinkTo, DT, LI)) ++ !IsAcceptableTarget(AA, Inst, SuccToSinkTo, DT, LI)) + SuccToSinkTo = DT.getNode(SuccToSinkTo)->getIDom()->getBlock(); + if (SuccToSinkTo == BB) + SuccToSinkTo = nullptr; + +commit 8e702735090388a3231a863e343f880d0f96fecb +Author: Jeremy Morse +Date: Fri Jan 24 10:53:11 2025 +0000 + + [NFC][DebugInfo] Use iterator moveBefore at many call-sites (#123583) + + As part of the "RemoveDIs" project, BasicBlock::iterator now carries a + debug-info bit that's needed when getFirstNonPHI and similar feed into + instruction insertion positions. Call-sites where that's necessary were + updated a year ago; but to ensure some type safety however, we'd like to + have all calls to moveBefore use iterators. + + This patch adds a (guaranteed dereferenceable) iterator-taking + moveBefore, and changes a bunch of call-sites where it's obviously safe + to change to use it by just calling getIterator() on an instruction + pointer. A follow-up patch will contain less-obviously-safe changes. + + We'll eventually deprecate and remove the instruction-pointer + insertBefore, but not before adding concise documentation of what + considerations are needed (very few). + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 46bcfd6b41ce..1a48a59c4189 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -168,7 +168,7 @@ static bool SinkInstruction(Instruction *Inst, + SuccToSinkTo->printAsOperand(dbgs(), false); dbgs() << ")\n"); + + // Move the instruction. +- Inst->moveBefore(&*SuccToSinkTo->getFirstInsertionPt()); ++ Inst->moveBefore(SuccToSinkTo->getFirstInsertionPt()); + return true; + } + + +commit 2a2b426f13dfd33c7495da1c54ab9d1a8e625d87 +Author: XChy +Date: Mon Oct 9 22:34:44 2023 +0800 + + [Sink] Fix bugs of sinking unreachable BB from phi (#68576) + + Resolve #68529. + Sink pass doesn't consider whether Basicblock from phi is unreachable. + This patch moves unreachability check after checking phi. + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index ed768deacd06..46bcfd6b41ce 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -130,15 +130,16 @@ static bool SinkInstruction(Instruction *Inst, + for (Use &U : Inst->uses()) { + Instruction *UseInst = cast(U.getUser()); + BasicBlock *UseBlock = UseInst->getParent(); +- // Don't worry about dead users. +- if (!DT.isReachableFromEntry(UseBlock)) +- continue; + if (PHINode *PN = dyn_cast(UseInst)) { + // PHI nodes use the operand in the predecessor block, not the block with + // the PHI. + unsigned Num = PHINode::getIncomingValueNumForOperand(U.getOperandNo()); + UseBlock = PN->getIncomingBlock(Num); + } ++ // Don't worry about dead users. ++ if (!DT.isReachableFromEntry(UseBlock)) ++ continue; ++ + if (SuccToSinkTo) + SuccToSinkTo = DT.findNearestCommonDominator(SuccToSinkTo, UseBlock); + else + +commit 4eafc9b6ff4ae2bce82e9fdf0123b336825d931c +Author: Nikita Popov +Date: Wed Aug 23 15:04:45 2023 +0200 + + [IR] Treat callbr as special terminator (PR64215) + + isLegalToHoistInto() currently return true for callbr instructions. + That means that a callbr with one successor will be considered a + proper loop preheader, which may result in instructions that use + the callbr return value being hoisted past it. + + Fix this by adding callbr to isExceptionTerminator (with a rename + to isSpecialTerminator), which also fixes similar assumptions in + other places. + + Fixes https://github.com/llvm/llvm-project/issues/64215. + + Differential Revision: https://reviews.llvm.org/D158609 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 8b99f73b850b..ed768deacd06 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -67,9 +67,8 @@ static bool IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo, + assert(Inst && "Instruction to be sunk is null"); + assert(SuccToSinkTo && "Candidate sink target is null"); + +- // It's never legal to sink an instruction into a block which terminates in an +- // EH-pad. +- if (SuccToSinkTo->getTerminator()->isExceptionalTerminator()) ++ // It's never legal to sink an instruction into an EH-pad block. ++ if (SuccToSinkTo->isEHPad()) + return false; + + // If the block has multiple predecessors, this would introduce computation + +commit 6b852ffa9973015fb5deb6d859d980692387dcc7 +Author: Fangrui Song +Date: Fri Nov 18 01:23:12 2022 +0000 + + [Sink] Process basic blocks with a single successor + + This condition seems unnecessary. + + Reviewed By: arsenm + + Differential Revision: https://reviews.llvm.org/D93511 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index dad45c47e0c2..8b99f73b850b 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -174,9 +174,6 @@ static bool SinkInstruction(Instruction *Inst, + + static bool ProcessBlock(BasicBlock &BB, DominatorTree &DT, LoopInfo &LI, + AAResults &AA) { +- // Can't sink anything out of a block that has less than two successors. +- if (BB.getTerminator()->getNumSuccessors() <= 1) return false; +- + // Don't bother sinking code out of unreachable blocks. In addition to being + // unprofitable, it can also lead to infinite looping, because in an + // unreachable loop there may be nowhere to stop. + +commit c316332e1789221ec26875d1dc335382b6e68d83 +Author: Carl Ritson +Date: Thu Oct 6 09:06:32 2022 +0900 + + [Sink] Allow sinking of invariant loads across critical edges + + Invariant loads can always be sunk. + + Reviewed By: foad, arsenm + + Differential Revision: https://reviews.llvm.org/D135133 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index e8fde53005f0..dad45c47e0c2 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -79,7 +79,8 @@ static bool IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo, + if (SuccToSinkTo->getUniquePredecessor() != Inst->getParent()) { + // We cannot sink a load across a critical edge - there may be stores in + // other code paths. +- if (Inst->mayReadFromMemory()) ++ if (Inst->mayReadFromMemory() && ++ !Inst->hasMetadata(LLVMContext::MD_invariant_load)) + return false; + + // We don't want to sink across a critical edge if we don't dominate the + +commit e22af03a794d633915d0b51c15e05bb9cb9b4ec9 +Author: Nikita Popov +Date: Thu Apr 7 16:23:56 2022 +0200 + + [Sink] Don't sink non-willreturn calls (PR51188) + + Fixes https://github.com/llvm/llvm-project/issues/51188. + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index ac6f34aab415..e8fde53005f0 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -43,7 +43,7 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis &AA, + } + + if (Inst->isTerminator() || isa(Inst) || Inst->isEHPad() || +- Inst->mayThrow()) ++ Inst->mayThrow() || !Inst->willReturn()) + return false; + + if (auto *Call = dyn_cast(Inst)) { + +commit 59630917d6cc7c4a273f617f92bf6190ee2992e1 +Author: serge-sans-paille +Date: Wed Mar 2 16:38:19 2022 +0100 + + Cleanup includes: Transform/Scalar + + Estimated impact on preprocessor output line: + before: 1062981579 + after: 1062494547 + + Discourse thread: https://discourse.llvm.org/t/include-what-you-use-include-cleanup + Differential Revision: https://reviews.llvm.org/D120817 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 8600aacdb056..ac6f34aab415 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -15,12 +15,7 @@ + #include "llvm/ADT/Statistic.h" + #include "llvm/Analysis/AliasAnalysis.h" + #include "llvm/Analysis/LoopInfo.h" +-#include "llvm/Analysis/ValueTracking.h" +-#include "llvm/IR/CFG.h" +-#include "llvm/IR/DataLayout.h" + #include "llvm/IR/Dominators.h" +-#include "llvm/IR/IntrinsicInst.h" +-#include "llvm/IR/Module.h" + #include "llvm/InitializePasses.h" + #include "llvm/Support/Debug.h" + #include "llvm/Support/raw_ostream.h" + +commit 30bb5be38908b0006ed94124515e43774ee37915 +Author: Hongtao Yu +Date: Mon Apr 26 09:12:29 2021 -0700 + + [CSSPGO] Unblock optimizations with pseudo probe instrumentation part 2. + + As a follow-up to D95982, this patch continues unblocking optimizations that are blocked by pseudu probe instrumention. + + The optimizations unblocked are: + - In-block load propagation. + - In-block dead store elimination + - Memory copy optimization that turns stores to consecutive memories into a memset. + + These optimizations are local to a block, so they shouldn't affect the profile quality. + + Reviewed By: wmi + + Differential Revision: https://reviews.llvm.org/D100075 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 89cfbe384be4..8600aacdb056 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -202,7 +202,7 @@ static bool ProcessBlock(BasicBlock &BB, DominatorTree &DT, LoopInfo &LI, + if (!ProcessedBegin) + --I; + +- if (isa(Inst)) ++ if (Inst->isDebugOrPseudoInst()) + continue; + + if (SinkInstruction(Inst, Stores, DT, LI, AA)) { + +commit f192a27ed3bacdf727f27857adeb6d3762383295 +Author: Changpeng Fang +Date: Fri Oct 9 16:20:26 2020 -0700 + + Sink: Handle instruction sink when a user is dead + + Summary: + The current instruction sink pass uses findNearestCommonDominator of all users to find block to sink the instruction to. + However, a user may be in a dead block, which will result in unexpected behavior. + + This patch handles such cases by skipping dead blocks. This patch fixes: + https://bugs.llvm.org/show_bug.cgi?id=47415 + + Reviewers: + MaskRay, arsenm + + Differential Revision: + https://reviews.llvm.org/D89166 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index c430724ab1ac..89cfbe384be4 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -135,6 +135,9 @@ static bool SinkInstruction(Instruction *Inst, + for (Use &U : Inst->uses()) { + Instruction *UseInst = cast(U.getUser()); + BasicBlock *UseBlock = UseInst->getParent(); ++ // Don't worry about dead users. ++ if (!DT.isReachableFromEntry(UseBlock)) ++ continue; + if (PHINode *PN = dyn_cast(UseInst)) { + // PHI nodes use the operand in the predecessor block, not the block with + // the PHI. + +commit f2284e3405d87143b2478f28b8045bef84953c91 +Author: Fangrui Song +Date: Sun Aug 30 22:51:00 2020 -0700 + + [Sink] Optimize/simplify sink candidate finding with nearest common dominator + + For an instruction in the basic block BB, SinkingPass enumerates basic blocks + dominated by BB and BB's successors. For each enumerated basic block, + SinkingPass uses `AllUsesDominatedByBlock` to check whether the basic + block dominates all of the instruction's users. This is inefficient. + + Use the nearest common dominator of all users to avoid enumerating the + candidate. The nearest common dominator may be in a parent loop which is + not beneficial. In that case, find the ancestors in the dominator tree. + + In the case that the instruction has no user, with this change we will + not perform unnecessary move. This causes some amdgpu test changes. + + A stage-2 x86-64 clang is a byte identical with this change. + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 48f289c8f17d..c430724ab1ac 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -32,31 +32,6 @@ using namespace llvm; + STATISTIC(NumSunk, "Number of instructions sunk"); + STATISTIC(NumSinkIter, "Number of sinking iterations"); + +-/// AllUsesDominatedByBlock - Return true if all uses of the specified value +-/// occur in blocks dominated by the specified block. +-static bool AllUsesDominatedByBlock(Instruction *Inst, BasicBlock *BB, +- DominatorTree &DT) { +- // Ignoring debug uses is necessary so debug info doesn't affect the code. +- // This may leave a referencing dbg_value in the original block, before +- // the definition of the vreg. Dwarf generator handles this although the +- // user might not get the right info at runtime. +- for (Use &U : Inst->uses()) { +- // Determine the block of the use. +- Instruction *UseInst = cast(U.getUser()); +- BasicBlock *UseBlock = UseInst->getParent(); +- if (PHINode *PN = dyn_cast(UseInst)) { +- // PHI nodes use the operand in the predecessor block, not the block with +- // the PHI. +- unsigned Num = PHINode::getIncomingValueNumForOperand(U.getOperandNo()); +- UseBlock = PN->getIncomingBlock(Num); +- } +- // Check that it dominates. +- if (!DT.dominates(BB, UseBlock)) +- return false; +- } +- return true; +-} +- + static bool isSafeToMove(Instruction *Inst, AliasAnalysis &AA, + SmallPtrSetImpl &Stores) { + +@@ -97,11 +72,6 @@ static bool IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo, + assert(Inst && "Instruction to be sunk is null"); + assert(SuccToSinkTo && "Candidate sink target is null"); + +- // It is not possible to sink an instruction into its own block. This can +- // happen with loops. +- if (Inst->getParent() == SuccToSinkTo) +- return false; +- + // It's never legal to sink an instruction into a block which terminates in an + // EH-pad. + if (SuccToSinkTo->getTerminator()->isExceptionalTerminator()) +@@ -129,9 +99,7 @@ static bool IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo, + return false; + } + +- // Finally, check that all the uses of the instruction are actually +- // dominated by the candidate +- return AllUsesDominatedByBlock(Inst, SuccToSinkTo, DT); ++ return true; + } + + /// SinkInstruction - Determine whether it is safe to sink the specified machine +@@ -162,25 +130,34 @@ static bool SinkInstruction(Instruction *Inst, + // decide. + BasicBlock *SuccToSinkTo = nullptr; + +- // Instructions can only be sunk if all their uses are in blocks +- // dominated by one of the successors. +- // Look at all the dominated blocks and see if we can sink it in one. +- DomTreeNode *DTN = DT.getNode(Inst->getParent()); +- for (auto I = DTN->begin(), E = DTN->end(); I != E && SuccToSinkTo == nullptr; +- ++I) { +- BasicBlock *Candidate = (*I)->getBlock(); +- // A node always immediate-dominates its children on the dominator +- // tree. +- if (IsAcceptableTarget(Inst, Candidate, DT, LI)) +- SuccToSinkTo = Candidate; ++ // Find the nearest common dominator of all users as the candidate. ++ BasicBlock *BB = Inst->getParent(); ++ for (Use &U : Inst->uses()) { ++ Instruction *UseInst = cast(U.getUser()); ++ BasicBlock *UseBlock = UseInst->getParent(); ++ if (PHINode *PN = dyn_cast(UseInst)) { ++ // PHI nodes use the operand in the predecessor block, not the block with ++ // the PHI. ++ unsigned Num = PHINode::getIncomingValueNumForOperand(U.getOperandNo()); ++ UseBlock = PN->getIncomingBlock(Num); ++ } ++ if (SuccToSinkTo) ++ SuccToSinkTo = DT.findNearestCommonDominator(SuccToSinkTo, UseBlock); ++ else ++ SuccToSinkTo = UseBlock; ++ // The current basic block needs to dominate the candidate. ++ if (!DT.dominates(BB, SuccToSinkTo)) ++ return false; + } + +- // If no suitable postdominator was found, look at all the successors and +- // decide which one we should sink to, if any. +- for (succ_iterator I = succ_begin(Inst->getParent()), +- E = succ_end(Inst->getParent()); I != E && !SuccToSinkTo; ++I) { +- if (IsAcceptableTarget(Inst, *I, DT, LI)) +- SuccToSinkTo = *I; ++ if (SuccToSinkTo) { ++ // The nearest common dominator may be in a parent loop of BB, which may not ++ // be beneficial. Find an ancestor. ++ while (SuccToSinkTo != BB && ++ !IsAcceptableTarget(Inst, SuccToSinkTo, DT, LI)) ++ SuccToSinkTo = DT.getNode(SuccToSinkTo)->getIDom()->getBlock(); ++ if (SuccToSinkTo == BB) ++ SuccToSinkTo = nullptr; + } + + // If we couldn't find a block to sink to, ignore this instruction. + +commit 3fa989d4fd6b854209ba4e950d96b91d6d5797b4 +Author: Nicolai Hähnle +Date: Thu Jul 2 20:36:30 2020 +0200 + + DomTree: remove explicit use of DomTreeNodeBase::iterator + + Summary: + Almost all uses of these iterators, including implicit ones, really + only need the const variant (as it should be). The only exception is + in NewGVN, which changes the order of dominator tree child nodes. + + Change-Id: I4b5bd71e32d71b0c67b03d4927d93fe9413726d4 + + Reviewers: arsenm, RKSimon, mehdi_amini, courbet, rriddle, aartbik + + Subscribers: wdng, Prazek, hiraditya, kuhar, rogfer01, rriddle, jpienaar, shauheen, antiagainst, nicolasvasilache, arpith-jacob, mgester, lucyrfox, aartbik, liufengdb, stephenneuendorffer, Joonsoo, grosul1, vkmr, Kayjukh, jurahul, msifontes, cfe-commits, llvm-commits + + Tags: #clang, #mlir, #llvm + + Differential Revision: https://reviews.llvm.org/D83087 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 677d86f8c7b4..48f289c8f17d 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -166,8 +166,8 @@ static bool SinkInstruction(Instruction *Inst, + // dominated by one of the successors. + // Look at all the dominated blocks and see if we can sink it in one. + DomTreeNode *DTN = DT.getNode(Inst->getParent()); +- for (DomTreeNode::iterator I = DTN->begin(), E = DTN->end(); +- I != E && SuccToSinkTo == nullptr; ++I) { ++ for (auto I = DTN->begin(), E = DTN->end(); I != E && SuccToSinkTo == nullptr; ++ ++I) { + BasicBlock *Candidate = (*I)->getBlock(); + // A node always immediate-dominates its children on the dominator + // tree. + +commit 05da2fe52162c80dfa18aedf70cf73cb11201811 +Author: Reid Kleckner +Date: Wed Nov 13 13:15:01 2019 -0800 + + Sink all InitializePasses.h includes + + This file lists every pass in LLVM, and is included by Pass.h, which is + very popular. Every time we add, remove, or rename a pass in LLVM, it + caused lots of recompilation. + + I found this fact by looking at this table, which is sorted by the + number of times a file was changed over the last 100,000 git commits + multiplied by the number of object files that depend on it in the + current checkout: + recompiles touches affected_files header + 342380 95 3604 llvm/include/llvm/ADT/STLExtras.h + 314730 234 1345 llvm/include/llvm/InitializePasses.h + 307036 118 2602 llvm/include/llvm/ADT/APInt.h + 213049 59 3611 llvm/include/llvm/Support/MathExtras.h + 170422 47 3626 llvm/include/llvm/Support/Compiler.h + 162225 45 3605 llvm/include/llvm/ADT/Optional.h + 158319 63 2513 llvm/include/llvm/ADT/Triple.h + 140322 39 3598 llvm/include/llvm/ADT/StringRef.h + 137647 59 2333 llvm/include/llvm/Support/Error.h + 131619 73 1803 llvm/include/llvm/Support/FileSystem.h + + Before this change, touching InitializePasses.h would cause 1345 files + to recompile. After this change, touching it only causes 550 compiles in + an incremental rebuild. + + Reviewers: bkramer, asbirlea, bollu, jdoerfert + + Differential Revision: https://reviews.llvm.org/D70211 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 72b586c85fe1..677d86f8c7b4 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -21,6 +21,7 @@ + #include "llvm/IR/Dominators.h" + #include "llvm/IR/IntrinsicInst.h" + #include "llvm/IR/Module.h" ++#include "llvm/InitializePasses.h" + #include "llvm/Support/Debug.h" + #include "llvm/Support/raw_ostream.h" + #include "llvm/Transforms/Scalar.h" + +commit 9b0b626d2c19802bf3d56272cbc3a13d3c9ee5dd +Author: Matt Arsenault +Date: Sun Oct 27 19:37:45 2019 -0700 + + Use isConvergent helper instead of directly checking attribute + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 90f3a2aa46e1..72b586c85fe1 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -78,7 +78,7 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis &AA, + if (auto *Call = dyn_cast(Inst)) { + // Convergent operations cannot be made control-dependent on additional + // values. +- if (Call->hasFnAttr(Attribute::Convergent)) ++ if (Call->isConvergent()) + return false; + + for (Instruction *S : Stores) + +commit 2946cd701067404b99c39fb29dc9c74bd7193eb3 +Author: Chandler Carruth +Date: Sat Jan 19 08:50:56 2019 +0000 + + Update the file headers across all of the LLVM projects in the monorepo + to reflect the new license. + + We understand that people may be surprised that we're moving the header + entirely to discuss the new license. We checked this carefully with the + Foundation's lawyer and we believe this is the correct approach. + + Essentially, all code in the project is now made available by the LLVM + project under our new license, so you will see that the license headers + include that license only. Some of our contributors have contributed + code under our old license, and accordingly, we have retained a copy of + our old license notice in the top-level files in each project and + repository. + + llvm-svn: 351636 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index c99da8f0737a..90f3a2aa46e1 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -1,9 +1,8 @@ + //===-- Sink.cpp - Code Sinking -------------------------------------------===// + // +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. ++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. ++// See https://llvm.org/LICENSE.txt for license information. ++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + // + //===----------------------------------------------------------------------===// + // + +commit 363ac6837427ffc6adcc68c44788bb4d92d52873 +Author: Chandler Carruth +Date: Mon Jan 7 05:42:51 2019 +0000 + + [CallSite removal] Migrate all Alias Analysis APIs to use the newly + minted `CallBase` class instead of the `CallSite` wrapper. + + This moves the largest interwoven collection of APIs that traffic in + `CallSite`s. While a handful of these could have been migrated with + a minorly more shallow migration by converting from a `CallSite` to + a `CallBase`, it hardly seemed worth it. Most of the APIs needed to + migrate together because of the complex interplay of AA APIs and the + fact that converting from a `CallBase` to a `CallSite` isn't free in its + current implementation. + + Out of tree users of these APIs can fairly reliably migrate with some + combination of `.getInstruction()` on the `CallSite` instance and + casting the resulting pointer. The most generic form will look like `CS` + -> `cast_or_null(CS.getInstruction())` but in most cases there + is a more elegant migration. Hopefully, this migrates enough APIs for + users to fully move from `CallSite` to the base class. All of the + in-tree users were easily migrated in that fashion. + + Thanks for the review from Saleem! + + Differential Revision: https://reviews.llvm.org/D55641 + + llvm-svn: 350503 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index d1cdfabb0cc4..c99da8f0737a 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -76,14 +76,14 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis &AA, + Inst->mayThrow()) + return false; + +- if (auto CS = CallSite(Inst)) { ++ if (auto *Call = dyn_cast(Inst)) { + // Convergent operations cannot be made control-dependent on additional + // values. +- if (CS.hasFnAttr(Attribute::Convergent)) ++ if (Call->hasFnAttr(Attribute::Convergent)) + return false; + + for (Instruction *S : Stores) +- if (isModSet(AA.getModRefInfo(S, CS))) ++ if (isModSet(AA.getModRefInfo(S, Call))) + return false; + } + + +commit 9ae926b973e42633f7bc7db39b33241dbb9f2158 +Author: Chandler Carruth +Date: Sun Aug 26 09:51:22 2018 +0000 + + [IR] Replace `isa` with `isTerminator()`. + + This is a bit awkward in a handful of places where we didn't even have + an instruction and now we have to see if we can build one. But on the + whole, this seems like a win and at worst a reasonable cost for removing + `TerminatorInst`. + + All of this is part of the removal of `TerminatorInst` from the + `Instruction` type hierarchy. + + llvm-svn: 340701 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index b59d52f2ecff..d1cdfabb0cc4 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -72,7 +72,7 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis &AA, + return false; + } + +- if (isa(Inst) || isa(Inst) || Inst->isEHPad() || ++ if (Inst->isTerminator() || isa(Inst) || Inst->isEHPad() || + Inst->mayThrow()) + return false; + + +commit 698fbe7b59a77888f108fbfe37e17a1db0cace8c +Author: Chandler Carruth +Date: Sun Aug 26 08:56:42 2018 +0000 + + [IR] Sink `isExceptional` predicate to `Instruction`, rename it to + `isExceptionalTermiantor` and implement it for opcodes as well following + the common pattern in `Instruction`. + + Part of removing `TerminatorInst` from the `Instruction` type hierarchy + to make it easier to share logic and interfaces between instructions + that are both terminators and not terminators. + + llvm-svn: 340699 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index ca6b93e0b4a9..b59d52f2ecff 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -104,7 +104,7 @@ static bool IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo, + + // It's never legal to sink an instruction into a block which terminates in an + // EH-pad. +- if (SuccToSinkTo->getTerminator()->isExceptional()) ++ if (SuccToSinkTo->getTerminator()->isExceptionalTerminator()) + return false; + + // If the block has multiple predecessors, this would introduce computation + +commit d34e60ca8532511acb8c93ef26297e349fbec86a +Author: Nicola Zaghen +Date: Mon May 14 12:53:11 2018 +0000 + + Rename DEBUG macro to LLVM_DEBUG. + + The DEBUG() macro is very generic so it might clash with other projects. + The renaming was done as follows: + - git grep -l 'DEBUG' | xargs sed -i 's/\bDEBUG\s\?(/LLVM_DEBUG(/g' + - git diff -U0 master | ../clang/tools/clang-format/clang-format-diff.py -i -p1 -style LLVM + - Manual change to APInt + - Manually chage DOCS as regex doesn't match it. + + In the transition period the DEBUG() macro is still present and aliased + to the LLVM_DEBUG() one. + + Differential Revision: https://reviews.llvm.org/D43624 + + llvm-svn: 332240 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 811762880493..ca6b93e0b4a9 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -187,11 +187,9 @@ static bool SinkInstruction(Instruction *Inst, + if (!SuccToSinkTo) + return false; + +- DEBUG(dbgs() << "Sink" << *Inst << " ("; +- Inst->getParent()->printAsOperand(dbgs(), false); +- dbgs() << " -> "; +- SuccToSinkTo->printAsOperand(dbgs(), false); +- dbgs() << ")\n"); ++ LLVM_DEBUG(dbgs() << "Sink" << *Inst << " ("; ++ Inst->getParent()->printAsOperand(dbgs(), false); dbgs() << " -> "; ++ SuccToSinkTo->printAsOperand(dbgs(), false); dbgs() << ")\n"); + + // Move the instruction. + Inst->moveBefore(&*SuccToSinkTo->getFirstInsertionPt()); +@@ -244,7 +242,7 @@ static bool iterativelySinkInstructions(Function &F, DominatorTree &DT, + + do { + MadeChange = false; +- DEBUG(dbgs() << "Sinking iteration " << NumSinkIter << "\n"); ++ LLVM_DEBUG(dbgs() << "Sinking iteration " << NumSinkIter << "\n"); + // Process all basic blocks. + for (BasicBlock &I : F) + MadeChange |= ProcessBlock(I, DT, LI, AA); + +commit efe6a84e5b5015326ee0825e275bc929f8afee5f +Author: Fiona Glaser +Date: Thu Jan 11 21:28:57 2018 +0000 + + [Sink] Really really fix predicate in legality check + + LoadInst isn't enough; we need to include intrinsics that perform loads too. + + All side-effecting intrinsics and such are already covered by the isSafe + check, so we just need to care about things that read from memory. + + D41960, originally from D33179. + + llvm-svn: 322311 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index cfb8a062299f..811762880493 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -114,7 +114,7 @@ static bool IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo, + if (SuccToSinkTo->getUniquePredecessor() != Inst->getParent()) { + // We cannot sink a load across a critical edge - there may be stores in + // other code paths. +- if (isa(Inst)) ++ if (Inst->mayReadFromMemory()) + return false; + + // We don't want to sink across a critical edge if we don't dominate the + +commit 63d2250a42b7b1e35e747ab07e181d2d8ec86dbc +Author: Alina Sbirlea +Date: Tue Dec 5 20:12:23 2017 +0000 + + Modify ModRefInfo values using static inline method abstractions [NFC]. + + Summary: + The aim is to make ModRefInfo checks and changes more intuitive + and less error prone using inline methods that abstract the bit operations. + + Ideally ModRefInfo would become an enum class, but that change will require + a wider set of changes into FunctionModRefBehavior. + + Reviewers: sanjoy, george.burgess.iv, dberlin, hfinkel + + Subscribers: nlopes, llvm-commits + + Differential Revision: https://reviews.llvm.org/D40749 + + llvm-svn: 319821 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 5210f165b874..cfb8a062299f 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -68,7 +68,7 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis &AA, + if (LoadInst *L = dyn_cast(Inst)) { + MemoryLocation Loc = MemoryLocation::get(L); + for (Instruction *S : Stores) +- if (AA.getModRefInfo(S, Loc) & MRI_Mod) ++ if (isModSet(AA.getModRefInfo(S, Loc))) + return false; + } + +@@ -83,7 +83,7 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis &AA, + return false; + + for (Instruction *S : Stores) +- if (AA.getModRefInfo(S, CS) & MRI_Mod) ++ if (isModSet(AA.getModRefInfo(S, CS))) + return false; + } + + +commit 5329174cb1b32bb34b90f1fdd5525ed84716ecec +Author: Keno Fischer +Date: Fri Jun 9 19:31:10 2017 +0000 + + [Sink] Fix predicate in legality check + + Summary: + isSafeToSpeculativelyExecute is the wrong predicate to use here. + All that checks for is whether it is safe to hoist a value due to + unaligned/un-dereferencable accesses. However, not only are we doing + sinking rather than hoisting, our concern is that the location + we're loading from may have been modified. Instead forbid sinking + any load across a critical edge. + + Reviewers: majnemer + + Subscribers: davide, llvm-commits + + Differential Revision: https://reviews.llvm.org/D33179 + + llvm-svn: 305102 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 102e9eaeab77..5210f165b874 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -114,7 +114,7 @@ static bool IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo, + if (SuccToSinkTo->getUniquePredecessor() != Inst->getParent()) { + // We cannot sink a load across a critical edge - there may be stores in + // other code paths. +- if (!isSafeToSpeculativelyExecute(Inst)) ++ if (isa(Inst)) + return false; + + // We don't want to sink across a critical edge if we don't dominate the + +commit cbf04d95e6295cc35d85490fb03f7c83e9180dc5 +Author: Xin Tong +Date: Mon Mar 20 00:30:19 2017 +0000 + + Remove unnecessary IDom check + + Summary: This Idom check seems unnecessary. The immediate children of a node on the Dominator Tree should always be the IDom of its immediate children in this case. + + Reviewers: hfinkel, majnemer, dberlin + + Reviewed By: dberlin + + Subscribers: dberlin, davide, llvm-commits + + Differential Revision: https://reviews.llvm.org/D26954 + + llvm-svn: 298232 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 504a22a229c8..102e9eaeab77 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -164,13 +164,14 @@ static bool SinkInstruction(Instruction *Inst, + + // Instructions can only be sunk if all their uses are in blocks + // dominated by one of the successors. +- // Look at all the postdominators and see if we can sink it in one. ++ // Look at all the dominated blocks and see if we can sink it in one. + DomTreeNode *DTN = DT.getNode(Inst->getParent()); + for (DomTreeNode::iterator I = DTN->begin(), E = DTN->end(); + I != E && SuccToSinkTo == nullptr; ++I) { + BasicBlock *Candidate = (*I)->getBlock(); +- if ((*I)->getIDom()->getBlock() == Inst->getParent() && +- IsAcceptableTarget(Inst, Candidate, DT, LI)) ++ // A node always immediate-dominates its children on the dominator ++ // tree. ++ if (IsAcceptableTarget(Inst, Candidate, DT, LI)) + SuccToSinkTo = Candidate; + } + + +commit ca68a3ec47416185252b84d2bf60710c88be155f +Author: Chandler Carruth +Date: Sun Jan 15 06:32:49 2017 +0000 + + [PM] Introduce an analysis set used to preserve all analyses over + a function's CFG when that CFG is unchanged. + + This allows transformation passes to simply claim they preserve the CFG + and analysis passes to check for the CFG being preserved to remove the + fanout of all analyses being listed in all passes. + + I've gone through and removed or cleaned up as many of the comments + reminding us to do this as I could. + + Differential Revision: https://reviews.llvm.org/D28627 + + llvm-svn: 292054 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index c3f14a0f4b1e..504a22a229c8 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -262,9 +262,8 @@ PreservedAnalyses SinkingPass::run(Function &F, FunctionAnalysisManager &AM) { + if (!iterativelySinkInstructions(F, DT, LI, AA)) + return PreservedAnalyses::all(); + +- auto PA = PreservedAnalyses(); +- PA.preserve(); +- PA.preserve(); ++ PreservedAnalyses PA; ++ PA.preserveSet(); + return PA; + } + + +commit 36e0d01e13b32bf318139fd8c43849af7a0e13cc +Author: Sean Silva +Date: Tue Aug 9 00:28:15 2016 +0000 + + Consistently use FunctionAnalysisManager + + Besides a general consistently benefit, the extra layer of indirection + allows the mechanical part of https://reviews.llvm.org/D23256 that + requires touching every transformation and analysis to be factored out + cleanly. + + Thanks to David for the suggestion. + + llvm-svn: 278077 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index d9a296c63122..c3f14a0f4b1e 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -254,7 +254,7 @@ static bool iterativelySinkInstructions(Function &F, DominatorTree &DT, + return EverMadeChange; + } + +-PreservedAnalyses SinkingPass::run(Function &F, AnalysisManager &AM) { ++PreservedAnalyses SinkingPass::run(Function &F, FunctionAnalysisManager &AM) { + auto &DT = AM.getResult(F); + auto &LI = AM.getResult(F); + auto &AA = AM.getResult(F); + +commit 889a20cf40c8e61a62e32bef38a0abea6194d6f1 +Author: Nicolai Haehnle +Date: Mon Jul 11 14:11:51 2016 +0000 + + [Sink] Don't move calls to readonly functions across stores + + Summary: + + Reviewers: hfinkel, majnemer, tstellarAMD, sunfish + + Subscribers: llvm-commits + + Differential Revision: http://reviews.llvm.org/D17279 + + llvm-svn: 275066 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 5fa43bda9d09..d9a296c63122 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -76,11 +76,15 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis &AA, + Inst->mayThrow()) + return false; + +- // Convergent operations cannot be made control-dependent on additional +- // values. + if (auto CS = CallSite(Inst)) { ++ // Convergent operations cannot be made control-dependent on additional ++ // values. + if (CS.hasFnAttr(Attribute::Convergent)) + return false; ++ ++ for (Instruction *S : Stores) ++ if (AA.getModRefInfo(S, CS) & MRI_Mod) ++ return false; + } + + return true; + +commit 135f735af149e305635ba3886065b493d5c2bf8c +Author: Benjamin Kramer +Date: Sun Jun 26 12:28:59 2016 +0000 + + Apply clang-tidy's modernize-loop-convert to most of lib/Transforms. + + Only minor manual fixes. No functionality change intended. + + llvm-svn: 273808 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index c5f29fa99dc8..5fa43bda9d09 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -241,9 +241,8 @@ static bool iterativelySinkInstructions(Function &F, DominatorTree &DT, + MadeChange = false; + DEBUG(dbgs() << "Sinking iteration " << NumSinkIter << "\n"); + // Process all basic blocks. +- for (Function::iterator I = F.begin(), E = F.end(); +- I != E; ++I) +- MadeChange |= ProcessBlock(*I, DT, LI, AA); ++ for (BasicBlock &I : F) ++ MadeChange |= ProcessBlock(I, DT, LI, AA); + EverMadeChange |= MadeChange; + NumSinkIter++; + } while (MadeChange); + +commit b93949089e8cd8e192c0293811f9cbd801af27b6 +Author: Justin Bogner +Date: Fri Apr 22 19:54:10 2016 +0000 + + PM: Port SinkingPass to the new pass manager + + llvm-svn: 267199 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index e5860328d04f..c5f29fa99dc8 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -12,7 +12,7 @@ + // + //===----------------------------------------------------------------------===// + +-#include "llvm/Transforms/Scalar.h" ++#include "llvm/Transforms/Scalar/Sink.h" + #include "llvm/ADT/Statistic.h" + #include "llvm/Analysis/AliasAnalysis.h" + #include "llvm/Analysis/LoopInfo.h" +@@ -24,6 +24,7 @@ + #include "llvm/IR/Module.h" + #include "llvm/Support/Debug.h" + #include "llvm/Support/raw_ostream.h" ++#include "llvm/Transforms/Scalar.h" + using namespace llvm; + + #define DEBUG_TYPE "sink" +@@ -31,50 +32,10 @@ using namespace llvm; + STATISTIC(NumSunk, "Number of instructions sunk"); + STATISTIC(NumSinkIter, "Number of sinking iterations"); + +-namespace { +- class Sinking : public FunctionPass { +- DominatorTree *DT; +- LoopInfo *LI; +- AliasAnalysis *AA; +- +- public: +- static char ID; // Pass identification +- Sinking() : FunctionPass(ID) { +- initializeSinkingPass(*PassRegistry::getPassRegistry()); +- } +- +- bool runOnFunction(Function &F) override; +- +- void getAnalysisUsage(AnalysisUsage &AU) const override { +- AU.setPreservesCFG(); +- FunctionPass::getAnalysisUsage(AU); +- AU.addRequired(); +- AU.addRequired(); +- AU.addRequired(); +- AU.addPreserved(); +- AU.addPreserved(); +- } +- private: +- bool ProcessBlock(BasicBlock &BB); +- bool SinkInstruction(Instruction *I, SmallPtrSetImpl &Stores); +- bool AllUsesDominatedByBlock(Instruction *Inst, BasicBlock *BB) const; +- bool IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo) const; +- }; +-} // end anonymous namespace +- +-char Sinking::ID = 0; +-INITIALIZE_PASS_BEGIN(Sinking, "sink", "Code sinking", false, false) +-INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) +-INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) +-INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass) +-INITIALIZE_PASS_END(Sinking, "sink", "Code sinking", false, false) +- +-FunctionPass *llvm::createSinkingPass() { return new Sinking(); } +- + /// AllUsesDominatedByBlock - Return true if all uses of the specified value + /// occur in blocks dominated by the specified block. +-bool Sinking::AllUsesDominatedByBlock(Instruction *Inst, +- BasicBlock *BB) const { ++static bool AllUsesDominatedByBlock(Instruction *Inst, BasicBlock *BB, ++ DominatorTree &DT) { + // Ignoring debug uses is necessary so debug info doesn't affect the code. + // This may leave a referencing dbg_value in the original block, before + // the definition of the vreg. Dwarf generator handles this although the +@@ -90,13 +51,13 @@ bool Sinking::AllUsesDominatedByBlock(Instruction *Inst, + UseBlock = PN->getIncomingBlock(Num); + } + // Check that it dominates. +- if (!DT->dominates(BB, UseBlock)) ++ if (!DT.dominates(BB, UseBlock)) + return false; + } + return true; + } + +-static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, ++static bool isSafeToMove(Instruction *Inst, AliasAnalysis &AA, + SmallPtrSetImpl &Stores) { + + if (Inst->mayWriteToMemory()) { +@@ -107,7 +68,7 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, + if (LoadInst *L = dyn_cast(Inst)) { + MemoryLocation Loc = MemoryLocation::get(L); + for (Instruction *S : Stores) +- if (AA->getModRefInfo(S, Loc) & MRI_Mod) ++ if (AA.getModRefInfo(S, Loc) & MRI_Mod) + return false; + } + +@@ -127,8 +88,8 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, + + /// IsAcceptableTarget - Return true if it is possible to sink the instruction + /// in the specified basic block. +-bool Sinking::IsAcceptableTarget(Instruction *Inst, +- BasicBlock *SuccToSinkTo) const { ++static bool IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo, ++ DominatorTree &DT, LoopInfo &LI) { + assert(Inst && "Instruction to be sunk is null"); + assert(SuccToSinkTo && "Candidate sink target is null"); + +@@ -154,25 +115,26 @@ bool Sinking::IsAcceptableTarget(Instruction *Inst, + + // We don't want to sink across a critical edge if we don't dominate the + // successor. We could be introducing calculations to new code paths. +- if (!DT->dominates(Inst->getParent(), SuccToSinkTo)) ++ if (!DT.dominates(Inst->getParent(), SuccToSinkTo)) + return false; + + // Don't sink instructions into a loop. +- Loop *succ = LI->getLoopFor(SuccToSinkTo); +- Loop *cur = LI->getLoopFor(Inst->getParent()); ++ Loop *succ = LI.getLoopFor(SuccToSinkTo); ++ Loop *cur = LI.getLoopFor(Inst->getParent()); + if (succ != nullptr && succ != cur) + return false; + } + + // Finally, check that all the uses of the instruction are actually + // dominated by the candidate +- return AllUsesDominatedByBlock(Inst, SuccToSinkTo); ++ return AllUsesDominatedByBlock(Inst, SuccToSinkTo, DT); + } + + /// SinkInstruction - Determine whether it is safe to sink the specified machine + /// instruction out of its current block into a successor. +-bool Sinking::SinkInstruction(Instruction *Inst, +- SmallPtrSetImpl &Stores) { ++static bool SinkInstruction(Instruction *Inst, ++ SmallPtrSetImpl &Stores, ++ DominatorTree &DT, LoopInfo &LI, AAResults &AA) { + + // Don't sink static alloca instructions. CodeGen assumes allocas outside the + // entry block are dynamically sized stack objects. +@@ -199,12 +161,12 @@ bool Sinking::SinkInstruction(Instruction *Inst, + // Instructions can only be sunk if all their uses are in blocks + // dominated by one of the successors. + // Look at all the postdominators and see if we can sink it in one. +- DomTreeNode *DTN = DT->getNode(Inst->getParent()); ++ DomTreeNode *DTN = DT.getNode(Inst->getParent()); + for (DomTreeNode::iterator I = DTN->begin(), E = DTN->end(); + I != E && SuccToSinkTo == nullptr; ++I) { + BasicBlock *Candidate = (*I)->getBlock(); + if ((*I)->getIDom()->getBlock() == Inst->getParent() && +- IsAcceptableTarget(Inst, Candidate)) ++ IsAcceptableTarget(Inst, Candidate, DT, LI)) + SuccToSinkTo = Candidate; + } + +@@ -212,7 +174,7 @@ bool Sinking::SinkInstruction(Instruction *Inst, + // decide which one we should sink to, if any. + for (succ_iterator I = succ_begin(Inst->getParent()), + E = succ_end(Inst->getParent()); I != E && !SuccToSinkTo; ++I) { +- if (IsAcceptableTarget(Inst, *I)) ++ if (IsAcceptableTarget(Inst, *I, DT, LI)) + SuccToSinkTo = *I; + } + +@@ -231,14 +193,15 @@ bool Sinking::SinkInstruction(Instruction *Inst, + return true; + } + +-bool Sinking::ProcessBlock(BasicBlock &BB) { ++static bool ProcessBlock(BasicBlock &BB, DominatorTree &DT, LoopInfo &LI, ++ AAResults &AA) { + // Can't sink anything out of a block that has less than two successors. + if (BB.getTerminator()->getNumSuccessors() <= 1) return false; + + // Don't bother sinking code out of unreachable blocks. In addition to being + // unprofitable, it can also lead to infinite looping, because in an + // unreachable loop there may be nowhere to stop. +- if (!DT->isReachableFromEntry(&BB)) return false; ++ if (!DT.isReachableFromEntry(&BB)) return false; + + bool MadeChange = false; + +@@ -259,7 +222,7 @@ bool Sinking::ProcessBlock(BasicBlock &BB) { + if (isa(Inst)) + continue; + +- if (SinkInstruction(Inst, Stores)) { ++ if (SinkInstruction(Inst, Stores, DT, LI, AA)) { + ++NumSunk; + MadeChange = true; + } +@@ -270,11 +233,8 @@ bool Sinking::ProcessBlock(BasicBlock &BB) { + return MadeChange; + } + +-bool Sinking::runOnFunction(Function &F) { +- DT = &getAnalysis().getDomTree(); +- LI = &getAnalysis().getLoopInfo(); +- AA = &getAnalysis().getAAResults(); +- ++static bool iterativelySinkInstructions(Function &F, DominatorTree &DT, ++ LoopInfo &LI, AAResults &AA) { + bool MadeChange, EverMadeChange = false; + + do { +@@ -283,10 +243,61 @@ bool Sinking::runOnFunction(Function &F) { + // Process all basic blocks. + for (Function::iterator I = F.begin(), E = F.end(); + I != E; ++I) +- MadeChange |= ProcessBlock(*I); ++ MadeChange |= ProcessBlock(*I, DT, LI, AA); + EverMadeChange |= MadeChange; + NumSinkIter++; + } while (MadeChange); + + return EverMadeChange; + } ++ ++PreservedAnalyses SinkingPass::run(Function &F, AnalysisManager &AM) { ++ auto &DT = AM.getResult(F); ++ auto &LI = AM.getResult(F); ++ auto &AA = AM.getResult(F); ++ ++ if (!iterativelySinkInstructions(F, DT, LI, AA)) ++ return PreservedAnalyses::all(); ++ ++ auto PA = PreservedAnalyses(); ++ PA.preserve(); ++ PA.preserve(); ++ return PA; ++} ++ ++namespace { ++ class SinkingLegacyPass : public FunctionPass { ++ public: ++ static char ID; // Pass identification ++ SinkingLegacyPass() : FunctionPass(ID) { ++ initializeSinkingLegacyPassPass(*PassRegistry::getPassRegistry()); ++ } ++ ++ bool runOnFunction(Function &F) override { ++ auto &DT = getAnalysis().getDomTree(); ++ auto &LI = getAnalysis().getLoopInfo(); ++ auto &AA = getAnalysis().getAAResults(); ++ ++ return iterativelySinkInstructions(F, DT, LI, AA); ++ } ++ ++ void getAnalysisUsage(AnalysisUsage &AU) const override { ++ AU.setPreservesCFG(); ++ FunctionPass::getAnalysisUsage(AU); ++ AU.addRequired(); ++ AU.addRequired(); ++ AU.addRequired(); ++ AU.addPreserved(); ++ AU.addPreserved(); ++ } ++ }; ++} // end anonymous namespace ++ ++char SinkingLegacyPass::ID = 0; ++INITIALIZE_PASS_BEGIN(SinkingLegacyPass, "sink", "Code sinking", false, false) ++INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) ++INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) ++INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass) ++INITIALIZE_PASS_END(SinkingLegacyPass, "sink", "Code sinking", false, false) ++ ++FunctionPass *llvm::createSinkingPass() { return new SinkingLegacyPass(); } + +commit 82077c4ab0b05980492f14b9cf31f6a4af35da34 +Author: Justin Bogner +Date: Fri Apr 22 19:54:04 2016 +0000 + + PM: Reorder the functions used for SinkingPass. NFC + + This will make the port to the new PM easier to follow. + + llvm-svn: 267198 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index eb09f584dc68..e5860328d04f 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -96,66 +96,6 @@ bool Sinking::AllUsesDominatedByBlock(Instruction *Inst, + return true; + } + +-bool Sinking::runOnFunction(Function &F) { +- DT = &getAnalysis().getDomTree(); +- LI = &getAnalysis().getLoopInfo(); +- AA = &getAnalysis().getAAResults(); +- +- bool MadeChange, EverMadeChange = false; +- +- do { +- MadeChange = false; +- DEBUG(dbgs() << "Sinking iteration " << NumSinkIter << "\n"); +- // Process all basic blocks. +- for (Function::iterator I = F.begin(), E = F.end(); +- I != E; ++I) +- MadeChange |= ProcessBlock(*I); +- EverMadeChange |= MadeChange; +- NumSinkIter++; +- } while (MadeChange); +- +- return EverMadeChange; +-} +- +-bool Sinking::ProcessBlock(BasicBlock &BB) { +- // Can't sink anything out of a block that has less than two successors. +- if (BB.getTerminator()->getNumSuccessors() <= 1) return false; +- +- // Don't bother sinking code out of unreachable blocks. In addition to being +- // unprofitable, it can also lead to infinite looping, because in an +- // unreachable loop there may be nowhere to stop. +- if (!DT->isReachableFromEntry(&BB)) return false; +- +- bool MadeChange = false; +- +- // Walk the basic block bottom-up. Remember if we saw a store. +- BasicBlock::iterator I = BB.end(); +- --I; +- bool ProcessedBegin = false; +- SmallPtrSet Stores; +- do { +- Instruction *Inst = &*I; // The instruction to sink. +- +- // Predecrement I (if it's not begin) so that it isn't invalidated by +- // sinking. +- ProcessedBegin = I == BB.begin(); +- if (!ProcessedBegin) +- --I; +- +- if (isa(Inst)) +- continue; +- +- if (SinkInstruction(Inst, Stores)) { +- ++NumSunk; +- MadeChange = true; +- } +- +- // If we just processed the first instruction in the block, we're done. +- } while (!ProcessedBegin); +- +- return MadeChange; +-} +- + static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, + SmallPtrSetImpl &Stores) { + +@@ -290,3 +230,63 @@ bool Sinking::SinkInstruction(Instruction *Inst, + Inst->moveBefore(&*SuccToSinkTo->getFirstInsertionPt()); + return true; + } ++ ++bool Sinking::ProcessBlock(BasicBlock &BB) { ++ // Can't sink anything out of a block that has less than two successors. ++ if (BB.getTerminator()->getNumSuccessors() <= 1) return false; ++ ++ // Don't bother sinking code out of unreachable blocks. In addition to being ++ // unprofitable, it can also lead to infinite looping, because in an ++ // unreachable loop there may be nowhere to stop. ++ if (!DT->isReachableFromEntry(&BB)) return false; ++ ++ bool MadeChange = false; ++ ++ // Walk the basic block bottom-up. Remember if we saw a store. ++ BasicBlock::iterator I = BB.end(); ++ --I; ++ bool ProcessedBegin = false; ++ SmallPtrSet Stores; ++ do { ++ Instruction *Inst = &*I; // The instruction to sink. ++ ++ // Predecrement I (if it's not begin) so that it isn't invalidated by ++ // sinking. ++ ProcessedBegin = I == BB.begin(); ++ if (!ProcessedBegin) ++ --I; ++ ++ if (isa(Inst)) ++ continue; ++ ++ if (SinkInstruction(Inst, Stores)) { ++ ++NumSunk; ++ MadeChange = true; ++ } ++ ++ // If we just processed the first instruction in the block, we're done. ++ } while (!ProcessedBegin); ++ ++ return MadeChange; ++} ++ ++bool Sinking::runOnFunction(Function &F) { ++ DT = &getAnalysis().getDomTree(); ++ LI = &getAnalysis().getLoopInfo(); ++ AA = &getAnalysis().getAAResults(); ++ ++ bool MadeChange, EverMadeChange = false; ++ ++ do { ++ MadeChange = false; ++ DEBUG(dbgs() << "Sinking iteration " << NumSinkIter << "\n"); ++ // Process all basic blocks. ++ for (Function::iterator I = F.begin(), E = F.end(); ++ I != E; ++I) ++ MadeChange |= ProcessBlock(*I); ++ EverMadeChange |= MadeChange; ++ NumSinkIter++; ++ } while (MadeChange); ++ ++ return EverMadeChange; ++} + +commit 7a08381403b54cd8998f3c922f18b65867e3c07c +Author: Richard Trieu +Date: Thu Feb 18 22:09:30 2016 +0000 + + Remove uses of builtin comma operator. + + Cleanup for upcoming Clang warning -Wcomma. No functionality change intended. + + llvm-svn: 261270 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 64109b2df117..eb09f584dc68 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -145,8 +145,10 @@ bool Sinking::ProcessBlock(BasicBlock &BB) { + if (isa(Inst)) + continue; + +- if (SinkInstruction(Inst, Stores)) +- ++NumSunk, MadeChange = true; ++ if (SinkInstruction(Inst, Stores)) { ++ ++NumSunk; ++ MadeChange = true; ++ } + + // If we just processed the first instruction in the block, we're done. + } while (!ProcessedBegin); + +commit 8a1c45d6e86d54c40835fa8638d1fd900071783c +Author: David Majnemer +Date: Sat Dec 12 05:38:55 2015 +0000 + + [IR] Reformulate LLVM's EH funclet IR + + While we have successfully implemented a funclet-oriented EH scheme on + top of LLVM IR, our scheme has some notable deficiencies: + - catchendpad and cleanupendpad are necessary in the current design + but they are difficult to explain to others, even to seasoned LLVM + experts. + - catchendpad and cleanupendpad are optimization barriers. They cannot + be split and force all potentially throwing call-sites to be invokes. + This has a noticable effect on the quality of our code generation. + - catchpad, while similar in some aspects to invoke, is fairly awkward. + It is unsplittable, starts a funclet, and has control flow to other + funclets. + - The nesting relationship between funclets is currently a property of + control flow edges. Because of this, we are forced to carefully + analyze the flow graph to see if there might potentially exist illegal + nesting among funclets. While we have logic to clone funclets when + they are illegally nested, it would be nicer if we had a + representation which forbade them upfront. + + Let's clean this up a bit by doing the following: + - Instead, make catchpad more like cleanuppad and landingpad: no control + flow, just a bunch of simple operands; catchpad would be splittable. + - Introduce catchswitch, a control flow instruction designed to model + the constraints of funclet oriented EH. + - Make funclet scoping explicit by having funclet instructions consume + the token produced by the funclet which contains them. + - Remove catchendpad and cleanupendpad. Their presence can be inferred + implicitly using coloring information. + + N.B. The state numbering code for the CLR has been updated but the + veracity of it's output cannot be spoken for. An expert should take a + look to make sure the results are reasonable. + + Reviewers: rnk, JosephTremoulet, andrew.w.kaylor + + Differential Revision: http://reviews.llvm.org/D15139 + + llvm-svn: 255422 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 7c0ac7aa6fae..64109b2df117 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -169,7 +169,8 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, + return false; + } + +- if (isa(Inst) || isa(Inst) || Inst->isEHPad()) ++ if (isa(Inst) || isa(Inst) || Inst->isEHPad() || ++ Inst->mayThrow()) + return false; + + // Convergent operations cannot be made control-dependent on additional +@@ -194,6 +195,11 @@ bool Sinking::IsAcceptableTarget(Instruction *Inst, + if (Inst->getParent() == SuccToSinkTo) + return false; + ++ // It's never legal to sink an instruction into a block which terminates in an ++ // EH-pad. ++ if (SuccToSinkTo->getTerminator()->isExceptional()) ++ return false; ++ + // If the block has multiple predecessors, this would introduce computation + // on different code paths. We could split the critical edge, but for now we + // just punt. + +commit 86c95b5642807d2aba091f437d11691b3a285439 +Author: Keno Fischer +Date: Mon Nov 16 04:47:58 2015 +0000 + + [Sink] Don't move landingpads + + Summary: Moving landingpads into successor basic blocks makes the + verifier sad. Teach Sink that much like PHI nodes and terminator + instructions, landingpads (and cleanuppads, etc.) may not be moved + between basic blocks. + + Reviewers: majnemer + + Subscribers: llvm-commits + + Differential Revision: http://reviews.llvm.org/D14475 + + llvm-svn: 253182 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index f6ccd999ea00..7c0ac7aa6fae 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -169,7 +169,7 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, + return false; + } + +- if (isa(Inst) || isa(Inst)) ++ if (isa(Inst) || isa(Inst) || Inst->isEHPad()) + return false; + + // Convergent operations cannot be made control-dependent on additional + +commit e0675fb8fbc78bd1e60bab0c1fac711eab96ab6e +Author: David Majnemer +Date: Thu Oct 22 20:29:08 2015 +0000 + + [Sink] Don't check BB.empty() + + As an invariant, BasicBlocks cannot be empty when passed to a transform. + This is not the case for MachineBasicBlocks and the Sink pass was ported + from the MachineSink pass which would explain the check's existence. + + llvm-svn: 251057 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 8b916347999c..f6ccd999ea00 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -119,7 +119,7 @@ bool Sinking::runOnFunction(Function &F) { + + bool Sinking::ProcessBlock(BasicBlock &BB) { + // Can't sink anything out of a block that has less than two successors. +- if (BB.getTerminator()->getNumSuccessors() <= 1 || BB.empty()) return false; ++ if (BB.getTerminator()->getNumSuccessors() <= 1) return false; + + // Don't bother sinking code out of unreachable blocks. In addition to being + // unprofitable, it can also lead to infinite looping, because in an + +commit be4d8cba1ccf6f0611db50e8c7ba366ce3a3137d +Author: Duncan P. N. Exon Smith +Date: Tue Oct 13 19:26:58 2015 +0000 + + Scalar: Remove remaining ilist iterator implicit conversions + + Remove remaining `ilist_iterator` implicit conversions from + LLVMScalarOpts. + + This change exposed some scary behaviour in + lib/Transforms/Scalar/SCCP.cpp around line 1770. This patch changes a + call from `Function::begin()` to `&Function::front()`, since the return + was immediately being passed into another function that takes a + `Function*`. `Function::front()` started to assert, since the function + was empty. Note that `Function::end()` does not point at a legal + `Function*` -- it points at an `ilist_half_node` -- so the other + function was getting garbage before. (I added the missing check for + `Function::isDeclaration()`.) + + Otherwise, no functionality change intended. + + llvm-svn: 250211 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 17a6858a0c00..8b916347999c 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -134,7 +134,7 @@ bool Sinking::ProcessBlock(BasicBlock &BB) { + bool ProcessedBegin = false; + SmallPtrSet Stores; + do { +- Instruction *Inst = I; // The instruction to sink. ++ Instruction *Inst = &*I; // The instruction to sink. + + // Predecrement I (if it's not begin) so that it isn't invalidated by + // sinking. +@@ -279,6 +279,6 @@ bool Sinking::SinkInstruction(Instruction *Inst, + dbgs() << ")\n"); + + // Move the instruction. +- Inst->moveBefore(SuccToSinkTo->getFirstInsertionPt()); ++ Inst->moveBefore(&*SuccToSinkTo->getFirstInsertionPt()); + return true; + } + +commit d95b08a0a72ef47268b94738360c9319dcdc4772 +Author: Owen Anderson +Date: Fri Oct 9 18:06:13 2015 +0000 + + Refine the definition of convergent to only disallow the addition of new control dependencies. + + This covers the common case of operations that cannot be sunk. + Operations that cannot be hoisted should already be handled properly via + the safe-to-speculate rules and mechanisms. + + llvm-svn: 249865 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index adc53b17bdf9..17a6858a0c00 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -172,7 +172,8 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, + if (isa(Inst) || isa(Inst)) + return false; + +- // Convergent operations can only be moved to control equivalent blocks. ++ // Convergent operations cannot be made control-dependent on additional ++ // values. + if (auto CS = CallSite(Inst)) { + if (CS.hasFnAttr(Attribute::Convergent)) + return false; + +commit 7b560d40bddfb60f162a7541288aeba3776f79f8 +Author: Chandler Carruth +Date: Wed Sep 9 17:55:00 2015 +0000 + + [PM/AA] Rebuild LLVM's alias analysis infrastructure in a way compatible + with the new pass manager, and no longer relying on analysis groups. + + This builds essentially a ground-up new AA infrastructure stack for + LLVM. The core ideas are the same that are used throughout the new pass + manager: type erased polymorphism and direct composition. The design is + as follows: + + - FunctionAAResults is a type-erasing alias analysis results aggregation + interface to walk a single query across a range of results from + different alias analyses. Currently this is function-specific as we + always assume that aliasing queries are *within* a function. + + - AAResultBase is a CRTP utility providing stub implementations of + various parts of the alias analysis result concept, notably in several + cases in terms of other more general parts of the interface. This can + be used to implement only a narrow part of the interface rather than + the entire interface. This isn't really ideal, this logic should be + hoisted into FunctionAAResults as currently it will cause + a significant amount of redundant work, but it faithfully models the + behavior of the prior infrastructure. + + - All the alias analysis passes are ported to be wrapper passes for the + legacy PM and new-style analysis passes for the new PM with a shared + result object. In some cases (most notably CFL), this is an extremely + naive approach that we should revisit when we can specialize for the + new pass manager. + + - BasicAA has been restructured to reflect that it is much more + fundamentally a function analysis because it uses dominator trees and + loop info that need to be constructed for each function. + + All of the references to getting alias analysis results have been + updated to use the new aggregation interface. All the preservation and + other pass management code has been updated accordingly. + + The way the FunctionAAResultsWrapperPass works is to detect the + available alias analyses when run, and add them to the results object. + This means that we should be able to continue to respect when various + passes are added to the pipeline, for example adding CFL or adding TBAA + passes should just cause their results to be available and to get folded + into this. The exception to this rule is BasicAA which really needs to + be a function pass due to using dominator trees and loop info. As + a consequence, the FunctionAAResultsWrapperPass directly depends on + BasicAA and always includes it in the aggregation. + + This has significant implications for preserving analyses. Generally, + most passes shouldn't bother preserving FunctionAAResultsWrapperPass + because rebuilding the results just updates the set of known AA passes. + The exception to this rule are LoopPass instances which need to preserve + all the function analyses that the loop pass manager will end up + needing. This means preserving both BasicAAWrapperPass and the + aggregating FunctionAAResultsWrapperPass. + + Now, when preserving an alias analysis, you do so by directly preserving + that analysis. This is only necessary for non-immutable-pass-provided + alias analyses though, and there are only three of interest: BasicAA, + GlobalsAA (formerly GlobalsModRef), and SCEVAA. Usually BasicAA is + preserved when needed because it (like DominatorTree and LoopInfo) is + marked as a CFG-only pass. I've expanded GlobalsAA into the preserved + set everywhere we previously were preserving all of AliasAnalysis, and + I've added SCEVAA in the intersection of that with where we preserve + SCEV itself. + + One significant challenge to all of this is that the CGSCC passes were + actually using the alias analysis implementations by taking advantage of + a pretty amazing set of loop holes in the old pass manager's analysis + management code which allowed analysis groups to slide through in many + cases. Moving away from analysis groups makes this problem much more + obvious. To fix it, I've leveraged the flexibility the design of the new + PM components provides to just directly construct the relevant alias + analyses for the relevant functions in the IPO passes that need them. + This is a bit hacky, but should go away with the new pass manager, and + is already in many ways cleaner than the prior state. + + Another significant challenge is that various facilities of the old + alias analysis infrastructure just don't fit any more. The most + significant of these is the alias analysis 'counter' pass. That pass + relied on the ability to snoop on AA queries at different points in the + analysis group chain. Instead, I'm planning to build printing + functionality directly into the aggregation layer. I've not included + that in this patch merely to keep it smaller. + + Note that all of this needs a nearly complete rewrite of the AA + documentation. I'm planning to do that, but I'd like to make sure the + new design settles, and to flesh out a bit more of what it looks like in + the new pass manager first. + + Differential Revision: http://reviews.llvm.org/D12080 + + llvm-svn: 247167 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 17684c04dc4d..adc53b17bdf9 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -48,7 +48,7 @@ namespace { + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesCFG(); + FunctionPass::getAnalysisUsage(AU); +- AU.addRequired(); ++ AU.addRequired(); + AU.addRequired(); + AU.addRequired(); + AU.addPreserved(); +@@ -66,7 +66,7 @@ char Sinking::ID = 0; + INITIALIZE_PASS_BEGIN(Sinking, "sink", "Code sinking", false, false) + INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) + INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) +-INITIALIZE_AG_DEPENDENCY(AliasAnalysis) ++INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass) + INITIALIZE_PASS_END(Sinking, "sink", "Code sinking", false, false) + + FunctionPass *llvm::createSinkingPass() { return new Sinking(); } +@@ -99,7 +99,7 @@ bool Sinking::AllUsesDominatedByBlock(Instruction *Inst, + bool Sinking::runOnFunction(Function &F) { + DT = &getAnalysis().getDomTree(); + LI = &getAnalysis().getLoopInfo(); +- AA = &getAnalysis(); ++ AA = &getAnalysis().getAAResults(); + + bool MadeChange, EverMadeChange = false; + + +commit 194f59ca5d2f48f1e0b7fa95971ae9f88e95ba95 +Author: Chandler Carruth +Date: Wed Jul 22 23:15:57 2015 +0000 + + [PM/AA] Extract the ModRef enums from the AliasAnalysis class in + preparation for de-coupling the AA implementations. + + In order to do this, they had to become fake-scoped using the + traditional LLVM pattern of a leading initialism. These can't be actual + scoped enumerations because they're bitfields and thus inherently we use + them as integers. + + I've also renamed the behavior enums that are specific to reasoning + about the mod/ref behavior of functions when called. This makes it more + clear that they have a very narrow domain of applicability. + + I think there is a significantly cleaner API for all of this, but + I don't want to try to do really substantive changes for now, I just + want to refactor the things away from analysis groups so I'm preserving + the exact original design and just cleaning up the names, style, and + lifting out of the class. + + Differential Revision: http://reviews.llvm.org/D10564 + + llvm-svn: 242963 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index f49f4eaaedcb..17684c04dc4d 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -165,7 +165,7 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, + if (LoadInst *L = dyn_cast(Inst)) { + MemoryLocation Loc = MemoryLocation::get(L); + for (Instruction *S : Stores) +- if (AA->getModRefInfo(S, Loc) & AliasAnalysis::Mod) ++ if (AA->getModRefInfo(S, Loc) & MRI_Mod) + return false; + } + + +commit ac80dc753228af5f1b415bc9fa9834aeba19122b +Author: Chandler Carruth +Date: Wed Jun 17 07:18:54 2015 +0000 + + [PM/AA] Remove the Location typedef from the AliasAnalysis class now + that it is its own entity in the form of MemoryLocation, and update all + the callers. + + This is an entirely mechanical change. References to "Location" within + AA subclases become "MemoryLocation", and elsewhere + "AliasAnalysis::Location" becomes "MemoryLocation". Hope that helps + out-of-tree folks update. + + llvm-svn: 239885 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 078c6a921a08..f49f4eaaedcb 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -163,7 +163,7 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, + } + + if (LoadInst *L = dyn_cast(Inst)) { +- AliasAnalysis::Location Loc = MemoryLocation::get(L); ++ MemoryLocation Loc = MemoryLocation::get(L); + for (Instruction *S : Stores) + if (AA->getModRefInfo(S, Loc) & AliasAnalysis::Mod) + return false; + +commit 70c61c1a8adad268f1058986aa501afb142ecb4c +Author: Chandler Carruth +Date: Thu Jun 4 02:03:15 2015 +0000 + + [PM/AA] Start refactoring AliasAnalysis to remove the analysis group and + port it to the new pass manager. + + All this does is extract the inner "location" class used by AA into its + own full fledged type. This seems *much* cleaner as MemoryDependence and + soon MemorySSA also use this heavily, and it doesn't make much sense + being inside the AA infrastructure. + + This will also make it much easier to break apart the AA infrastructure + into something that stands on its own rather than using the analysis + group design. + + There are a few places where this makes APIs not make sense -- they were + taking an AliasAnalysis pointer just to build locations. I'll try to + clean those up in follow-up commits. + + Differential Revision: http://reviews.llvm.org/D10228 + + llvm-svn: 239003 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index ec3a0186641e..078c6a921a08 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -163,7 +163,7 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, + } + + if (LoadInst *L = dyn_cast(Inst)) { +- AliasAnalysis::Location Loc = AA->getLocation(L); ++ AliasAnalysis::Location Loc = MemoryLocation::get(L); + for (Instruction *S : Stores) + if (AA->getModRefInfo(S, Loc) & AliasAnalysis::Mod) + return false; + +commit 15d180550448a7561e5d3c7e1ffa22602f2b3ed7 +Author: Owen Anderson +Date: Mon Jun 1 17:20:31 2015 +0000 + + Teach the IR Sink pass to (conservatively) respect convergent annotations. + + llvm-svn: 238762 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index b169d5612f00..ec3a0186641e 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -172,6 +172,12 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, + if (isa(Inst) || isa(Inst)) + return false; + ++ // Convergent operations can only be moved to control equivalent blocks. ++ if (auto CS = CallSite(Inst)) { ++ if (CS.hasFnAttr(Attribute::Convergent)) ++ return false; ++ } ++ + return true; + } + + +commit a28d91d81b5daa4d8b92452ea8203a57023b576f +Author: Mehdi Amini +Date: Tue Mar 10 02:37:25 2015 +0000 + + DataLayout is mandatory, update the API to reflect it with references. + + Summary: + Now that the DataLayout is a mandatory part of the module, let's start + cleaning the codebase. This patch is a first attempt at doing that. + + This patch is not exactly NFC as for instance some places were passing + a nullptr instead of the DataLayout, possibly just because there was a + default value on the DataLayout argument to many functions in the API. + Even though it is not purely NFC, there is no change in the + validation. + + I turned as many pointer to DataLayout to references, this helped + figuring out all the places where a nullptr could come up. + + I had initially a local version of this patch broken into over 30 + independant, commits but some later commit were cleaning the API and + touching part of the code modified in the previous commits, so it + seemed cleaner without the intermediate state. + + Test Plan: + + Reviewers: echristo + + Subscribers: llvm-commits + + From: Mehdi Amini + llvm-svn: 231740 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 4ba3f1949db6..b169d5612f00 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -36,7 +36,6 @@ namespace { + DominatorTree *DT; + LoopInfo *LI; + AliasAnalysis *AA; +- const DataLayout *DL; + + public: + static char ID; // Pass identification +@@ -101,7 +100,6 @@ bool Sinking::runOnFunction(Function &F) { + DT = &getAnalysis().getDomTree(); + LI = &getAnalysis().getLoopInfo(); + AA = &getAnalysis(); +- DL = &F.getParent()->getDataLayout(); + + bool MadeChange, EverMadeChange = false; + +@@ -196,7 +194,7 @@ bool Sinking::IsAcceptableTarget(Instruction *Inst, + if (SuccToSinkTo->getUniquePredecessor() != Inst->getParent()) { + // We cannot sink a load across a critical edge - there may be stores in + // other code paths. +- if (!isSafeToSpeculativelyExecute(Inst, DL)) ++ if (!isSafeToSpeculativelyExecute(Inst)) + return false; + + // We don't want to sink across a critical edge if we don't dominate the + +commit 46a43556db23edb514f190cc03b0ce7f68d40534 +Author: Mehdi Amini +Date: Wed Mar 4 18:43:29 2015 +0000 + + Make DataLayout Non-Optional in the Module + + Summary: + DataLayout keeps the string used for its creation. + + As a side effect it is no longer needed in the Module. + This is "almost" NFC, the string is no longer + canonicalized, you can't rely on two "equals" DataLayout + having the same string returned by getStringRepresentation(). + + Get rid of DataLayoutPass: the DataLayout is in the Module + + The DataLayout is "per-module", let's enforce this by not + duplicating it more than necessary. + One more step toward non-optionality of the DataLayout in the + module. + + Make DataLayout Non-Optional in the Module + + Module->getDataLayout() will never returns nullptr anymore. + + Reviewers: echristo + + Subscribers: resistor, llvm-commits, jholewinski + + Differential Revision: http://reviews.llvm.org/D7992 + + From: Mehdi Amini + llvm-svn: 231270 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index d0ee0a679b38..4ba3f1949db6 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -21,6 +21,7 @@ + #include "llvm/IR/DataLayout.h" + #include "llvm/IR/Dominators.h" + #include "llvm/IR/IntrinsicInst.h" ++#include "llvm/IR/Module.h" + #include "llvm/Support/Debug.h" + #include "llvm/Support/raw_ostream.h" + using namespace llvm; +@@ -100,8 +101,7 @@ bool Sinking::runOnFunction(Function &F) { + DT = &getAnalysis().getDomTree(); + LI = &getAnalysis().getLoopInfo(); + AA = &getAnalysis(); +- DataLayoutPass *DLP = getAnalysisIfAvailable(); +- DL = DLP ? &DLP->getDataLayout() : nullptr; ++ DL = &F.getParent()->getDataLayout(); + + bool MadeChange, EverMadeChange = false; + + +commit 4f8f307c77fa5b4de2eec8868b8734b2ab93dd22 +Author: Chandler Carruth +Date: Sat Jan 17 14:16:18 2015 +0000 + + [PM] Split the LoopInfo object apart from the legacy pass, creating + a LoopInfoWrapperPass to wire the object up to the legacy pass manager. + + This switches all the clients of LoopInfo over and paves the way to port + LoopInfo to the new pass manager. No functionality change is intended + with this iteration. + + llvm-svn: 226373 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 903b675fdd56..d0ee0a679b38 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -50,9 +50,9 @@ namespace { + FunctionPass::getAnalysisUsage(AU); + AU.addRequired(); + AU.addRequired(); +- AU.addRequired(); ++ AU.addRequired(); + AU.addPreserved(); +- AU.addPreserved(); ++ AU.addPreserved(); + } + private: + bool ProcessBlock(BasicBlock &BB); +@@ -64,7 +64,7 @@ namespace { + + char Sinking::ID = 0; + INITIALIZE_PASS_BEGIN(Sinking, "sink", "Code sinking", false, false) +-INITIALIZE_PASS_DEPENDENCY(LoopInfo) ++INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) + INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) + INITIALIZE_AG_DEPENDENCY(AliasAnalysis) + INITIALIZE_PASS_END(Sinking, "sink", "Code sinking", false, false) +@@ -98,7 +98,7 @@ bool Sinking::AllUsesDominatedByBlock(Instruction *Inst, + + bool Sinking::runOnFunction(Function &F) { + DT = &getAnalysis().getDomTree(); +- LI = &getAnalysis(); ++ LI = &getAnalysis().getLoopInfo(); + AA = &getAnalysis(); + DataLayoutPass *DLP = getAnalysisIfAvailable(); + DL = DLP ? &DLP->getDataLayout() : nullptr; + +commit 4627679cece264a966faa82a7c5bb79f273d5b6e +Author: Craig Topper +Date: Sun Aug 24 23:23:06 2014 +0000 + + Use range based for loops to avoid needing to re-mention SmallPtrSet size. + + llvm-svn: 216351 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 2f4e23a7488b..903b675fdd56 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -166,9 +166,8 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, + + if (LoadInst *L = dyn_cast(Inst)) { + AliasAnalysis::Location Loc = AA->getLocation(L); +- for (SmallPtrSet::iterator I = Stores.begin(), +- E = Stores.end(); I != E; ++I) +- if (AA->getModRefInfo(*I, Loc) & AliasAnalysis::Mod) ++ for (Instruction *S : Stores) ++ if (AA->getModRefInfo(S, Loc) & AliasAnalysis::Mod) + return false; + } + + +commit 71b7b68b741a29c473479c64dbaca00b94e316ab +Author: Craig Topper +Date: Thu Aug 21 05:55:13 2014 +0000 + + Repace SmallPtrSet with SmallPtrSetImpl in function arguments to avoid needing to mention the size. + + llvm-svn: 216158 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 7348c45c5d37..2f4e23a7488b 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -56,7 +56,7 @@ namespace { + } + private: + bool ProcessBlock(BasicBlock &BB); +- bool SinkInstruction(Instruction *I, SmallPtrSet &Stores); ++ bool SinkInstruction(Instruction *I, SmallPtrSetImpl &Stores); + bool AllUsesDominatedByBlock(Instruction *Inst, BasicBlock *BB) const; + bool IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo) const; + }; +@@ -157,7 +157,7 @@ bool Sinking::ProcessBlock(BasicBlock &BB) { + } + + static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, +- SmallPtrSet &Stores) { ++ SmallPtrSetImpl &Stores) { + + if (Inst->mayWriteToMemory()) { + Stores.insert(Inst); +@@ -220,7 +220,7 @@ bool Sinking::IsAcceptableTarget(Instruction *Inst, + /// SinkInstruction - Determine whether it is safe to sink the specified machine + /// instruction out of its current block into a successor. + bool Sinking::SinkInstruction(Instruction *Inst, +- SmallPtrSet &Stores) { ++ SmallPtrSetImpl &Stores) { + + // Don't sink static alloca instructions. CodeGen assumes allocas outside the + // entry block are dynamically sized stack objects. + +commit 6230691c9186e95cd19dff07074a54fb70719957 +Author: Craig Topper +Date: Mon Aug 18 00:24:38 2014 +0000 + + Revert "Repace SmallPtrSet with SmallPtrSetImpl in function arguments to avoid needing to mention the size." + + Getting a weird buildbot failure that I need to investigate. + + llvm-svn: 215870 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 2f4e23a7488b..7348c45c5d37 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -56,7 +56,7 @@ namespace { + } + private: + bool ProcessBlock(BasicBlock &BB); +- bool SinkInstruction(Instruction *I, SmallPtrSetImpl &Stores); ++ bool SinkInstruction(Instruction *I, SmallPtrSet &Stores); + bool AllUsesDominatedByBlock(Instruction *Inst, BasicBlock *BB) const; + bool IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo) const; + }; +@@ -157,7 +157,7 @@ bool Sinking::ProcessBlock(BasicBlock &BB) { + } + + static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, +- SmallPtrSetImpl &Stores) { ++ SmallPtrSet &Stores) { + + if (Inst->mayWriteToMemory()) { + Stores.insert(Inst); +@@ -220,7 +220,7 @@ bool Sinking::IsAcceptableTarget(Instruction *Inst, + /// SinkInstruction - Determine whether it is safe to sink the specified machine + /// instruction out of its current block into a successor. + bool Sinking::SinkInstruction(Instruction *Inst, +- SmallPtrSetImpl &Stores) { ++ SmallPtrSet &Stores) { + + // Don't sink static alloca instructions. CodeGen assumes allocas outside the + // entry block are dynamically sized stack objects. + +commit 5229cfd1638705a7dbf668a840c6015f6b3ecbc6 +Author: Craig Topper +Date: Sun Aug 17 23:47:00 2014 +0000 + + Repace SmallPtrSet with SmallPtrSetImpl in function arguments to avoid needing to mention the size. + + llvm-svn: 215868 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 7348c45c5d37..2f4e23a7488b 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -56,7 +56,7 @@ namespace { + } + private: + bool ProcessBlock(BasicBlock &BB); +- bool SinkInstruction(Instruction *I, SmallPtrSet &Stores); ++ bool SinkInstruction(Instruction *I, SmallPtrSetImpl &Stores); + bool AllUsesDominatedByBlock(Instruction *Inst, BasicBlock *BB) const; + bool IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo) const; + }; +@@ -157,7 +157,7 @@ bool Sinking::ProcessBlock(BasicBlock &BB) { + } + + static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, +- SmallPtrSet &Stores) { ++ SmallPtrSetImpl &Stores) { + + if (Inst->mayWriteToMemory()) { + Stores.insert(Inst); +@@ -220,7 +220,7 @@ bool Sinking::IsAcceptableTarget(Instruction *Inst, + /// SinkInstruction - Determine whether it is safe to sink the specified machine + /// instruction out of its current block into a successor. + bool Sinking::SinkInstruction(Instruction *Inst, +- SmallPtrSet &Stores) { ++ SmallPtrSetImpl &Stores) { + + // Don't sink static alloca instructions. CodeGen assumes allocas outside the + // entry block are dynamically sized stack objects. + +commit 6c99015fe2c1814f793530adc96f48050081612e +Author: Duncan P. N. Exon Smith +Date: Mon Jul 21 17:06:51 2014 +0000 + + Revert "[C++11] Add predecessors(BasicBlock *) / successors(BasicBlock *) iterator ranges." + + This reverts commit r213474 (and r213475), which causes a miscompile on + a stage2 LTO build. I'll reply on the list in a moment. + + llvm-svn: 213562 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 2f7a9f9a65cf..7348c45c5d37 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -258,11 +258,10 @@ bool Sinking::SinkInstruction(Instruction *Inst, + + // If no suitable postdominator was found, look at all the successors and + // decide which one we should sink to, if any. +- for (BasicBlock *Succ : successors(Inst->getParent())) { +- if (SuccToSinkTo) +- break; +- if (IsAcceptableTarget(Inst, Succ)) +- SuccToSinkTo = Succ; ++ for (succ_iterator I = succ_begin(Inst->getParent()), ++ E = succ_end(Inst->getParent()); I != E && !SuccToSinkTo; ++I) { ++ if (IsAcceptableTarget(Inst, *I)) ++ SuccToSinkTo = *I; + } + + // If we couldn't find a block to sink to, ignore this instruction. + +commit d11beffef4f1117aceb9f2f5532b4a317c30c05a +Author: Manuel Jacob +Date: Sun Jul 20 09:10:11 2014 +0000 + + [C++11] Add predecessors(BasicBlock *) / successors(BasicBlock *) iterator ranges. + + Summary: This patch introduces two new iterator ranges and updates existing code to use it. No functional change intended. + + Test Plan: All tests (make check-all) still pass. + + Reviewers: dblaikie + + Reviewed By: dblaikie + + Subscribers: llvm-commits + + Differential Revision: http://reviews.llvm.org/D4481 + + llvm-svn: 213474 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 7348c45c5d37..2f7a9f9a65cf 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -258,10 +258,11 @@ bool Sinking::SinkInstruction(Instruction *Inst, + + // If no suitable postdominator was found, look at all the successors and + // decide which one we should sink to, if any. +- for (succ_iterator I = succ_begin(Inst->getParent()), +- E = succ_end(Inst->getParent()); I != E && !SuccToSinkTo; ++I) { +- if (IsAcceptableTarget(Inst, *I)) +- SuccToSinkTo = *I; ++ for (BasicBlock *Succ : successors(Inst->getParent())) { ++ if (SuccToSinkTo) ++ break; ++ if (IsAcceptableTarget(Inst, Succ)) ++ SuccToSinkTo = Succ; + } + + // If we couldn't find a block to sink to, ignore this instruction. + +commit 511fea7acdc360bc77978370cfbe0218738ea24c +Author: Hal Finkel +Date: Thu Jul 10 16:07:11 2014 +0000 + + Feeding isSafeToSpeculativelyExecute its DataLayout pointer (in Sink) + + This is the one remaining place I see where passing + isSafeToSpeculativelyExecute a DataLayout pointer might matter (at least for + loads) -- I think I got the others in r212720. Most of the other remaining + callers of isSafeToSpeculativelyExecute only use it for call sites (or + otherwise exclude loads). + + llvm-svn: 212730 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 482c33aa6e0b..7348c45c5d37 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -18,6 +18,7 @@ + #include "llvm/Analysis/LoopInfo.h" + #include "llvm/Analysis/ValueTracking.h" + #include "llvm/IR/CFG.h" ++#include "llvm/IR/DataLayout.h" + #include "llvm/IR/Dominators.h" + #include "llvm/IR/IntrinsicInst.h" + #include "llvm/Support/Debug.h" +@@ -34,6 +35,7 @@ namespace { + DominatorTree *DT; + LoopInfo *LI; + AliasAnalysis *AA; ++ const DataLayout *DL; + + public: + static char ID; // Pass identification +@@ -98,6 +100,8 @@ bool Sinking::runOnFunction(Function &F) { + DT = &getAnalysis().getDomTree(); + LI = &getAnalysis(); + AA = &getAnalysis(); ++ DataLayoutPass *DLP = getAnalysisIfAvailable(); ++ DL = DLP ? &DLP->getDataLayout() : nullptr; + + bool MadeChange, EverMadeChange = false; + +@@ -193,7 +197,7 @@ bool Sinking::IsAcceptableTarget(Instruction *Inst, + if (SuccToSinkTo->getUniquePredecessor() != Inst->getParent()) { + // We cannot sink a load across a critical edge - there may be stores in + // other code paths. +- if (!isSafeToSpeculativelyExecute(Inst)) ++ if (!isSafeToSpeculativelyExecute(Inst, DL)) + return false; + + // We don't want to sink across a critical edge if we don't dominate the + +commit f40110f4d80436071213ed7fcbe367d64aa52c71 +Author: Craig Topper +Date: Fri Apr 25 05:29:35 2014 +0000 + + [C++] Use 'nullptr'. Transforms edition. + + llvm-svn: 207196 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 121ee0923b39..482c33aa6e0b 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -204,7 +204,7 @@ bool Sinking::IsAcceptableTarget(Instruction *Inst, + // Don't sink instructions into a loop. + Loop *succ = LI->getLoopFor(SuccToSinkTo); + Loop *cur = LI->getLoopFor(Inst->getParent()); +- if (succ != 0 && succ != cur) ++ if (succ != nullptr && succ != cur) + return false; + } + +@@ -238,14 +238,14 @@ bool Sinking::SinkInstruction(Instruction *Inst, + + // SuccToSinkTo - This is the successor to sink this instruction to, once we + // decide. +- BasicBlock *SuccToSinkTo = 0; ++ BasicBlock *SuccToSinkTo = nullptr; + + // Instructions can only be sunk if all their uses are in blocks + // dominated by one of the successors. + // Look at all the postdominators and see if we can sink it in one. + DomTreeNode *DTN = DT->getNode(Inst->getParent()); + for (DomTreeNode::iterator I = DTN->begin(), E = DTN->end(); +- I != E && SuccToSinkTo == 0; ++I) { ++ I != E && SuccToSinkTo == nullptr; ++I) { + BasicBlock *Candidate = (*I)->getBlock(); + if ((*I)->getIDom()->getBlock() == Inst->getParent() && + IsAcceptableTarget(Inst, Candidate)) +@@ -255,13 +255,13 @@ bool Sinking::SinkInstruction(Instruction *Inst, + // If no suitable postdominator was found, look at all the successors and + // decide which one we should sink to, if any. + for (succ_iterator I = succ_begin(Inst->getParent()), +- E = succ_end(Inst->getParent()); I != E && SuccToSinkTo == 0; ++I) { ++ E = succ_end(Inst->getParent()); I != E && !SuccToSinkTo; ++I) { + if (IsAcceptableTarget(Inst, *I)) + SuccToSinkTo = *I; + } + + // If we couldn't find a block to sink to, ignore this instruction. +- if (SuccToSinkTo == 0) ++ if (!SuccToSinkTo) + return false; + + DEBUG(dbgs() << "Sink" << *Inst << " ("; + +commit 964daaaf192f76eccb4eb9fed849133c91b96bc5 +Author: Chandler Carruth +Date: Tue Apr 22 02:55:47 2014 +0000 + + [Modules] Fix potential ODR violations by sinking the DEBUG_TYPE + definition below all of the header #include lines, lib/Transforms/... + edition. + + This one is tricky for two reasons. We again have a couple of passes + that define something else before the includes as well. I've sunk their + name macros with the DEBUG_TYPE. + + Also, InstCombine contains headers that need DEBUG_TYPE, so now those + headers #define and #undef DEBUG_TYPE around their code, leaving them + well formed modular headers. Fixing these headers was a large motivation + for all of these changes, as "leaky" macros of this form are hard on the + modules implementation. + + llvm-svn: 206844 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 41073749abc7..121ee0923b39 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -12,7 +12,6 @@ + // + //===----------------------------------------------------------------------===// + +-#define DEBUG_TYPE "sink" + #include "llvm/Transforms/Scalar.h" + #include "llvm/ADT/Statistic.h" + #include "llvm/Analysis/AliasAnalysis.h" +@@ -25,6 +24,8 @@ + #include "llvm/Support/raw_ostream.h" + using namespace llvm; + ++#define DEBUG_TYPE "sink" ++ + STATISTIC(NumSunk, "Number of instructions sunk"); + STATISTIC(NumSinkIter, "Number of sinking iterations"); + + +commit edfd81d9656217cc9d14d7854b401bb3d5d559f7 +Author: Tom Stellard +Date: Fri Mar 21 15:51:51 2014 +0000 + + Sink: Don't sink static allocas from the entry block + + CodeGen treats allocas outside the entry block as dynamically sized + stack objects. + + llvm-svn: 204473 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 5e1e4564bba9..41073749abc7 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -216,6 +216,13 @@ bool Sinking::IsAcceptableTarget(Instruction *Inst, + /// instruction out of its current block into a successor. + bool Sinking::SinkInstruction(Instruction *Inst, + SmallPtrSet &Stores) { ++ ++ // Don't sink static alloca instructions. CodeGen assumes allocas outside the ++ // entry block are dynamically sized stack objects. ++ if (AllocaInst *AI = dyn_cast(Inst)) ++ if (AI->isStaticAlloca()) ++ return false; ++ + // Check if it's safe to move the instruction. + if (!isSafeToMove(Inst, AA, Stores)) + return false; + +commit cdf4788401afff02e12279fc1fded94d6180639c +Author: Chandler Carruth +Date: Sun Mar 9 03:16:01 2014 +0000 + + [C++11] Add range based accessors for the Use-Def chain of a Value. + + This requires a number of steps. + 1) Move value_use_iterator into the Value class as an implementation + detail + 2) Change it to actually be a *Use* iterator rather than a *User* + iterator. + 3) Add an adaptor which is a User iterator that always looks through the + Use to the User. + 4) Wrap these in Value::use_iterator and Value::user_iterator typedefs. + 5) Add the range adaptors as Value::uses() and Value::users(). + 6) Update *all* of the callers to correctly distinguish between whether + they wanted a use_iterator (and to explicitly dig out the User when + needed), or a user_iterator which makes the Use itself totally + opaque. + + Because #6 requires churning essentially everything that walked the + Use-Def chains, I went ahead and added all of the range adaptors and + switched them to range-based loops where appropriate. Also because the + renaming requires at least churning every line of code, it didn't make + any sense to split these up into multiple commits -- all of which would + touch all of the same lies of code. + + The result is still not quite optimal. The Value::use_iterator is a nice + regular iterator, but Value::user_iterator is an iterator over User*s + rather than over the User objects themselves. As a consequence, it fits + a bit awkwardly into the range-based world and it has the weird + extra-dereferencing 'operator->' that so many of our iterators have. + I think this could be fixed by providing something which transforms + a range of T&s into a range of T*s, but that *can* be separated into + another patch, and it isn't yet 100% clear whether this is the right + move. + + However, this change gets us most of the benefit and cleans up + a substantial amount of code around Use and User. =] + + llvm-svn: 203364 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 643a5957cf91..5e1e4564bba9 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -76,15 +76,14 @@ bool Sinking::AllUsesDominatedByBlock(Instruction *Inst, + // This may leave a referencing dbg_value in the original block, before + // the definition of the vreg. Dwarf generator handles this although the + // user might not get the right info at runtime. +- for (Value::use_iterator I = Inst->use_begin(), +- E = Inst->use_end(); I != E; ++I) { ++ for (Use &U : Inst->uses()) { + // Determine the block of the use. +- Instruction *UseInst = cast(*I); ++ Instruction *UseInst = cast(U.getUser()); + BasicBlock *UseBlock = UseInst->getParent(); + if (PHINode *PN = dyn_cast(UseInst)) { + // PHI nodes use the operand in the predecessor block, not the block with + // the PHI. +- unsigned Num = PHINode::getIncomingValueNumForOperand(I.getOperandNo()); ++ unsigned Num = PHINode::getIncomingValueNumForOperand(U.getOperandNo()); + UseBlock = PN->getIncomingBlock(Num); + } + // Check that it dominates. + +commit 3e4c697ca1314da24ac34e42293cc28d88fdc134 +Author: Craig Topper +Date: Wed Mar 5 09:10:37 2014 +0000 + + [C++11] Add 'override' keyword to virtual methods that override their base class. + + llvm-svn: 202953 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 287bd5b7d617..643a5957cf91 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -40,9 +40,9 @@ namespace { + initializeSinkingPass(*PassRegistry::getPassRegistry()); + } + +- virtual bool runOnFunction(Function &F); ++ bool runOnFunction(Function &F) override; + +- virtual void getAnalysisUsage(AnalysisUsage &AU) const { ++ void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesCFG(); + FunctionPass::getAnalysisUsage(AU); + AU.addRequired(); + +commit 1305dc3351d93e2377b538feff62ccf9518b0291 +Author: Chandler Carruth +Date: Tue Mar 4 11:45:46 2014 +0000 + + [Modules] Move CFG.h to the IR library as it defines graph traits over + IR types. + + llvm-svn: 202827 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index e500c3b24e71..287bd5b7d617 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -18,9 +18,9 @@ + #include "llvm/Analysis/AliasAnalysis.h" + #include "llvm/Analysis/LoopInfo.h" + #include "llvm/Analysis/ValueTracking.h" ++#include "llvm/IR/CFG.h" + #include "llvm/IR/Dominators.h" + #include "llvm/IR/IntrinsicInst.h" +-#include "llvm/Support/CFG.h" + #include "llvm/Support/Debug.h" + #include "llvm/Support/raw_ostream.h" + using namespace llvm; + +commit 73523021d0a97c150a76a5cf4a91e99cd03b9efb +Author: Chandler Carruth +Date: Mon Jan 13 13:07:17 2014 +0000 + + [PM] Split DominatorTree into a concrete analysis result object which + can be used by both the new pass manager and the old. + + This removes it from any of the virtual mess of the pass interfaces and + lets it derive cleanly from the DominatorTreeBase<> template. In turn, + tons of boilerplate interface can be nuked and it turns into a very + straightforward extension of the base DominatorTree interface. + + The old analysis pass is now a simple wrapper. The names and style of + this split should match the split between CallGraph and + CallGraphWrapperPass. All of the users of DominatorTree have been + updated to match using many of the same tricks as with CallGraph. The + goal is that the common type remains the resulting DominatorTree rather + than the pass. This will make subsequent work toward the new pass + manager significantly easier. + + Also in numerous places things became cleaner because I switched from + re-running the pass (!!! mid way through some other passes run!!!) to + directly recomputing the domtree. + + llvm-svn: 199104 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index d4c5c73c0332..e500c3b24e71 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -46,9 +46,9 @@ namespace { + AU.setPreservesCFG(); + FunctionPass::getAnalysisUsage(AU); + AU.addRequired(); +- AU.addRequired(); ++ AU.addRequired(); + AU.addRequired(); +- AU.addPreserved(); ++ AU.addPreserved(); + AU.addPreserved(); + } + private: +@@ -62,7 +62,7 @@ namespace { + char Sinking::ID = 0; + INITIALIZE_PASS_BEGIN(Sinking, "sink", "Code sinking", false, false) + INITIALIZE_PASS_DEPENDENCY(LoopInfo) +-INITIALIZE_PASS_DEPENDENCY(DominatorTree) ++INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) + INITIALIZE_AG_DEPENDENCY(AliasAnalysis) + INITIALIZE_PASS_END(Sinking, "sink", "Code sinking", false, false) + +@@ -95,7 +95,7 @@ bool Sinking::AllUsesDominatedByBlock(Instruction *Inst, + } + + bool Sinking::runOnFunction(Function &F) { +- DT = &getAnalysis(); ++ DT = &getAnalysis().getDomTree(); + LI = &getAnalysis(); + AA = &getAnalysis(); + + +commit 5ad5f15cffe022de72d0e710714f852ad8a1c6fe +Author: Chandler Carruth +Date: Mon Jan 13 09:26:24 2014 +0000 + + [cleanup] Move the Dominators.h and Verifier.h headers into the IR + directory. These passes are already defined in the IR library, and it + doesn't make any sense to have the headers in Analysis. + + Long term, I think there is going to be a much better way to divide + these matters. The dominators code should be fully separated into the + abstract graph algorithm and have that put in Support where it becomes + obvious that evn Clang's CFGBlock's can use it. Then the verifier can + manually construct dominance information from the Support-driven + interface while the Analysis library can provide a pass which both + caches, reconstructs, and supports a nice update API. + + But those are very long term, and so I don't want to leave the really + confusing structure until that day arrives. + + llvm-svn: 199082 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index a5096da46a08..d4c5c73c0332 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -16,9 +16,9 @@ + #include "llvm/Transforms/Scalar.h" + #include "llvm/ADT/Statistic.h" + #include "llvm/Analysis/AliasAnalysis.h" +-#include "llvm/Analysis/Dominators.h" + #include "llvm/Analysis/LoopInfo.h" + #include "llvm/Analysis/ValueTracking.h" ++#include "llvm/IR/Dominators.h" + #include "llvm/IR/IntrinsicInst.h" + #include "llvm/Support/CFG.h" + #include "llvm/Support/Debug.h" + +commit d48cdbf0c3ee31bcac2d8304da2ee5dc16c35056 +Author: Chandler Carruth +Date: Thu Jan 9 02:29:41 2014 +0000 + + Put the functionality for printing a value to a raw_ostream as an + operand into the Value interface just like the core print method is. + That gives a more conistent organization to the IR printing interfaces + -- they are all attached to the IR objects themselves. Also, update all + the users. + + This removes the 'Writer.h' header which contained only a single function + declaration. + + llvm-svn: 198836 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index cf8e5b75ab4d..a5096da46a08 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -20,7 +20,6 @@ + #include "llvm/Analysis/LoopInfo.h" + #include "llvm/Analysis/ValueTracking.h" + #include "llvm/IR/IntrinsicInst.h" +-#include "llvm/IR/Writer.h" + #include "llvm/Support/CFG.h" + #include "llvm/Support/Debug.h" + #include "llvm/Support/raw_ostream.h" +@@ -259,9 +258,9 @@ bool Sinking::SinkInstruction(Instruction *Inst, + return false; + + DEBUG(dbgs() << "Sink" << *Inst << " ("; +- WriteAsOperand(dbgs(), Inst->getParent(), false); ++ Inst->getParent()->printAsOperand(dbgs(), false); + dbgs() << " -> "; +- WriteAsOperand(dbgs(), SuccToSinkTo, false); ++ SuccToSinkTo->printAsOperand(dbgs(), false); + dbgs() << ")\n"); + + // Move the instruction. + +commit 9aca918df941788c12f9bef50e5ca0d6f57d2429 +Author: Chandler Carruth +Date: Tue Jan 7 12:34:26 2014 +0000 + + Move the LLVM IR asm writer header files into the IR directory, as they + are part of the core IR library in order to support dumping and other + basic functionality. + + Rename the 'Assembly' include directory to 'AsmParser' to match the + library name and the only functionality left their -- printing has been + in the core IR library for quite some time. + + Update all of the #includes to match. + + All of this started because I wanted to have the layering in good shape + before I started adding support for printing LLVM IR using the new pass + infrastructure, and commandline support for the new pass infrastructure. + + llvm-svn: 198688 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index d4595bb373e6..cf8e5b75ab4d 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -19,8 +19,8 @@ + #include "llvm/Analysis/Dominators.h" + #include "llvm/Analysis/LoopInfo.h" + #include "llvm/Analysis/ValueTracking.h" +-#include "llvm/Assembly/Writer.h" + #include "llvm/IR/IntrinsicInst.h" ++#include "llvm/IR/Writer.h" + #include "llvm/Support/CFG.h" + #include "llvm/Support/Debug.h" + #include "llvm/Support/raw_ostream.h" + +commit 9fb823bbd484eebe4f8756338b14ed3725261997 +Author: Chandler Carruth +Date: Wed Jan 2 11:36:10 2013 +0000 + + Move all of the header files which are involved in modelling the LLVM IR + into their new header subdirectory: include/llvm/IR. This matches the + directory structure of lib, and begins to correct a long standing point + of file layout clutter in LLVM. + + There are still more header files to move here, but I wanted to handle + them in separate commits to make tracking what files make sense at each + layer easier. + + The only really questionable files here are the target intrinsic + tablegen files. But that's a battle I'd rather not fight today. + + I've updated both CMake and Makefile build systems (I think, and my + tests think, but I may have missed something). + + I've also re-sorted the includes throughout the project. I'll be + committing updates to Clang, DragonEgg, and Polly momentarily. + + llvm-svn: 171366 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index cde9c178ad8c..d4595bb373e6 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -20,7 +20,7 @@ + #include "llvm/Analysis/LoopInfo.h" + #include "llvm/Analysis/ValueTracking.h" + #include "llvm/Assembly/Writer.h" +-#include "llvm/IntrinsicInst.h" ++#include "llvm/IR/IntrinsicInst.h" + #include "llvm/Support/CFG.h" + #include "llvm/Support/Debug.h" + #include "llvm/Support/raw_ostream.h" + +commit ed0881b2a67c530079dfd4141dbd9a899e6c1a7c +Author: Chandler Carruth +Date: Mon Dec 3 16:50:05 2012 +0000 + + Use the new script to sort the includes of every file under lib. + + Sooooo many of these had incorrect or strange main module includes. + I have manually inspected all of these, and fixed the main module + include to be the nearest plausible thing I could find. If you own or + care about any of these source files, I encourage you to take some time + and check that these edits were sensible. I can't have broken anything + (I strictly added headers, and reordered them, never removed), but they + may not be the headers you'd really like to identify as containing the + API being implemented. + + Many forward declarations and missing includes were added to a header + files to allow them to parse cleanly when included first. The main + module rule does in fact have its merits. =] + + llvm-svn: 169131 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 34f1d6c6221a..cde9c178ad8c 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -14,13 +14,13 @@ + + #define DEBUG_TYPE "sink" + #include "llvm/Transforms/Scalar.h" +-#include "llvm/IntrinsicInst.h" ++#include "llvm/ADT/Statistic.h" ++#include "llvm/Analysis/AliasAnalysis.h" + #include "llvm/Analysis/Dominators.h" + #include "llvm/Analysis/LoopInfo.h" +-#include "llvm/Analysis/AliasAnalysis.h" + #include "llvm/Analysis/ValueTracking.h" + #include "llvm/Assembly/Writer.h" +-#include "llvm/ADT/Statistic.h" ++#include "llvm/IntrinsicInst.h" + #include "llvm/Support/CFG.h" + #include "llvm/Support/Debug.h" + #include "llvm/Support/raw_ostream.h" + +commit 465834c85f97666559d7acae8c028cb4ee3012f6 +Author: Nadav Rotem +Date: Tue Jul 24 10:51:42 2012 +0000 + + Clean whitespaces. + + llvm-svn: 160668 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index d6ec65169dee..34f1d6c6221a 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -40,9 +40,9 @@ namespace { + Sinking() : FunctionPass(ID) { + initializeSinkingPass(*PassRegistry::getPassRegistry()); + } +- ++ + virtual bool runOnFunction(Function &F); +- ++ + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + FunctionPass::getAnalysisUsage(AU); +@@ -59,7 +59,7 @@ namespace { + bool IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo) const; + }; + } // end anonymous namespace +- ++ + char Sinking::ID = 0; + INITIALIZE_PASS_BEGIN(Sinking, "sink", "Code sinking", false, false) + INITIALIZE_PASS_DEPENDENCY(LoopInfo) +@@ -71,7 +71,7 @@ FunctionPass *llvm::createSinkingPass() { return new Sinking(); } + + /// AllUsesDominatedByBlock - Return true if all uses of the specified value + /// occur in blocks dominated by the specified block. +-bool Sinking::AllUsesDominatedByBlock(Instruction *Inst, ++bool Sinking::AllUsesDominatedByBlock(Instruction *Inst, + BasicBlock *BB) const { + // Ignoring debug uses is necessary so debug info doesn't affect the code. + // This may leave a referencing dbg_value in the original block, before +@@ -101,18 +101,18 @@ bool Sinking::runOnFunction(Function &F) { + AA = &getAnalysis(); + + bool MadeChange, EverMadeChange = false; +- ++ + do { + MadeChange = false; + DEBUG(dbgs() << "Sinking iteration " << NumSinkIter << "\n"); + // Process all basic blocks. +- for (Function::iterator I = F.begin(), E = F.end(); ++ for (Function::iterator I = F.begin(), E = F.end(); + I != E; ++I) + MadeChange |= ProcessBlock(*I); + EverMadeChange |= MadeChange; + NumSinkIter++; + } while (MadeChange); +- ++ + return EverMadeChange; + } + +@@ -121,8 +121,8 @@ bool Sinking::ProcessBlock(BasicBlock &BB) { + if (BB.getTerminator()->getNumSuccessors() <= 1 || BB.empty()) return false; + + // Don't bother sinking code out of unreachable blocks. In addition to being +- // unprofitable, it can also lead to infinite looping, because in an unreachable +- // loop there may be nowhere to stop. ++ // unprofitable, it can also lead to infinite looping, because in an ++ // unreachable loop there may be nowhere to stop. + if (!DT->isReachableFromEntry(&BB)) return false; + + bool MadeChange = false; +@@ -134,7 +134,7 @@ bool Sinking::ProcessBlock(BasicBlock &BB) { + SmallPtrSet Stores; + do { + Instruction *Inst = I; // The instruction to sink. +- ++ + // Predecrement I (if it's not begin) so that it isn't invalidated by + // sinking. + ProcessedBegin = I == BB.begin(); +@@ -146,10 +146,10 @@ bool Sinking::ProcessBlock(BasicBlock &BB) { + + if (SinkInstruction(Inst, Stores)) + ++NumSunk, MadeChange = true; +- ++ + // If we just processed the first instruction in the block, we're done. + } while (!ProcessedBegin); +- ++ + return MadeChange; + } + +@@ -177,16 +177,17 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, + + /// IsAcceptableTarget - Return true if it is possible to sink the instruction + /// in the specified basic block. +-bool Sinking::IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo) const { ++bool Sinking::IsAcceptableTarget(Instruction *Inst, ++ BasicBlock *SuccToSinkTo) const { + assert(Inst && "Instruction to be sunk is null"); + assert(SuccToSinkTo && "Candidate sink target is null"); +- ++ + // It is not possible to sink an instruction into its own block. This can + // happen with loops. + if (Inst->getParent() == SuccToSinkTo) + return false; +- +- // If the block has multiple predecessors, this would introduce computation ++ ++ // If the block has multiple predecessors, this would introduce computation + // on different code paths. We could split the critical edge, but for now we + // just punt. + // FIXME: Split critical edges if not backedges. +@@ -195,18 +196,19 @@ bool Sinking::IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo) co + // other code paths. + if (!isSafeToSpeculativelyExecute(Inst)) + return false; +- ++ + // We don't want to sink across a critical edge if we don't dominate the + // successor. We could be introducing calculations to new code paths. + if (!DT->dominates(Inst->getParent(), SuccToSinkTo)) + return false; +- ++ + // Don't sink instructions into a loop. +- Loop *succ = LI->getLoopFor(SuccToSinkTo), *cur = LI->getLoopFor(Inst->getParent()); ++ Loop *succ = LI->getLoopFor(SuccToSinkTo); ++ Loop *cur = LI->getLoopFor(Inst->getParent()); + if (succ != 0 && succ != cur) + return false; + } +- ++ + // Finally, check that all the uses of the instruction are actually + // dominated by the candidate + return AllUsesDominatedByBlock(Inst, SuccToSinkTo); +@@ -219,7 +221,7 @@ bool Sinking::SinkInstruction(Instruction *Inst, + // Check if it's safe to move the instruction. + if (!isSafeToMove(Inst, AA, Stores)) + return false; +- ++ + // FIXME: This should include support for sinking instructions within the + // block they are currently in to shorten the live ranges. We often get + // instructions sunk into the top of a large block, but it would be better to +@@ -227,41 +229,41 @@ bool Sinking::SinkInstruction(Instruction *Inst, + // be careful not to *increase* register pressure though, e.g. sinking + // "x = y + z" down if it kills y and z would increase the live ranges of y + // and z and only shrink the live range of x. +- ++ + // SuccToSinkTo - This is the successor to sink this instruction to, once we + // decide. + BasicBlock *SuccToSinkTo = 0; +- ++ + // Instructions can only be sunk if all their uses are in blocks + // dominated by one of the successors. + // Look at all the postdominators and see if we can sink it in one. + DomTreeNode *DTN = DT->getNode(Inst->getParent()); +- for (DomTreeNode::iterator I = DTN->begin(), E = DTN->end(); ++ for (DomTreeNode::iterator I = DTN->begin(), E = DTN->end(); + I != E && SuccToSinkTo == 0; ++I) { + BasicBlock *Candidate = (*I)->getBlock(); +- if ((*I)->getIDom()->getBlock() == Inst->getParent() && ++ if ((*I)->getIDom()->getBlock() == Inst->getParent() && + IsAcceptableTarget(Inst, Candidate)) + SuccToSinkTo = Candidate; + } + +- // If no suitable postdominator was found, look at all the successors and ++ // If no suitable postdominator was found, look at all the successors and + // decide which one we should sink to, if any. +- for (succ_iterator I = succ_begin(Inst->getParent()), ++ for (succ_iterator I = succ_begin(Inst->getParent()), + E = succ_end(Inst->getParent()); I != E && SuccToSinkTo == 0; ++I) { + if (IsAcceptableTarget(Inst, *I)) + SuccToSinkTo = *I; + } +- ++ + // If we couldn't find a block to sink to, ignore this instruction. + if (SuccToSinkTo == 0) + return false; +- ++ + DEBUG(dbgs() << "Sink" << *Inst << " ("; +- WriteAsOperand(dbgs(), Inst->getParent(), false); ++ WriteAsOperand(dbgs(), Inst->getParent(), false); + dbgs() << " -> "; +- WriteAsOperand(dbgs(), SuccToSinkTo, false); ++ WriteAsOperand(dbgs(), SuccToSinkTo, false); + dbgs() << ")\n"); +- ++ + // Move the instruction. + Inst->moveBefore(SuccToSinkTo->getFirstInsertionPt()); + return true; + +commit 339bb61e32593aa393ceda3c7168c24814a27161 +Author: Duncan Sands +Date: Thu May 31 08:09:49 2012 +0000 + + Enhance the sinking code to handle diamond patterns. Patch by + Carlo Alberto Ferraris. + + llvm-svn: 157736 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index ef65c0a3a907..d6ec65169dee 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -27,6 +27,7 @@ + using namespace llvm; + + STATISTIC(NumSunk, "Number of instructions sunk"); ++STATISTIC(NumSinkIter, "Number of sinking iterations"); + + namespace { + class Sinking : public FunctionPass { +@@ -55,6 +56,7 @@ namespace { + bool ProcessBlock(BasicBlock &BB); + bool SinkInstruction(Instruction *I, SmallPtrSet &Stores); + bool AllUsesDominatedByBlock(Instruction *Inst, BasicBlock *BB) const; ++ bool IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo) const; + }; + } // end anonymous namespace + +@@ -98,20 +100,19 @@ bool Sinking::runOnFunction(Function &F) { + LI = &getAnalysis(); + AA = &getAnalysis(); + +- bool EverMadeChange = false; ++ bool MadeChange, EverMadeChange = false; + +- while (1) { +- bool MadeChange = false; +- ++ do { ++ MadeChange = false; ++ DEBUG(dbgs() << "Sinking iteration " << NumSinkIter << "\n"); + // Process all basic blocks. + for (Function::iterator I = F.begin(), E = F.end(); + I != E; ++I) + MadeChange |= ProcessBlock(*I); +- +- // If this iteration over the code changed anything, keep iterating. +- if (!MadeChange) break; +- EverMadeChange = true; +- } ++ EverMadeChange |= MadeChange; ++ NumSinkIter++; ++ } while (MadeChange); ++ + return EverMadeChange; + } + +@@ -174,6 +175,43 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, + return true; + } + ++/// IsAcceptableTarget - Return true if it is possible to sink the instruction ++/// in the specified basic block. ++bool Sinking::IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo) const { ++ assert(Inst && "Instruction to be sunk is null"); ++ assert(SuccToSinkTo && "Candidate sink target is null"); ++ ++ // It is not possible to sink an instruction into its own block. This can ++ // happen with loops. ++ if (Inst->getParent() == SuccToSinkTo) ++ return false; ++ ++ // If the block has multiple predecessors, this would introduce computation ++ // on different code paths. We could split the critical edge, but for now we ++ // just punt. ++ // FIXME: Split critical edges if not backedges. ++ if (SuccToSinkTo->getUniquePredecessor() != Inst->getParent()) { ++ // We cannot sink a load across a critical edge - there may be stores in ++ // other code paths. ++ if (!isSafeToSpeculativelyExecute(Inst)) ++ return false; ++ ++ // We don't want to sink across a critical edge if we don't dominate the ++ // successor. We could be introducing calculations to new code paths. ++ if (!DT->dominates(Inst->getParent(), SuccToSinkTo)) ++ return false; ++ ++ // Don't sink instructions into a loop. ++ Loop *succ = LI->getLoopFor(SuccToSinkTo), *cur = LI->getLoopFor(Inst->getParent()); ++ if (succ != 0 && succ != cur) ++ return false; ++ } ++ ++ // Finally, check that all the uses of the instruction are actually ++ // dominated by the candidate ++ return AllUsesDominatedByBlock(Inst, SuccToSinkTo); ++} ++ + /// SinkInstruction - Determine whether it is safe to sink the specified machine + /// instruction out of its current block into a successor. + bool Sinking::SinkInstruction(Instruction *Inst, +@@ -190,85 +228,41 @@ bool Sinking::SinkInstruction(Instruction *Inst, + // "x = y + z" down if it kills y and z would increase the live ranges of y + // and z and only shrink the live range of x. + +- // Loop over all the operands of the specified instruction. If there is +- // anything we can't handle, bail out. +- BasicBlock *ParentBlock = Inst->getParent(); +- + // SuccToSinkTo - This is the successor to sink this instruction to, once we + // decide. + BasicBlock *SuccToSinkTo = 0; + +- // FIXME: This picks a successor to sink into based on having one +- // successor that dominates all the uses. However, there are cases where +- // sinking can happen but where the sink point isn't a successor. For +- // example: +- // x = computation +- // if () {} else {} +- // use x +- // the instruction could be sunk over the whole diamond for the +- // if/then/else (or loop, etc), allowing it to be sunk into other blocks +- // after that. +- + // Instructions can only be sunk if all their uses are in blocks + // dominated by one of the successors. +- // Look at all the successors and decide which one +- // we should sink to. +- for (succ_iterator SI = succ_begin(ParentBlock), +- E = succ_end(ParentBlock); SI != E; ++SI) { +- if (AllUsesDominatedByBlock(Inst, *SI)) { +- SuccToSinkTo = *SI; +- break; +- } ++ // Look at all the postdominators and see if we can sink it in one. ++ DomTreeNode *DTN = DT->getNode(Inst->getParent()); ++ for (DomTreeNode::iterator I = DTN->begin(), E = DTN->end(); ++ I != E && SuccToSinkTo == 0; ++I) { ++ BasicBlock *Candidate = (*I)->getBlock(); ++ if ((*I)->getIDom()->getBlock() == Inst->getParent() && ++ IsAcceptableTarget(Inst, Candidate)) ++ SuccToSinkTo = Candidate; ++ } ++ ++ // If no suitable postdominator was found, look at all the successors and ++ // decide which one we should sink to, if any. ++ for (succ_iterator I = succ_begin(Inst->getParent()), ++ E = succ_end(Inst->getParent()); I != E && SuccToSinkTo == 0; ++I) { ++ if (IsAcceptableTarget(Inst, *I)) ++ SuccToSinkTo = *I; + } + + // If we couldn't find a block to sink to, ignore this instruction. + if (SuccToSinkTo == 0) + return false; + +- // It is not possible to sink an instruction into its own block. This can +- // happen with loops. +- if (Inst->getParent() == SuccToSinkTo) +- return false; +- +- DEBUG(dbgs() << "Sink instr " << *Inst); +- DEBUG(dbgs() << "to block "; +- WriteAsOperand(dbgs(), SuccToSinkTo, false)); +- +- // If the block has multiple predecessors, this would introduce computation on +- // a path that it doesn't already exist. We could split the critical edge, +- // but for now we just punt. +- // FIXME: Split critical edges if not backedges. +- if (SuccToSinkTo->getUniquePredecessor() != ParentBlock) { +- // We cannot sink a load across a critical edge - there may be stores in +- // other code paths. +- if (!isSafeToSpeculativelyExecute(Inst)) { +- DEBUG(dbgs() << " *** PUNTING: Wont sink load along critical edge.\n"); +- return false; +- } +- +- // We don't want to sink across a critical edge if we don't dominate the +- // successor. We could be introducing calculations to new code paths. +- if (!DT->dominates(ParentBlock, SuccToSinkTo)) { +- DEBUG(dbgs() << " *** PUNTING: Critical edge found\n"); +- return false; +- } +- +- // Don't sink instructions into a loop. +- if (LI->isLoopHeader(SuccToSinkTo)) { +- DEBUG(dbgs() << " *** PUNTING: Loop header found\n"); +- return false; +- } +- +- // Otherwise we are OK with sinking along a critical edge. +- DEBUG(dbgs() << "Sinking along critical edge.\n"); +- } +- +- // Determine where to insert into. Skip phi nodes. +- BasicBlock::iterator InsertPos = SuccToSinkTo->begin(); +- while (InsertPos != SuccToSinkTo->end() && isa(InsertPos)) +- ++InsertPos; ++ DEBUG(dbgs() << "Sink" << *Inst << " ("; ++ WriteAsOperand(dbgs(), Inst->getParent(), false); ++ dbgs() << " -> "; ++ WriteAsOperand(dbgs(), SuccToSinkTo, false); ++ dbgs() << ")\n"); + + // Move the instruction. +- Inst->moveBefore(InsertPos); ++ Inst->moveBefore(SuccToSinkTo->getFirstInsertionPt()); + return true; + } + +commit 75d7d5e988539819d596f345d99c26a7aa3bd09b +Author: Dan Gohman +Date: Wed Dec 14 23:49:11 2011 +0000 + + Move Instruction::isSafeToSpeculativelyExecute out of VMCore and + into Analysis as a standalone function, since there's no need for + it to be in VMCore. Also, update it to use isKnownNonZero and + other goodies available in Analysis, making it more precise, + enabling more aggressive optimization. + + llvm-svn: 146610 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index c83f56c4d2d7..ef65c0a3a907 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -18,6 +18,7 @@ + #include "llvm/Analysis/Dominators.h" + #include "llvm/Analysis/LoopInfo.h" + #include "llvm/Analysis/AliasAnalysis.h" ++#include "llvm/Analysis/ValueTracking.h" + #include "llvm/Assembly/Writer.h" + #include "llvm/ADT/Statistic.h" + #include "llvm/Support/CFG.h" +@@ -240,7 +241,7 @@ bool Sinking::SinkInstruction(Instruction *Inst, + if (SuccToSinkTo->getUniquePredecessor() != ParentBlock) { + // We cannot sink a load across a critical edge - there may be stores in + // other code paths. +- if (!Inst->isSafeToSpeculativelyExecute()) { ++ if (!isSafeToSpeculativelyExecute(Inst)) { + DEBUG(dbgs() << " *** PUNTING: Wont sink load along critical edge.\n"); + return false; + } + +commit 71f5c2f1585e4bec0cc676e0476738af999dba70 +Author: Eli Friedman +Date: Thu Sep 1 21:21:24 2011 +0000 + + Fix an issue with the IR sink pass found by inspection. (I'm not sure anyone is actually using this, but might as well fix it since I found the issue.) + + llvm-svn: 138965 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 705f44204900..c83f56c4d2d7 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -153,9 +153,13 @@ bool Sinking::ProcessBlock(BasicBlock &BB) { + + static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, + SmallPtrSet &Stores) { +- if (LoadInst *L = dyn_cast(Inst)) { +- if (L->isVolatile()) return false; + ++ if (Inst->mayWriteToMemory()) { ++ Stores.insert(Inst); ++ return false; ++ } ++ ++ if (LoadInst *L = dyn_cast(Inst)) { + AliasAnalysis::Location Loc = AA->getLocation(L); + for (SmallPtrSet::iterator I = Stores.begin(), + E = Stores.end(); I != E; ++I) +@@ -163,11 +167,6 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, + return false; + } + +- if (Inst->mayWriteToMemory()) { +- Stores.insert(Inst); +- return false; +- } +- + if (isa(Inst) || isa(Inst)) + return false; + + +commit 65316d674914067bd0b6da080f8a7cf7c1aa0e78 +Author: Dan Gohman +Date: Thu Nov 11 21:50:19 2010 +0000 + + Add helper functions for computing the Location of load, store, + and vaarg instructions. + + llvm-svn: 118845 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index a54ba8e0ae54..705f44204900 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -15,7 +15,6 @@ + #define DEBUG_TYPE "sink" + #include "llvm/Transforms/Scalar.h" + #include "llvm/IntrinsicInst.h" +-#include "llvm/LLVMContext.h" + #include "llvm/Analysis/Dominators.h" + #include "llvm/Analysis/LoopInfo.h" + #include "llvm/Analysis/AliasAnalysis.h" +@@ -157,10 +156,7 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, + if (LoadInst *L = dyn_cast(Inst)) { + if (L->isVolatile()) return false; + +- Value *Ptr = L->getPointerOperand(); +- uint64_t Size = AA->getTypeStoreSize(L->getType()); +- const MDNode *TBAAInfo = L->getMetadata(LLVMContext::MD_tbaa); +- AliasAnalysis::Location Loc(Ptr, Size, TBAAInfo); ++ AliasAnalysis::Location Loc = AA->getLocation(L); + for (SmallPtrSet::iterator I = Stores.begin(), + E = Stores.end(); I != E; ++I) + if (AA->getModRefInfo(*I, Loc) & AliasAnalysis::Mod) + +commit 0cc4c7516e2e5b1feaa9850de03615b6329ef919 +Author: Dan Gohman +Date: Thu Nov 11 16:21:47 2010 +0000 + + Make Sink tbaa-aware. + + llvm-svn: 118788 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index d6f1e93a812d..a54ba8e0ae54 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -15,6 +15,7 @@ + #define DEBUG_TYPE "sink" + #include "llvm/Transforms/Scalar.h" + #include "llvm/IntrinsicInst.h" ++#include "llvm/LLVMContext.h" + #include "llvm/Analysis/Dominators.h" + #include "llvm/Analysis/LoopInfo.h" + #include "llvm/Analysis/AliasAnalysis.h" +@@ -158,9 +159,11 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, + + Value *Ptr = L->getPointerOperand(); + uint64_t Size = AA->getTypeStoreSize(L->getType()); ++ const MDNode *TBAAInfo = L->getMetadata(LLVMContext::MD_tbaa); ++ AliasAnalysis::Location Loc(Ptr, Size, TBAAInfo); + for (SmallPtrSet::iterator I = Stores.begin(), + E = Stores.end(); I != E; ++I) +- if (AA->getModRefInfo(*I, Ptr, Size) & AliasAnalysis::Mod) ++ if (AA->getModRefInfo(*I, Loc) & AliasAnalysis::Mod) + return false; + } + + +commit c3b4ea7b7d7e1c6f2e29ef3c85f798d94741111a +Author: Dan Gohman +Date: Thu Nov 11 16:20:28 2010 +0000 + + It's safe to sink some instructions which are not safe to speculatively + execute. Make Sink's predicate more precise. + + llvm-svn: 118787 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 1aca908267b4..d6f1e93a812d 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -169,7 +169,10 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, + return false; + } + +- return Inst->isSafeToSpeculativelyExecute(); ++ if (isa(Inst) || isa(Inst)) ++ return false; ++ ++ return true; + } + + /// SinkInstruction - Determine whether it is safe to sink the specified machine + +commit f372cf869b7795d72843fb3a097af9d03b5c2b42 +Author: Dan Gohman +Date: Tue Oct 19 22:54:46 2010 +0000 + + Reapply r116831 and r116839, converting AliasAnalysis to use + uint64_t, plus fixes for places I missed before. + + llvm-svn: 116875 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 7306ee5e2e45..1aca908267b4 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -157,7 +157,7 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, + if (L->isVolatile()) return false; + + Value *Ptr = L->getPointerOperand(); +- unsigned Size = AA->getTypeStoreSize(L->getType()); ++ uint64_t Size = AA->getTypeStoreSize(L->getType()); + for (SmallPtrSet::iterator I = Stores.begin(), + E = Stores.end(); I != E; ++I) + if (AA->getModRefInfo(*I, Ptr, Size) & AliasAnalysis::Mod) + +commit 6c18d1aac08df0143d9a9810261421faeac81d4a +Author: Owen Anderson +Date: Tue Oct 19 17:21:58 2010 +0000 + + Get rid of static constructors for pass registration. Instead, every pass exposes an initializeMyPassFunction(), which + must be called in the pass's constructor. This function uses static dependency declarations to recursively initialize + the pass's dependencies. + + Clients that only create passes through the createFooPass() APIs will require no changes. Clients that want to use the + CommandLine options for passes will need to manually call the appropriate initialization functions in PassInitialization.h + before parsing commandline arguments. + + I have tested this with all standard configurations of clang and llvm-gcc on Darwin. It is possible that there are problems + with the static dependencies that will only be visible with non-standard options. If you encounter any crash in pass + registration/creation, please send the testcase to me directly. + + llvm-svn: 116820 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 0071428354e6..7306ee5e2e45 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -35,7 +35,9 @@ namespace { + + public: + static char ID; // Pass identification +- Sinking() : FunctionPass(ID) {} ++ Sinking() : FunctionPass(ID) { ++ initializeSinkingPass(*PassRegistry::getPassRegistry()); ++ } + + virtual bool runOnFunction(Function &F); + + +commit 8ac477ffb509943c940ce37f45b8429388dfdf58 +Author: Owen Anderson +Date: Tue Oct 12 19:48:12 2010 +0000 + + Begin adding static dependence information to passes, which will allow us to + perform initialization without static constructors AND without explicit initialization + by the client. For the moment, passes are required to initialize both their + (potential) dependencies and any passes they preserve. I hope to be able to relax + the latter requirement in the future. + + llvm-svn: 116334 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 6dc52a6f8e71..0071428354e6 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -56,7 +56,11 @@ namespace { + } // end anonymous namespace + + char Sinking::ID = 0; +-INITIALIZE_PASS(Sinking, "sink", "Code sinking", false, false) ++INITIALIZE_PASS_BEGIN(Sinking, "sink", "Code sinking", false, false) ++INITIALIZE_PASS_DEPENDENCY(LoopInfo) ++INITIALIZE_PASS_DEPENDENCY(DominatorTree) ++INITIALIZE_AG_DEPENDENCY(AliasAnalysis) ++INITIALIZE_PASS_END(Sinking, "sink", "Code sinking", false, false) + + FunctionPass *llvm::createSinkingPass() { return new Sinking(); } + + +commit df7a4f2515ce59b487c24e8bb8ea98c10b3edabf +Author: Owen Anderson +Date: Thu Oct 7 22:25:06 2010 +0000 + + Now with fewer extraneous semicolons! + + llvm-svn: 115996 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 95d3dedfb62d..6dc52a6f8e71 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -56,7 +56,7 @@ namespace { + } // end anonymous namespace + + char Sinking::ID = 0; +-INITIALIZE_PASS(Sinking, "sink", "Code sinking", false, false); ++INITIALIZE_PASS(Sinking, "sink", "Code sinking", false, false) + + FunctionPass *llvm::createSinkingPass() { return new Sinking(); } + + +commit a7aed18624f7783b7c31b06069c43bec89f1813f +Author: Owen Anderson +Date: Fri Aug 6 18:33:48 2010 +0000 + + Reapply r110396, with fixes to appease the Linux buildbot gods. + + llvm-svn: 110460 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 2448312673ba..95d3dedfb62d 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -35,7 +35,7 @@ namespace { + + public: + static char ID; // Pass identification +- Sinking() : FunctionPass(&ID) {} ++ Sinking() : FunctionPass(ID) {} + + virtual bool runOnFunction(Function &F); + + +commit bda59bd247b1153e4bc19f85dee4cb594b9c2b32 +Author: Owen Anderson +Date: Fri Aug 6 00:23:35 2010 +0000 + + Revert r110396 to fix buildbots. + + llvm-svn: 110410 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 95d3dedfb62d..2448312673ba 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -35,7 +35,7 @@ namespace { + + public: + static char ID; // Pass identification +- Sinking() : FunctionPass(ID) {} ++ Sinking() : FunctionPass(&ID) {} + + virtual bool runOnFunction(Function &F); + + +commit 755aceb5d0df842b5132052d474c361b5605aedb +Author: Owen Anderson +Date: Thu Aug 5 23:42:04 2010 +0000 + + Don't use PassInfo* as a type identifier for passes. Instead, use the address of the static + ID member as the sole unique type identifier. Clean up APIs related to this change. + + llvm-svn: 110396 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index 2448312673ba..95d3dedfb62d 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -35,7 +35,7 @@ namespace { + + public: + static char ID; // Pass identification +- Sinking() : FunctionPass(&ID) {} ++ Sinking() : FunctionPass(ID) {} + + virtual bool runOnFunction(Function &F); + + +commit a57b97e7e7d4bd44ebc90c743e6db318fa5348d6 +Author: Owen Anderson +Date: Wed Jul 21 22:09:45 2010 +0000 + + Fix batch of converting RegisterPass<> to INTIALIZE_PASS(). + + llvm-svn: 109045 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +index b88ba4850509..2448312673ba 100644 +--- a/llvm/lib/Transforms/Scalar/Sink.cpp ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -56,8 +56,7 @@ namespace { + } // end anonymous namespace + + char Sinking::ID = 0; +-static RegisterPass +-X("sink", "Code sinking"); ++INITIALIZE_PASS(Sinking, "sink", "Code sinking", false, false); + + FunctionPass *llvm::createSinkingPass() { return new Sinking(); } + + +commit 5d5b8b1b8c8719d0ac362b8bc12957fc79de4595 +Author: Dan Gohman +Date: Fri May 7 15:40:13 2010 +0000 + + Add an LLVM IR version of code sinking. This uses the same simple algorithm + as MachineSink, but it isn't constrained by MachineInstr-level details. + + llvm-svn: 103257 + +diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp +new file mode 100644 +index 000000000000..b88ba4850509 +--- /dev/null ++++ b/llvm/lib/Transforms/Scalar/Sink.cpp +@@ -0,0 +1,267 @@ ++//===-- Sink.cpp - Code Sinking -------------------------------------------===// ++// ++// The LLVM Compiler Infrastructure ++// ++// This file is distributed under the University of Illinois Open Source ++// License. See LICENSE.TXT for details. ++// ++//===----------------------------------------------------------------------===// ++// ++// This pass moves instructions into successor blocks, when possible, so that ++// they aren't executed on paths where their results aren't needed. ++// ++//===----------------------------------------------------------------------===// ++ ++#define DEBUG_TYPE "sink" ++#include "llvm/Transforms/Scalar.h" ++#include "llvm/IntrinsicInst.h" ++#include "llvm/Analysis/Dominators.h" ++#include "llvm/Analysis/LoopInfo.h" ++#include "llvm/Analysis/AliasAnalysis.h" ++#include "llvm/Assembly/Writer.h" ++#include "llvm/ADT/Statistic.h" ++#include "llvm/Support/CFG.h" ++#include "llvm/Support/Debug.h" ++#include "llvm/Support/raw_ostream.h" ++using namespace llvm; ++ ++STATISTIC(NumSunk, "Number of instructions sunk"); ++ ++namespace { ++ class Sinking : public FunctionPass { ++ DominatorTree *DT; ++ LoopInfo *LI; ++ AliasAnalysis *AA; ++ ++ public: ++ static char ID; // Pass identification ++ Sinking() : FunctionPass(&ID) {} ++ ++ virtual bool runOnFunction(Function &F); ++ ++ virtual void getAnalysisUsage(AnalysisUsage &AU) const { ++ AU.setPreservesCFG(); ++ FunctionPass::getAnalysisUsage(AU); ++ AU.addRequired(); ++ AU.addRequired(); ++ AU.addRequired(); ++ AU.addPreserved(); ++ AU.addPreserved(); ++ } ++ private: ++ bool ProcessBlock(BasicBlock &BB); ++ bool SinkInstruction(Instruction *I, SmallPtrSet &Stores); ++ bool AllUsesDominatedByBlock(Instruction *Inst, BasicBlock *BB) const; ++ }; ++} // end anonymous namespace ++ ++char Sinking::ID = 0; ++static RegisterPass ++X("sink", "Code sinking"); ++ ++FunctionPass *llvm::createSinkingPass() { return new Sinking(); } ++ ++/// AllUsesDominatedByBlock - Return true if all uses of the specified value ++/// occur in blocks dominated by the specified block. ++bool Sinking::AllUsesDominatedByBlock(Instruction *Inst, ++ BasicBlock *BB) const { ++ // Ignoring debug uses is necessary so debug info doesn't affect the code. ++ // This may leave a referencing dbg_value in the original block, before ++ // the definition of the vreg. Dwarf generator handles this although the ++ // user might not get the right info at runtime. ++ for (Value::use_iterator I = Inst->use_begin(), ++ E = Inst->use_end(); I != E; ++I) { ++ // Determine the block of the use. ++ Instruction *UseInst = cast(*I); ++ BasicBlock *UseBlock = UseInst->getParent(); ++ if (PHINode *PN = dyn_cast(UseInst)) { ++ // PHI nodes use the operand in the predecessor block, not the block with ++ // the PHI. ++ unsigned Num = PHINode::getIncomingValueNumForOperand(I.getOperandNo()); ++ UseBlock = PN->getIncomingBlock(Num); ++ } ++ // Check that it dominates. ++ if (!DT->dominates(BB, UseBlock)) ++ return false; ++ } ++ return true; ++} ++ ++bool Sinking::runOnFunction(Function &F) { ++ DT = &getAnalysis(); ++ LI = &getAnalysis(); ++ AA = &getAnalysis(); ++ ++ bool EverMadeChange = false; ++ ++ while (1) { ++ bool MadeChange = false; ++ ++ // Process all basic blocks. ++ for (Function::iterator I = F.begin(), E = F.end(); ++ I != E; ++I) ++ MadeChange |= ProcessBlock(*I); ++ ++ // If this iteration over the code changed anything, keep iterating. ++ if (!MadeChange) break; ++ EverMadeChange = true; ++ } ++ return EverMadeChange; ++} ++ ++bool Sinking::ProcessBlock(BasicBlock &BB) { ++ // Can't sink anything out of a block that has less than two successors. ++ if (BB.getTerminator()->getNumSuccessors() <= 1 || BB.empty()) return false; ++ ++ // Don't bother sinking code out of unreachable blocks. In addition to being ++ // unprofitable, it can also lead to infinite looping, because in an unreachable ++ // loop there may be nowhere to stop. ++ if (!DT->isReachableFromEntry(&BB)) return false; ++ ++ bool MadeChange = false; ++ ++ // Walk the basic block bottom-up. Remember if we saw a store. ++ BasicBlock::iterator I = BB.end(); ++ --I; ++ bool ProcessedBegin = false; ++ SmallPtrSet Stores; ++ do { ++ Instruction *Inst = I; // The instruction to sink. ++ ++ // Predecrement I (if it's not begin) so that it isn't invalidated by ++ // sinking. ++ ProcessedBegin = I == BB.begin(); ++ if (!ProcessedBegin) ++ --I; ++ ++ if (isa(Inst)) ++ continue; ++ ++ if (SinkInstruction(Inst, Stores)) ++ ++NumSunk, MadeChange = true; ++ ++ // If we just processed the first instruction in the block, we're done. ++ } while (!ProcessedBegin); ++ ++ return MadeChange; ++} ++ ++static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, ++ SmallPtrSet &Stores) { ++ if (LoadInst *L = dyn_cast(Inst)) { ++ if (L->isVolatile()) return false; ++ ++ Value *Ptr = L->getPointerOperand(); ++ unsigned Size = AA->getTypeStoreSize(L->getType()); ++ for (SmallPtrSet::iterator I = Stores.begin(), ++ E = Stores.end(); I != E; ++I) ++ if (AA->getModRefInfo(*I, Ptr, Size) & AliasAnalysis::Mod) ++ return false; ++ } ++ ++ if (Inst->mayWriteToMemory()) { ++ Stores.insert(Inst); ++ return false; ++ } ++ ++ return Inst->isSafeToSpeculativelyExecute(); ++} ++ ++/// SinkInstruction - Determine whether it is safe to sink the specified machine ++/// instruction out of its current block into a successor. ++bool Sinking::SinkInstruction(Instruction *Inst, ++ SmallPtrSet &Stores) { ++ // Check if it's safe to move the instruction. ++ if (!isSafeToMove(Inst, AA, Stores)) ++ return false; ++ ++ // FIXME: This should include support for sinking instructions within the ++ // block they are currently in to shorten the live ranges. We often get ++ // instructions sunk into the top of a large block, but it would be better to ++ // also sink them down before their first use in the block. This xform has to ++ // be careful not to *increase* register pressure though, e.g. sinking ++ // "x = y + z" down if it kills y and z would increase the live ranges of y ++ // and z and only shrink the live range of x. ++ ++ // Loop over all the operands of the specified instruction. If there is ++ // anything we can't handle, bail out. ++ BasicBlock *ParentBlock = Inst->getParent(); ++ ++ // SuccToSinkTo - This is the successor to sink this instruction to, once we ++ // decide. ++ BasicBlock *SuccToSinkTo = 0; ++ ++ // FIXME: This picks a successor to sink into based on having one ++ // successor that dominates all the uses. However, there are cases where ++ // sinking can happen but where the sink point isn't a successor. For ++ // example: ++ // x = computation ++ // if () {} else {} ++ // use x ++ // the instruction could be sunk over the whole diamond for the ++ // if/then/else (or loop, etc), allowing it to be sunk into other blocks ++ // after that. ++ ++ // Instructions can only be sunk if all their uses are in blocks ++ // dominated by one of the successors. ++ // Look at all the successors and decide which one ++ // we should sink to. ++ for (succ_iterator SI = succ_begin(ParentBlock), ++ E = succ_end(ParentBlock); SI != E; ++SI) { ++ if (AllUsesDominatedByBlock(Inst, *SI)) { ++ SuccToSinkTo = *SI; ++ break; ++ } ++ } ++ ++ // If we couldn't find a block to sink to, ignore this instruction. ++ if (SuccToSinkTo == 0) ++ return false; ++ ++ // It is not possible to sink an instruction into its own block. This can ++ // happen with loops. ++ if (Inst->getParent() == SuccToSinkTo) ++ return false; ++ ++ DEBUG(dbgs() << "Sink instr " << *Inst); ++ DEBUG(dbgs() << "to block "; ++ WriteAsOperand(dbgs(), SuccToSinkTo, false)); ++ ++ // If the block has multiple predecessors, this would introduce computation on ++ // a path that it doesn't already exist. We could split the critical edge, ++ // but for now we just punt. ++ // FIXME: Split critical edges if not backedges. ++ if (SuccToSinkTo->getUniquePredecessor() != ParentBlock) { ++ // We cannot sink a load across a critical edge - there may be stores in ++ // other code paths. ++ if (!Inst->isSafeToSpeculativelyExecute()) { ++ DEBUG(dbgs() << " *** PUNTING: Wont sink load along critical edge.\n"); ++ return false; ++ } ++ ++ // We don't want to sink across a critical edge if we don't dominate the ++ // successor. We could be introducing calculations to new code paths. ++ if (!DT->dominates(ParentBlock, SuccToSinkTo)) { ++ DEBUG(dbgs() << " *** PUNTING: Critical edge found\n"); ++ return false; ++ } ++ ++ // Don't sink instructions into a loop. ++ if (LI->isLoopHeader(SuccToSinkTo)) { ++ DEBUG(dbgs() << " *** PUNTING: Loop header found\n"); ++ return false; ++ } ++ ++ // Otherwise we are OK with sinking along a critical edge. ++ DEBUG(dbgs() << "Sinking along critical edge.\n"); ++ } ++ ++ // Determine where to insert into. Skip phi nodes. ++ BasicBlock::iterator InsertPos = SuccToSinkTo->begin(); ++ while (InsertPos != SuccToSinkTo->end() && isa(InsertPos)) ++ ++InsertPos; ++ ++ // Move the instruction. ++ Inst->moveBefore(InsertPos); ++ return true; ++} From 5176797a8f2506f878c9fb0a7d0fd0c9f27c6c4a Mon Sep 17 00:00:00 2001 From: John Lu Date: Thu, 17 Apr 2025 14:50:07 -0500 Subject: [PATCH 06/14] Avoid two lookups. Use using instead of typedef. Signed-off-by: John Lu --- llvm/lib/Transforms/Scalar/Sink.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp index 9f0a7fddeb01a..a5404956f1c94 100644 --- a/llvm/lib/Transforms/Scalar/Sink.cpp +++ b/llvm/lib/Transforms/Scalar/Sink.cpp @@ -75,13 +75,12 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis &AA, return true; } -typedef SmallPtrSet BlocksSet; +using BlocksSet = SmallPtrSet; static void findStores(SmallPtrSetImpl &Stores, BasicBlock *LoadBB, BasicBlock *BB, BlocksSet &VisitedBlocksSet) { - if (BB == LoadBB || VisitedBlocksSet.contains(BB)) + if (BB == LoadBB || !VisitedBlocksSet.insert(BB).second) return; - VisitedBlocksSet.insert(BB); for (Instruction &Inst : *BB) if (Inst.mayWriteToMemory()) From 0322b92bdb600d077e548123bb23c489fd1532dd Mon Sep 17 00:00:00 2001 From: John Lu Date: Thu, 17 Apr 2025 14:52:33 -0500 Subject: [PATCH 07/14] Remove file Signed-off-by: John Lu --- llvm/lib/Transforms/Scalar/f | 4043 ---------------------------------- 1 file changed, 4043 deletions(-) delete mode 100644 llvm/lib/Transforms/Scalar/f diff --git a/llvm/lib/Transforms/Scalar/f b/llvm/lib/Transforms/Scalar/f deleted file mode 100644 index 67810a3ca0a45..0000000000000 --- a/llvm/lib/Transforms/Scalar/f +++ /dev/null @@ -1,4043 +0,0 @@ -commit 36eeb25bcd0d8a4b85489413bc1b1757d89e988d -Author: John Lu -Date: Wed Apr 16 06:39:59 2025 -0500 - - Extend Sink pass to allow loads to be sunk to non-immediate successor blocks - - Signed-off-by: John Lu - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 1a48a59c4189..57ce0c8990f4 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -27,43 +27,71 @@ using namespace llvm; - STATISTIC(NumSunk, "Number of instructions sunk"); - STATISTIC(NumSinkIter, "Number of sinking iterations"); - --static bool isSafeToMove(Instruction *Inst, AliasAnalysis &AA, -- SmallPtrSetImpl &Stores) { -- -- if (Inst->mayWriteToMemory()) { -- Stores.insert(Inst); -- return false; -- } -- -+static bool hasStoreConflict(Instruction *Inst, AliasAnalysis &AA, -+ SmallPtrSetImpl &Stores) { - if (LoadInst *L = dyn_cast(Inst)) { - MemoryLocation Loc = MemoryLocation::get(L); - for (Instruction *S : Stores) - if (isModSet(AA.getModRefInfo(S, Loc))) -- return false; -+ return true; -+ } else if (auto *Call = dyn_cast(Inst)) { -+ for (Instruction *S : Stores) -+ if (isModSet(AA.getModRefInfo(S, Call))) -+ return true; - } -+ return false; -+} - -+static bool isSafeToMove(Instruction *Inst, AliasAnalysis &AA, -+ SmallPtrSetImpl &Stores) { -+ if (Inst->mayWriteToMemory()) { -+ Stores.insert(Inst); -+ return false; -+ } - if (Inst->isTerminator() || isa(Inst) || Inst->isEHPad() || - Inst->mayThrow() || !Inst->willReturn()) - return false; -- -- if (auto *Call = dyn_cast(Inst)) { -- // Convergent operations cannot be made control-dependent on additional -- // values. -+ // Convergent operations cannot be made control-dependent on additional -+ // values. -+ if (auto *Call = dyn_cast(Inst)) - if (Call->isConvergent()) - return false; -+ if (hasStoreConflict(Inst, AA, Stores)) -+ return false; -+ return true; -+} - -- for (Instruction *S : Stores) -- if (isModSet(AA.getModRefInfo(S, Call))) -- return false; -- } -+typedef SmallPtrSet BlocksSet; -+static void findStores(SmallPtrSetImpl &Stores, -+ BasicBlock *LoadBB, BasicBlock *BB, -+ BlocksSet &VisitedBlocksSet) { -+ if (BB == LoadBB || VisitedBlocksSet.contains(BB)) -+ return; -+ VisitedBlocksSet.insert(BB); -+ -+ for (Instruction &Inst : *BB) -+ if (Inst.mayWriteToMemory()) -+ Stores.insert(&Inst); -+ for (BasicBlock *Pred : predecessors(BB)) -+ findStores(Stores, LoadBB, Pred, VisitedBlocksSet); -+} - -- return true; -+static bool hasConflictingStoreBeforeSuccToSinkTo(AliasAnalysis &AA, -+ Instruction *ReadMemInst, -+ BasicBlock *SuccToSinkTo) { -+ BlocksSet VisitedBlocksSet; -+ SmallPtrSet Stores; -+ BasicBlock *LoadBB = ReadMemInst->getParent(); -+ for (BasicBlock *Pred : predecessors(SuccToSinkTo)) -+ findStores(Stores, LoadBB, Pred, VisitedBlocksSet); -+ return hasStoreConflict(ReadMemInst, AA, Stores); - } - - /// IsAcceptableTarget - Return true if it is possible to sink the instruction - /// in the specified basic block. --static bool IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo, -- DominatorTree &DT, LoopInfo &LI) { -+static bool IsAcceptableTarget(AliasAnalysis &AA, Instruction *Inst, -+ BasicBlock *SuccToSinkTo, DominatorTree &DT, -+ LoopInfo &LI) { - assert(Inst && "Instruction to be sunk is null"); - assert(SuccToSinkTo && "Candidate sink target is null"); - -@@ -76,10 +104,10 @@ static bool IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo, - // just punt. - // FIXME: Split critical edges if not backedges. - if (SuccToSinkTo->getUniquePredecessor() != Inst->getParent()) { -- // We cannot sink a load across a critical edge - there may be stores in -- // other code paths. -+ // Ensure that there is no conflicting store on any path to SuccToSinkTo. - if (Inst->mayReadFromMemory() && -- !Inst->hasMetadata(LLVMContext::MD_invariant_load)) -+ !Inst->hasMetadata(LLVMContext::MD_invariant_load) && -+ hasConflictingStoreBeforeSuccToSinkTo(AA, Inst, SuccToSinkTo)) - return false; - - // We don't want to sink across a critical edge if we don't dominate the -@@ -153,7 +181,7 @@ static bool SinkInstruction(Instruction *Inst, - // The nearest common dominator may be in a parent loop of BB, which may not - // be beneficial. Find an ancestor. - while (SuccToSinkTo != BB && -- !IsAcceptableTarget(Inst, SuccToSinkTo, DT, LI)) -+ !IsAcceptableTarget(AA, Inst, SuccToSinkTo, DT, LI)) - SuccToSinkTo = DT.getNode(SuccToSinkTo)->getIDom()->getBlock(); - if (SuccToSinkTo == BB) - SuccToSinkTo = nullptr; - -commit 8e702735090388a3231a863e343f880d0f96fecb -Author: Jeremy Morse -Date: Fri Jan 24 10:53:11 2025 +0000 - - [NFC][DebugInfo] Use iterator moveBefore at many call-sites (#123583) - - As part of the "RemoveDIs" project, BasicBlock::iterator now carries a - debug-info bit that's needed when getFirstNonPHI and similar feed into - instruction insertion positions. Call-sites where that's necessary were - updated a year ago; but to ensure some type safety however, we'd like to - have all calls to moveBefore use iterators. - - This patch adds a (guaranteed dereferenceable) iterator-taking - moveBefore, and changes a bunch of call-sites where it's obviously safe - to change to use it by just calling getIterator() on an instruction - pointer. A follow-up patch will contain less-obviously-safe changes. - - We'll eventually deprecate and remove the instruction-pointer - insertBefore, but not before adding concise documentation of what - considerations are needed (very few). - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 46bcfd6b41ce..1a48a59c4189 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -168,7 +168,7 @@ static bool SinkInstruction(Instruction *Inst, - SuccToSinkTo->printAsOperand(dbgs(), false); dbgs() << ")\n"); - - // Move the instruction. -- Inst->moveBefore(&*SuccToSinkTo->getFirstInsertionPt()); -+ Inst->moveBefore(SuccToSinkTo->getFirstInsertionPt()); - return true; - } - - -commit 2a2b426f13dfd33c7495da1c54ab9d1a8e625d87 -Author: XChy -Date: Mon Oct 9 22:34:44 2023 +0800 - - [Sink] Fix bugs of sinking unreachable BB from phi (#68576) - - Resolve #68529. - Sink pass doesn't consider whether Basicblock from phi is unreachable. - This patch moves unreachability check after checking phi. - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index ed768deacd06..46bcfd6b41ce 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -130,15 +130,16 @@ static bool SinkInstruction(Instruction *Inst, - for (Use &U : Inst->uses()) { - Instruction *UseInst = cast(U.getUser()); - BasicBlock *UseBlock = UseInst->getParent(); -- // Don't worry about dead users. -- if (!DT.isReachableFromEntry(UseBlock)) -- continue; - if (PHINode *PN = dyn_cast(UseInst)) { - // PHI nodes use the operand in the predecessor block, not the block with - // the PHI. - unsigned Num = PHINode::getIncomingValueNumForOperand(U.getOperandNo()); - UseBlock = PN->getIncomingBlock(Num); - } -+ // Don't worry about dead users. -+ if (!DT.isReachableFromEntry(UseBlock)) -+ continue; -+ - if (SuccToSinkTo) - SuccToSinkTo = DT.findNearestCommonDominator(SuccToSinkTo, UseBlock); - else - -commit 4eafc9b6ff4ae2bce82e9fdf0123b336825d931c -Author: Nikita Popov -Date: Wed Aug 23 15:04:45 2023 +0200 - - [IR] Treat callbr as special terminator (PR64215) - - isLegalToHoistInto() currently return true for callbr instructions. - That means that a callbr with one successor will be considered a - proper loop preheader, which may result in instructions that use - the callbr return value being hoisted past it. - - Fix this by adding callbr to isExceptionTerminator (with a rename - to isSpecialTerminator), which also fixes similar assumptions in - other places. - - Fixes https://github.com/llvm/llvm-project/issues/64215. - - Differential Revision: https://reviews.llvm.org/D158609 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 8b99f73b850b..ed768deacd06 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -67,9 +67,8 @@ static bool IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo, - assert(Inst && "Instruction to be sunk is null"); - assert(SuccToSinkTo && "Candidate sink target is null"); - -- // It's never legal to sink an instruction into a block which terminates in an -- // EH-pad. -- if (SuccToSinkTo->getTerminator()->isExceptionalTerminator()) -+ // It's never legal to sink an instruction into an EH-pad block. -+ if (SuccToSinkTo->isEHPad()) - return false; - - // If the block has multiple predecessors, this would introduce computation - -commit 6b852ffa9973015fb5deb6d859d980692387dcc7 -Author: Fangrui Song -Date: Fri Nov 18 01:23:12 2022 +0000 - - [Sink] Process basic blocks with a single successor - - This condition seems unnecessary. - - Reviewed By: arsenm - - Differential Revision: https://reviews.llvm.org/D93511 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index dad45c47e0c2..8b99f73b850b 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -174,9 +174,6 @@ static bool SinkInstruction(Instruction *Inst, - - static bool ProcessBlock(BasicBlock &BB, DominatorTree &DT, LoopInfo &LI, - AAResults &AA) { -- // Can't sink anything out of a block that has less than two successors. -- if (BB.getTerminator()->getNumSuccessors() <= 1) return false; -- - // Don't bother sinking code out of unreachable blocks. In addition to being - // unprofitable, it can also lead to infinite looping, because in an - // unreachable loop there may be nowhere to stop. - -commit c316332e1789221ec26875d1dc335382b6e68d83 -Author: Carl Ritson -Date: Thu Oct 6 09:06:32 2022 +0900 - - [Sink] Allow sinking of invariant loads across critical edges - - Invariant loads can always be sunk. - - Reviewed By: foad, arsenm - - Differential Revision: https://reviews.llvm.org/D135133 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index e8fde53005f0..dad45c47e0c2 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -79,7 +79,8 @@ static bool IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo, - if (SuccToSinkTo->getUniquePredecessor() != Inst->getParent()) { - // We cannot sink a load across a critical edge - there may be stores in - // other code paths. -- if (Inst->mayReadFromMemory()) -+ if (Inst->mayReadFromMemory() && -+ !Inst->hasMetadata(LLVMContext::MD_invariant_load)) - return false; - - // We don't want to sink across a critical edge if we don't dominate the - -commit e22af03a794d633915d0b51c15e05bb9cb9b4ec9 -Author: Nikita Popov -Date: Thu Apr 7 16:23:56 2022 +0200 - - [Sink] Don't sink non-willreturn calls (PR51188) - - Fixes https://github.com/llvm/llvm-project/issues/51188. - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index ac6f34aab415..e8fde53005f0 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -43,7 +43,7 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis &AA, - } - - if (Inst->isTerminator() || isa(Inst) || Inst->isEHPad() || -- Inst->mayThrow()) -+ Inst->mayThrow() || !Inst->willReturn()) - return false; - - if (auto *Call = dyn_cast(Inst)) { - -commit 59630917d6cc7c4a273f617f92bf6190ee2992e1 -Author: serge-sans-paille -Date: Wed Mar 2 16:38:19 2022 +0100 - - Cleanup includes: Transform/Scalar - - Estimated impact on preprocessor output line: - before: 1062981579 - after: 1062494547 - - Discourse thread: https://discourse.llvm.org/t/include-what-you-use-include-cleanup - Differential Revision: https://reviews.llvm.org/D120817 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 8600aacdb056..ac6f34aab415 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -15,12 +15,7 @@ - #include "llvm/ADT/Statistic.h" - #include "llvm/Analysis/AliasAnalysis.h" - #include "llvm/Analysis/LoopInfo.h" --#include "llvm/Analysis/ValueTracking.h" --#include "llvm/IR/CFG.h" --#include "llvm/IR/DataLayout.h" - #include "llvm/IR/Dominators.h" --#include "llvm/IR/IntrinsicInst.h" --#include "llvm/IR/Module.h" - #include "llvm/InitializePasses.h" - #include "llvm/Support/Debug.h" - #include "llvm/Support/raw_ostream.h" - -commit 30bb5be38908b0006ed94124515e43774ee37915 -Author: Hongtao Yu -Date: Mon Apr 26 09:12:29 2021 -0700 - - [CSSPGO] Unblock optimizations with pseudo probe instrumentation part 2. - - As a follow-up to D95982, this patch continues unblocking optimizations that are blocked by pseudu probe instrumention. - - The optimizations unblocked are: - - In-block load propagation. - - In-block dead store elimination - - Memory copy optimization that turns stores to consecutive memories into a memset. - - These optimizations are local to a block, so they shouldn't affect the profile quality. - - Reviewed By: wmi - - Differential Revision: https://reviews.llvm.org/D100075 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 89cfbe384be4..8600aacdb056 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -202,7 +202,7 @@ static bool ProcessBlock(BasicBlock &BB, DominatorTree &DT, LoopInfo &LI, - if (!ProcessedBegin) - --I; - -- if (isa(Inst)) -+ if (Inst->isDebugOrPseudoInst()) - continue; - - if (SinkInstruction(Inst, Stores, DT, LI, AA)) { - -commit f192a27ed3bacdf727f27857adeb6d3762383295 -Author: Changpeng Fang -Date: Fri Oct 9 16:20:26 2020 -0700 - - Sink: Handle instruction sink when a user is dead - - Summary: - The current instruction sink pass uses findNearestCommonDominator of all users to find block to sink the instruction to. - However, a user may be in a dead block, which will result in unexpected behavior. - - This patch handles such cases by skipping dead blocks. This patch fixes: - https://bugs.llvm.org/show_bug.cgi?id=47415 - - Reviewers: - MaskRay, arsenm - - Differential Revision: - https://reviews.llvm.org/D89166 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index c430724ab1ac..89cfbe384be4 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -135,6 +135,9 @@ static bool SinkInstruction(Instruction *Inst, - for (Use &U : Inst->uses()) { - Instruction *UseInst = cast(U.getUser()); - BasicBlock *UseBlock = UseInst->getParent(); -+ // Don't worry about dead users. -+ if (!DT.isReachableFromEntry(UseBlock)) -+ continue; - if (PHINode *PN = dyn_cast(UseInst)) { - // PHI nodes use the operand in the predecessor block, not the block with - // the PHI. - -commit f2284e3405d87143b2478f28b8045bef84953c91 -Author: Fangrui Song -Date: Sun Aug 30 22:51:00 2020 -0700 - - [Sink] Optimize/simplify sink candidate finding with nearest common dominator - - For an instruction in the basic block BB, SinkingPass enumerates basic blocks - dominated by BB and BB's successors. For each enumerated basic block, - SinkingPass uses `AllUsesDominatedByBlock` to check whether the basic - block dominates all of the instruction's users. This is inefficient. - - Use the nearest common dominator of all users to avoid enumerating the - candidate. The nearest common dominator may be in a parent loop which is - not beneficial. In that case, find the ancestors in the dominator tree. - - In the case that the instruction has no user, with this change we will - not perform unnecessary move. This causes some amdgpu test changes. - - A stage-2 x86-64 clang is a byte identical with this change. - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 48f289c8f17d..c430724ab1ac 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -32,31 +32,6 @@ using namespace llvm; - STATISTIC(NumSunk, "Number of instructions sunk"); - STATISTIC(NumSinkIter, "Number of sinking iterations"); - --/// AllUsesDominatedByBlock - Return true if all uses of the specified value --/// occur in blocks dominated by the specified block. --static bool AllUsesDominatedByBlock(Instruction *Inst, BasicBlock *BB, -- DominatorTree &DT) { -- // Ignoring debug uses is necessary so debug info doesn't affect the code. -- // This may leave a referencing dbg_value in the original block, before -- // the definition of the vreg. Dwarf generator handles this although the -- // user might not get the right info at runtime. -- for (Use &U : Inst->uses()) { -- // Determine the block of the use. -- Instruction *UseInst = cast(U.getUser()); -- BasicBlock *UseBlock = UseInst->getParent(); -- if (PHINode *PN = dyn_cast(UseInst)) { -- // PHI nodes use the operand in the predecessor block, not the block with -- // the PHI. -- unsigned Num = PHINode::getIncomingValueNumForOperand(U.getOperandNo()); -- UseBlock = PN->getIncomingBlock(Num); -- } -- // Check that it dominates. -- if (!DT.dominates(BB, UseBlock)) -- return false; -- } -- return true; --} -- - static bool isSafeToMove(Instruction *Inst, AliasAnalysis &AA, - SmallPtrSetImpl &Stores) { - -@@ -97,11 +72,6 @@ static bool IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo, - assert(Inst && "Instruction to be sunk is null"); - assert(SuccToSinkTo && "Candidate sink target is null"); - -- // It is not possible to sink an instruction into its own block. This can -- // happen with loops. -- if (Inst->getParent() == SuccToSinkTo) -- return false; -- - // It's never legal to sink an instruction into a block which terminates in an - // EH-pad. - if (SuccToSinkTo->getTerminator()->isExceptionalTerminator()) -@@ -129,9 +99,7 @@ static bool IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo, - return false; - } - -- // Finally, check that all the uses of the instruction are actually -- // dominated by the candidate -- return AllUsesDominatedByBlock(Inst, SuccToSinkTo, DT); -+ return true; - } - - /// SinkInstruction - Determine whether it is safe to sink the specified machine -@@ -162,25 +130,34 @@ static bool SinkInstruction(Instruction *Inst, - // decide. - BasicBlock *SuccToSinkTo = nullptr; - -- // Instructions can only be sunk if all their uses are in blocks -- // dominated by one of the successors. -- // Look at all the dominated blocks and see if we can sink it in one. -- DomTreeNode *DTN = DT.getNode(Inst->getParent()); -- for (auto I = DTN->begin(), E = DTN->end(); I != E && SuccToSinkTo == nullptr; -- ++I) { -- BasicBlock *Candidate = (*I)->getBlock(); -- // A node always immediate-dominates its children on the dominator -- // tree. -- if (IsAcceptableTarget(Inst, Candidate, DT, LI)) -- SuccToSinkTo = Candidate; -+ // Find the nearest common dominator of all users as the candidate. -+ BasicBlock *BB = Inst->getParent(); -+ for (Use &U : Inst->uses()) { -+ Instruction *UseInst = cast(U.getUser()); -+ BasicBlock *UseBlock = UseInst->getParent(); -+ if (PHINode *PN = dyn_cast(UseInst)) { -+ // PHI nodes use the operand in the predecessor block, not the block with -+ // the PHI. -+ unsigned Num = PHINode::getIncomingValueNumForOperand(U.getOperandNo()); -+ UseBlock = PN->getIncomingBlock(Num); -+ } -+ if (SuccToSinkTo) -+ SuccToSinkTo = DT.findNearestCommonDominator(SuccToSinkTo, UseBlock); -+ else -+ SuccToSinkTo = UseBlock; -+ // The current basic block needs to dominate the candidate. -+ if (!DT.dominates(BB, SuccToSinkTo)) -+ return false; - } - -- // If no suitable postdominator was found, look at all the successors and -- // decide which one we should sink to, if any. -- for (succ_iterator I = succ_begin(Inst->getParent()), -- E = succ_end(Inst->getParent()); I != E && !SuccToSinkTo; ++I) { -- if (IsAcceptableTarget(Inst, *I, DT, LI)) -- SuccToSinkTo = *I; -+ if (SuccToSinkTo) { -+ // The nearest common dominator may be in a parent loop of BB, which may not -+ // be beneficial. Find an ancestor. -+ while (SuccToSinkTo != BB && -+ !IsAcceptableTarget(Inst, SuccToSinkTo, DT, LI)) -+ SuccToSinkTo = DT.getNode(SuccToSinkTo)->getIDom()->getBlock(); -+ if (SuccToSinkTo == BB) -+ SuccToSinkTo = nullptr; - } - - // If we couldn't find a block to sink to, ignore this instruction. - -commit 3fa989d4fd6b854209ba4e950d96b91d6d5797b4 -Author: Nicolai Hähnle -Date: Thu Jul 2 20:36:30 2020 +0200 - - DomTree: remove explicit use of DomTreeNodeBase::iterator - - Summary: - Almost all uses of these iterators, including implicit ones, really - only need the const variant (as it should be). The only exception is - in NewGVN, which changes the order of dominator tree child nodes. - - Change-Id: I4b5bd71e32d71b0c67b03d4927d93fe9413726d4 - - Reviewers: arsenm, RKSimon, mehdi_amini, courbet, rriddle, aartbik - - Subscribers: wdng, Prazek, hiraditya, kuhar, rogfer01, rriddle, jpienaar, shauheen, antiagainst, nicolasvasilache, arpith-jacob, mgester, lucyrfox, aartbik, liufengdb, stephenneuendorffer, Joonsoo, grosul1, vkmr, Kayjukh, jurahul, msifontes, cfe-commits, llvm-commits - - Tags: #clang, #mlir, #llvm - - Differential Revision: https://reviews.llvm.org/D83087 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 677d86f8c7b4..48f289c8f17d 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -166,8 +166,8 @@ static bool SinkInstruction(Instruction *Inst, - // dominated by one of the successors. - // Look at all the dominated blocks and see if we can sink it in one. - DomTreeNode *DTN = DT.getNode(Inst->getParent()); -- for (DomTreeNode::iterator I = DTN->begin(), E = DTN->end(); -- I != E && SuccToSinkTo == nullptr; ++I) { -+ for (auto I = DTN->begin(), E = DTN->end(); I != E && SuccToSinkTo == nullptr; -+ ++I) { - BasicBlock *Candidate = (*I)->getBlock(); - // A node always immediate-dominates its children on the dominator - // tree. - -commit 05da2fe52162c80dfa18aedf70cf73cb11201811 -Author: Reid Kleckner -Date: Wed Nov 13 13:15:01 2019 -0800 - - Sink all InitializePasses.h includes - - This file lists every pass in LLVM, and is included by Pass.h, which is - very popular. Every time we add, remove, or rename a pass in LLVM, it - caused lots of recompilation. - - I found this fact by looking at this table, which is sorted by the - number of times a file was changed over the last 100,000 git commits - multiplied by the number of object files that depend on it in the - current checkout: - recompiles touches affected_files header - 342380 95 3604 llvm/include/llvm/ADT/STLExtras.h - 314730 234 1345 llvm/include/llvm/InitializePasses.h - 307036 118 2602 llvm/include/llvm/ADT/APInt.h - 213049 59 3611 llvm/include/llvm/Support/MathExtras.h - 170422 47 3626 llvm/include/llvm/Support/Compiler.h - 162225 45 3605 llvm/include/llvm/ADT/Optional.h - 158319 63 2513 llvm/include/llvm/ADT/Triple.h - 140322 39 3598 llvm/include/llvm/ADT/StringRef.h - 137647 59 2333 llvm/include/llvm/Support/Error.h - 131619 73 1803 llvm/include/llvm/Support/FileSystem.h - - Before this change, touching InitializePasses.h would cause 1345 files - to recompile. After this change, touching it only causes 550 compiles in - an incremental rebuild. - - Reviewers: bkramer, asbirlea, bollu, jdoerfert - - Differential Revision: https://reviews.llvm.org/D70211 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 72b586c85fe1..677d86f8c7b4 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -21,6 +21,7 @@ - #include "llvm/IR/Dominators.h" - #include "llvm/IR/IntrinsicInst.h" - #include "llvm/IR/Module.h" -+#include "llvm/InitializePasses.h" - #include "llvm/Support/Debug.h" - #include "llvm/Support/raw_ostream.h" - #include "llvm/Transforms/Scalar.h" - -commit 9b0b626d2c19802bf3d56272cbc3a13d3c9ee5dd -Author: Matt Arsenault -Date: Sun Oct 27 19:37:45 2019 -0700 - - Use isConvergent helper instead of directly checking attribute - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 90f3a2aa46e1..72b586c85fe1 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -78,7 +78,7 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis &AA, - if (auto *Call = dyn_cast(Inst)) { - // Convergent operations cannot be made control-dependent on additional - // values. -- if (Call->hasFnAttr(Attribute::Convergent)) -+ if (Call->isConvergent()) - return false; - - for (Instruction *S : Stores) - -commit 2946cd701067404b99c39fb29dc9c74bd7193eb3 -Author: Chandler Carruth -Date: Sat Jan 19 08:50:56 2019 +0000 - - Update the file headers across all of the LLVM projects in the monorepo - to reflect the new license. - - We understand that people may be surprised that we're moving the header - entirely to discuss the new license. We checked this carefully with the - Foundation's lawyer and we believe this is the correct approach. - - Essentially, all code in the project is now made available by the LLVM - project under our new license, so you will see that the license headers - include that license only. Some of our contributors have contributed - code under our old license, and accordingly, we have retained a copy of - our old license notice in the top-level files in each project and - repository. - - llvm-svn: 351636 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index c99da8f0737a..90f3a2aa46e1 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -1,9 +1,8 @@ - //===-- Sink.cpp - Code Sinking -------------------------------------------===// - // --// The LLVM Compiler Infrastructure --// --// This file is distributed under the University of Illinois Open Source --// License. See LICENSE.TXT for details. -+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -+// See https://llvm.org/LICENSE.txt for license information. -+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - // - //===----------------------------------------------------------------------===// - // - -commit 363ac6837427ffc6adcc68c44788bb4d92d52873 -Author: Chandler Carruth -Date: Mon Jan 7 05:42:51 2019 +0000 - - [CallSite removal] Migrate all Alias Analysis APIs to use the newly - minted `CallBase` class instead of the `CallSite` wrapper. - - This moves the largest interwoven collection of APIs that traffic in - `CallSite`s. While a handful of these could have been migrated with - a minorly more shallow migration by converting from a `CallSite` to - a `CallBase`, it hardly seemed worth it. Most of the APIs needed to - migrate together because of the complex interplay of AA APIs and the - fact that converting from a `CallBase` to a `CallSite` isn't free in its - current implementation. - - Out of tree users of these APIs can fairly reliably migrate with some - combination of `.getInstruction()` on the `CallSite` instance and - casting the resulting pointer. The most generic form will look like `CS` - -> `cast_or_null(CS.getInstruction())` but in most cases there - is a more elegant migration. Hopefully, this migrates enough APIs for - users to fully move from `CallSite` to the base class. All of the - in-tree users were easily migrated in that fashion. - - Thanks for the review from Saleem! - - Differential Revision: https://reviews.llvm.org/D55641 - - llvm-svn: 350503 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index d1cdfabb0cc4..c99da8f0737a 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -76,14 +76,14 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis &AA, - Inst->mayThrow()) - return false; - -- if (auto CS = CallSite(Inst)) { -+ if (auto *Call = dyn_cast(Inst)) { - // Convergent operations cannot be made control-dependent on additional - // values. -- if (CS.hasFnAttr(Attribute::Convergent)) -+ if (Call->hasFnAttr(Attribute::Convergent)) - return false; - - for (Instruction *S : Stores) -- if (isModSet(AA.getModRefInfo(S, CS))) -+ if (isModSet(AA.getModRefInfo(S, Call))) - return false; - } - - -commit 9ae926b973e42633f7bc7db39b33241dbb9f2158 -Author: Chandler Carruth -Date: Sun Aug 26 09:51:22 2018 +0000 - - [IR] Replace `isa` with `isTerminator()`. - - This is a bit awkward in a handful of places where we didn't even have - an instruction and now we have to see if we can build one. But on the - whole, this seems like a win and at worst a reasonable cost for removing - `TerminatorInst`. - - All of this is part of the removal of `TerminatorInst` from the - `Instruction` type hierarchy. - - llvm-svn: 340701 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index b59d52f2ecff..d1cdfabb0cc4 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -72,7 +72,7 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis &AA, - return false; - } - -- if (isa(Inst) || isa(Inst) || Inst->isEHPad() || -+ if (Inst->isTerminator() || isa(Inst) || Inst->isEHPad() || - Inst->mayThrow()) - return false; - - -commit 698fbe7b59a77888f108fbfe37e17a1db0cace8c -Author: Chandler Carruth -Date: Sun Aug 26 08:56:42 2018 +0000 - - [IR] Sink `isExceptional` predicate to `Instruction`, rename it to - `isExceptionalTermiantor` and implement it for opcodes as well following - the common pattern in `Instruction`. - - Part of removing `TerminatorInst` from the `Instruction` type hierarchy - to make it easier to share logic and interfaces between instructions - that are both terminators and not terminators. - - llvm-svn: 340699 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index ca6b93e0b4a9..b59d52f2ecff 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -104,7 +104,7 @@ static bool IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo, - - // It's never legal to sink an instruction into a block which terminates in an - // EH-pad. -- if (SuccToSinkTo->getTerminator()->isExceptional()) -+ if (SuccToSinkTo->getTerminator()->isExceptionalTerminator()) - return false; - - // If the block has multiple predecessors, this would introduce computation - -commit d34e60ca8532511acb8c93ef26297e349fbec86a -Author: Nicola Zaghen -Date: Mon May 14 12:53:11 2018 +0000 - - Rename DEBUG macro to LLVM_DEBUG. - - The DEBUG() macro is very generic so it might clash with other projects. - The renaming was done as follows: - - git grep -l 'DEBUG' | xargs sed -i 's/\bDEBUG\s\?(/LLVM_DEBUG(/g' - - git diff -U0 master | ../clang/tools/clang-format/clang-format-diff.py -i -p1 -style LLVM - - Manual change to APInt - - Manually chage DOCS as regex doesn't match it. - - In the transition period the DEBUG() macro is still present and aliased - to the LLVM_DEBUG() one. - - Differential Revision: https://reviews.llvm.org/D43624 - - llvm-svn: 332240 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 811762880493..ca6b93e0b4a9 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -187,11 +187,9 @@ static bool SinkInstruction(Instruction *Inst, - if (!SuccToSinkTo) - return false; - -- DEBUG(dbgs() << "Sink" << *Inst << " ("; -- Inst->getParent()->printAsOperand(dbgs(), false); -- dbgs() << " -> "; -- SuccToSinkTo->printAsOperand(dbgs(), false); -- dbgs() << ")\n"); -+ LLVM_DEBUG(dbgs() << "Sink" << *Inst << " ("; -+ Inst->getParent()->printAsOperand(dbgs(), false); dbgs() << " -> "; -+ SuccToSinkTo->printAsOperand(dbgs(), false); dbgs() << ")\n"); - - // Move the instruction. - Inst->moveBefore(&*SuccToSinkTo->getFirstInsertionPt()); -@@ -244,7 +242,7 @@ static bool iterativelySinkInstructions(Function &F, DominatorTree &DT, - - do { - MadeChange = false; -- DEBUG(dbgs() << "Sinking iteration " << NumSinkIter << "\n"); -+ LLVM_DEBUG(dbgs() << "Sinking iteration " << NumSinkIter << "\n"); - // Process all basic blocks. - for (BasicBlock &I : F) - MadeChange |= ProcessBlock(I, DT, LI, AA); - -commit efe6a84e5b5015326ee0825e275bc929f8afee5f -Author: Fiona Glaser -Date: Thu Jan 11 21:28:57 2018 +0000 - - [Sink] Really really fix predicate in legality check - - LoadInst isn't enough; we need to include intrinsics that perform loads too. - - All side-effecting intrinsics and such are already covered by the isSafe - check, so we just need to care about things that read from memory. - - D41960, originally from D33179. - - llvm-svn: 322311 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index cfb8a062299f..811762880493 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -114,7 +114,7 @@ static bool IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo, - if (SuccToSinkTo->getUniquePredecessor() != Inst->getParent()) { - // We cannot sink a load across a critical edge - there may be stores in - // other code paths. -- if (isa(Inst)) -+ if (Inst->mayReadFromMemory()) - return false; - - // We don't want to sink across a critical edge if we don't dominate the - -commit 63d2250a42b7b1e35e747ab07e181d2d8ec86dbc -Author: Alina Sbirlea -Date: Tue Dec 5 20:12:23 2017 +0000 - - Modify ModRefInfo values using static inline method abstractions [NFC]. - - Summary: - The aim is to make ModRefInfo checks and changes more intuitive - and less error prone using inline methods that abstract the bit operations. - - Ideally ModRefInfo would become an enum class, but that change will require - a wider set of changes into FunctionModRefBehavior. - - Reviewers: sanjoy, george.burgess.iv, dberlin, hfinkel - - Subscribers: nlopes, llvm-commits - - Differential Revision: https://reviews.llvm.org/D40749 - - llvm-svn: 319821 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 5210f165b874..cfb8a062299f 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -68,7 +68,7 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis &AA, - if (LoadInst *L = dyn_cast(Inst)) { - MemoryLocation Loc = MemoryLocation::get(L); - for (Instruction *S : Stores) -- if (AA.getModRefInfo(S, Loc) & MRI_Mod) -+ if (isModSet(AA.getModRefInfo(S, Loc))) - return false; - } - -@@ -83,7 +83,7 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis &AA, - return false; - - for (Instruction *S : Stores) -- if (AA.getModRefInfo(S, CS) & MRI_Mod) -+ if (isModSet(AA.getModRefInfo(S, CS))) - return false; - } - - -commit 5329174cb1b32bb34b90f1fdd5525ed84716ecec -Author: Keno Fischer -Date: Fri Jun 9 19:31:10 2017 +0000 - - [Sink] Fix predicate in legality check - - Summary: - isSafeToSpeculativelyExecute is the wrong predicate to use here. - All that checks for is whether it is safe to hoist a value due to - unaligned/un-dereferencable accesses. However, not only are we doing - sinking rather than hoisting, our concern is that the location - we're loading from may have been modified. Instead forbid sinking - any load across a critical edge. - - Reviewers: majnemer - - Subscribers: davide, llvm-commits - - Differential Revision: https://reviews.llvm.org/D33179 - - llvm-svn: 305102 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 102e9eaeab77..5210f165b874 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -114,7 +114,7 @@ static bool IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo, - if (SuccToSinkTo->getUniquePredecessor() != Inst->getParent()) { - // We cannot sink a load across a critical edge - there may be stores in - // other code paths. -- if (!isSafeToSpeculativelyExecute(Inst)) -+ if (isa(Inst)) - return false; - - // We don't want to sink across a critical edge if we don't dominate the - -commit cbf04d95e6295cc35d85490fb03f7c83e9180dc5 -Author: Xin Tong -Date: Mon Mar 20 00:30:19 2017 +0000 - - Remove unnecessary IDom check - - Summary: This Idom check seems unnecessary. The immediate children of a node on the Dominator Tree should always be the IDom of its immediate children in this case. - - Reviewers: hfinkel, majnemer, dberlin - - Reviewed By: dberlin - - Subscribers: dberlin, davide, llvm-commits - - Differential Revision: https://reviews.llvm.org/D26954 - - llvm-svn: 298232 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 504a22a229c8..102e9eaeab77 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -164,13 +164,14 @@ static bool SinkInstruction(Instruction *Inst, - - // Instructions can only be sunk if all their uses are in blocks - // dominated by one of the successors. -- // Look at all the postdominators and see if we can sink it in one. -+ // Look at all the dominated blocks and see if we can sink it in one. - DomTreeNode *DTN = DT.getNode(Inst->getParent()); - for (DomTreeNode::iterator I = DTN->begin(), E = DTN->end(); - I != E && SuccToSinkTo == nullptr; ++I) { - BasicBlock *Candidate = (*I)->getBlock(); -- if ((*I)->getIDom()->getBlock() == Inst->getParent() && -- IsAcceptableTarget(Inst, Candidate, DT, LI)) -+ // A node always immediate-dominates its children on the dominator -+ // tree. -+ if (IsAcceptableTarget(Inst, Candidate, DT, LI)) - SuccToSinkTo = Candidate; - } - - -commit ca68a3ec47416185252b84d2bf60710c88be155f -Author: Chandler Carruth -Date: Sun Jan 15 06:32:49 2017 +0000 - - [PM] Introduce an analysis set used to preserve all analyses over - a function's CFG when that CFG is unchanged. - - This allows transformation passes to simply claim they preserve the CFG - and analysis passes to check for the CFG being preserved to remove the - fanout of all analyses being listed in all passes. - - I've gone through and removed or cleaned up as many of the comments - reminding us to do this as I could. - - Differential Revision: https://reviews.llvm.org/D28627 - - llvm-svn: 292054 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index c3f14a0f4b1e..504a22a229c8 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -262,9 +262,8 @@ PreservedAnalyses SinkingPass::run(Function &F, FunctionAnalysisManager &AM) { - if (!iterativelySinkInstructions(F, DT, LI, AA)) - return PreservedAnalyses::all(); - -- auto PA = PreservedAnalyses(); -- PA.preserve(); -- PA.preserve(); -+ PreservedAnalyses PA; -+ PA.preserveSet(); - return PA; - } - - -commit 36e0d01e13b32bf318139fd8c43849af7a0e13cc -Author: Sean Silva -Date: Tue Aug 9 00:28:15 2016 +0000 - - Consistently use FunctionAnalysisManager - - Besides a general consistently benefit, the extra layer of indirection - allows the mechanical part of https://reviews.llvm.org/D23256 that - requires touching every transformation and analysis to be factored out - cleanly. - - Thanks to David for the suggestion. - - llvm-svn: 278077 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index d9a296c63122..c3f14a0f4b1e 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -254,7 +254,7 @@ static bool iterativelySinkInstructions(Function &F, DominatorTree &DT, - return EverMadeChange; - } - --PreservedAnalyses SinkingPass::run(Function &F, AnalysisManager &AM) { -+PreservedAnalyses SinkingPass::run(Function &F, FunctionAnalysisManager &AM) { - auto &DT = AM.getResult(F); - auto &LI = AM.getResult(F); - auto &AA = AM.getResult(F); - -commit 889a20cf40c8e61a62e32bef38a0abea6194d6f1 -Author: Nicolai Haehnle -Date: Mon Jul 11 14:11:51 2016 +0000 - - [Sink] Don't move calls to readonly functions across stores - - Summary: - - Reviewers: hfinkel, majnemer, tstellarAMD, sunfish - - Subscribers: llvm-commits - - Differential Revision: http://reviews.llvm.org/D17279 - - llvm-svn: 275066 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 5fa43bda9d09..d9a296c63122 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -76,11 +76,15 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis &AA, - Inst->mayThrow()) - return false; - -- // Convergent operations cannot be made control-dependent on additional -- // values. - if (auto CS = CallSite(Inst)) { -+ // Convergent operations cannot be made control-dependent on additional -+ // values. - if (CS.hasFnAttr(Attribute::Convergent)) - return false; -+ -+ for (Instruction *S : Stores) -+ if (AA.getModRefInfo(S, CS) & MRI_Mod) -+ return false; - } - - return true; - -commit 135f735af149e305635ba3886065b493d5c2bf8c -Author: Benjamin Kramer -Date: Sun Jun 26 12:28:59 2016 +0000 - - Apply clang-tidy's modernize-loop-convert to most of lib/Transforms. - - Only minor manual fixes. No functionality change intended. - - llvm-svn: 273808 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index c5f29fa99dc8..5fa43bda9d09 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -241,9 +241,8 @@ static bool iterativelySinkInstructions(Function &F, DominatorTree &DT, - MadeChange = false; - DEBUG(dbgs() << "Sinking iteration " << NumSinkIter << "\n"); - // Process all basic blocks. -- for (Function::iterator I = F.begin(), E = F.end(); -- I != E; ++I) -- MadeChange |= ProcessBlock(*I, DT, LI, AA); -+ for (BasicBlock &I : F) -+ MadeChange |= ProcessBlock(I, DT, LI, AA); - EverMadeChange |= MadeChange; - NumSinkIter++; - } while (MadeChange); - -commit b93949089e8cd8e192c0293811f9cbd801af27b6 -Author: Justin Bogner -Date: Fri Apr 22 19:54:10 2016 +0000 - - PM: Port SinkingPass to the new pass manager - - llvm-svn: 267199 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index e5860328d04f..c5f29fa99dc8 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -12,7 +12,7 @@ - // - //===----------------------------------------------------------------------===// - --#include "llvm/Transforms/Scalar.h" -+#include "llvm/Transforms/Scalar/Sink.h" - #include "llvm/ADT/Statistic.h" - #include "llvm/Analysis/AliasAnalysis.h" - #include "llvm/Analysis/LoopInfo.h" -@@ -24,6 +24,7 @@ - #include "llvm/IR/Module.h" - #include "llvm/Support/Debug.h" - #include "llvm/Support/raw_ostream.h" -+#include "llvm/Transforms/Scalar.h" - using namespace llvm; - - #define DEBUG_TYPE "sink" -@@ -31,50 +32,10 @@ using namespace llvm; - STATISTIC(NumSunk, "Number of instructions sunk"); - STATISTIC(NumSinkIter, "Number of sinking iterations"); - --namespace { -- class Sinking : public FunctionPass { -- DominatorTree *DT; -- LoopInfo *LI; -- AliasAnalysis *AA; -- -- public: -- static char ID; // Pass identification -- Sinking() : FunctionPass(ID) { -- initializeSinkingPass(*PassRegistry::getPassRegistry()); -- } -- -- bool runOnFunction(Function &F) override; -- -- void getAnalysisUsage(AnalysisUsage &AU) const override { -- AU.setPreservesCFG(); -- FunctionPass::getAnalysisUsage(AU); -- AU.addRequired(); -- AU.addRequired(); -- AU.addRequired(); -- AU.addPreserved(); -- AU.addPreserved(); -- } -- private: -- bool ProcessBlock(BasicBlock &BB); -- bool SinkInstruction(Instruction *I, SmallPtrSetImpl &Stores); -- bool AllUsesDominatedByBlock(Instruction *Inst, BasicBlock *BB) const; -- bool IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo) const; -- }; --} // end anonymous namespace -- --char Sinking::ID = 0; --INITIALIZE_PASS_BEGIN(Sinking, "sink", "Code sinking", false, false) --INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) --INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) --INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass) --INITIALIZE_PASS_END(Sinking, "sink", "Code sinking", false, false) -- --FunctionPass *llvm::createSinkingPass() { return new Sinking(); } -- - /// AllUsesDominatedByBlock - Return true if all uses of the specified value - /// occur in blocks dominated by the specified block. --bool Sinking::AllUsesDominatedByBlock(Instruction *Inst, -- BasicBlock *BB) const { -+static bool AllUsesDominatedByBlock(Instruction *Inst, BasicBlock *BB, -+ DominatorTree &DT) { - // Ignoring debug uses is necessary so debug info doesn't affect the code. - // This may leave a referencing dbg_value in the original block, before - // the definition of the vreg. Dwarf generator handles this although the -@@ -90,13 +51,13 @@ bool Sinking::AllUsesDominatedByBlock(Instruction *Inst, - UseBlock = PN->getIncomingBlock(Num); - } - // Check that it dominates. -- if (!DT->dominates(BB, UseBlock)) -+ if (!DT.dominates(BB, UseBlock)) - return false; - } - return true; - } - --static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, -+static bool isSafeToMove(Instruction *Inst, AliasAnalysis &AA, - SmallPtrSetImpl &Stores) { - - if (Inst->mayWriteToMemory()) { -@@ -107,7 +68,7 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, - if (LoadInst *L = dyn_cast(Inst)) { - MemoryLocation Loc = MemoryLocation::get(L); - for (Instruction *S : Stores) -- if (AA->getModRefInfo(S, Loc) & MRI_Mod) -+ if (AA.getModRefInfo(S, Loc) & MRI_Mod) - return false; - } - -@@ -127,8 +88,8 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, - - /// IsAcceptableTarget - Return true if it is possible to sink the instruction - /// in the specified basic block. --bool Sinking::IsAcceptableTarget(Instruction *Inst, -- BasicBlock *SuccToSinkTo) const { -+static bool IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo, -+ DominatorTree &DT, LoopInfo &LI) { - assert(Inst && "Instruction to be sunk is null"); - assert(SuccToSinkTo && "Candidate sink target is null"); - -@@ -154,25 +115,26 @@ bool Sinking::IsAcceptableTarget(Instruction *Inst, - - // We don't want to sink across a critical edge if we don't dominate the - // successor. We could be introducing calculations to new code paths. -- if (!DT->dominates(Inst->getParent(), SuccToSinkTo)) -+ if (!DT.dominates(Inst->getParent(), SuccToSinkTo)) - return false; - - // Don't sink instructions into a loop. -- Loop *succ = LI->getLoopFor(SuccToSinkTo); -- Loop *cur = LI->getLoopFor(Inst->getParent()); -+ Loop *succ = LI.getLoopFor(SuccToSinkTo); -+ Loop *cur = LI.getLoopFor(Inst->getParent()); - if (succ != nullptr && succ != cur) - return false; - } - - // Finally, check that all the uses of the instruction are actually - // dominated by the candidate -- return AllUsesDominatedByBlock(Inst, SuccToSinkTo); -+ return AllUsesDominatedByBlock(Inst, SuccToSinkTo, DT); - } - - /// SinkInstruction - Determine whether it is safe to sink the specified machine - /// instruction out of its current block into a successor. --bool Sinking::SinkInstruction(Instruction *Inst, -- SmallPtrSetImpl &Stores) { -+static bool SinkInstruction(Instruction *Inst, -+ SmallPtrSetImpl &Stores, -+ DominatorTree &DT, LoopInfo &LI, AAResults &AA) { - - // Don't sink static alloca instructions. CodeGen assumes allocas outside the - // entry block are dynamically sized stack objects. -@@ -199,12 +161,12 @@ bool Sinking::SinkInstruction(Instruction *Inst, - // Instructions can only be sunk if all their uses are in blocks - // dominated by one of the successors. - // Look at all the postdominators and see if we can sink it in one. -- DomTreeNode *DTN = DT->getNode(Inst->getParent()); -+ DomTreeNode *DTN = DT.getNode(Inst->getParent()); - for (DomTreeNode::iterator I = DTN->begin(), E = DTN->end(); - I != E && SuccToSinkTo == nullptr; ++I) { - BasicBlock *Candidate = (*I)->getBlock(); - if ((*I)->getIDom()->getBlock() == Inst->getParent() && -- IsAcceptableTarget(Inst, Candidate)) -+ IsAcceptableTarget(Inst, Candidate, DT, LI)) - SuccToSinkTo = Candidate; - } - -@@ -212,7 +174,7 @@ bool Sinking::SinkInstruction(Instruction *Inst, - // decide which one we should sink to, if any. - for (succ_iterator I = succ_begin(Inst->getParent()), - E = succ_end(Inst->getParent()); I != E && !SuccToSinkTo; ++I) { -- if (IsAcceptableTarget(Inst, *I)) -+ if (IsAcceptableTarget(Inst, *I, DT, LI)) - SuccToSinkTo = *I; - } - -@@ -231,14 +193,15 @@ bool Sinking::SinkInstruction(Instruction *Inst, - return true; - } - --bool Sinking::ProcessBlock(BasicBlock &BB) { -+static bool ProcessBlock(BasicBlock &BB, DominatorTree &DT, LoopInfo &LI, -+ AAResults &AA) { - // Can't sink anything out of a block that has less than two successors. - if (BB.getTerminator()->getNumSuccessors() <= 1) return false; - - // Don't bother sinking code out of unreachable blocks. In addition to being - // unprofitable, it can also lead to infinite looping, because in an - // unreachable loop there may be nowhere to stop. -- if (!DT->isReachableFromEntry(&BB)) return false; -+ if (!DT.isReachableFromEntry(&BB)) return false; - - bool MadeChange = false; - -@@ -259,7 +222,7 @@ bool Sinking::ProcessBlock(BasicBlock &BB) { - if (isa(Inst)) - continue; - -- if (SinkInstruction(Inst, Stores)) { -+ if (SinkInstruction(Inst, Stores, DT, LI, AA)) { - ++NumSunk; - MadeChange = true; - } -@@ -270,11 +233,8 @@ bool Sinking::ProcessBlock(BasicBlock &BB) { - return MadeChange; - } - --bool Sinking::runOnFunction(Function &F) { -- DT = &getAnalysis().getDomTree(); -- LI = &getAnalysis().getLoopInfo(); -- AA = &getAnalysis().getAAResults(); -- -+static bool iterativelySinkInstructions(Function &F, DominatorTree &DT, -+ LoopInfo &LI, AAResults &AA) { - bool MadeChange, EverMadeChange = false; - - do { -@@ -283,10 +243,61 @@ bool Sinking::runOnFunction(Function &F) { - // Process all basic blocks. - for (Function::iterator I = F.begin(), E = F.end(); - I != E; ++I) -- MadeChange |= ProcessBlock(*I); -+ MadeChange |= ProcessBlock(*I, DT, LI, AA); - EverMadeChange |= MadeChange; - NumSinkIter++; - } while (MadeChange); - - return EverMadeChange; - } -+ -+PreservedAnalyses SinkingPass::run(Function &F, AnalysisManager &AM) { -+ auto &DT = AM.getResult(F); -+ auto &LI = AM.getResult(F); -+ auto &AA = AM.getResult(F); -+ -+ if (!iterativelySinkInstructions(F, DT, LI, AA)) -+ return PreservedAnalyses::all(); -+ -+ auto PA = PreservedAnalyses(); -+ PA.preserve(); -+ PA.preserve(); -+ return PA; -+} -+ -+namespace { -+ class SinkingLegacyPass : public FunctionPass { -+ public: -+ static char ID; // Pass identification -+ SinkingLegacyPass() : FunctionPass(ID) { -+ initializeSinkingLegacyPassPass(*PassRegistry::getPassRegistry()); -+ } -+ -+ bool runOnFunction(Function &F) override { -+ auto &DT = getAnalysis().getDomTree(); -+ auto &LI = getAnalysis().getLoopInfo(); -+ auto &AA = getAnalysis().getAAResults(); -+ -+ return iterativelySinkInstructions(F, DT, LI, AA); -+ } -+ -+ void getAnalysisUsage(AnalysisUsage &AU) const override { -+ AU.setPreservesCFG(); -+ FunctionPass::getAnalysisUsage(AU); -+ AU.addRequired(); -+ AU.addRequired(); -+ AU.addRequired(); -+ AU.addPreserved(); -+ AU.addPreserved(); -+ } -+ }; -+} // end anonymous namespace -+ -+char SinkingLegacyPass::ID = 0; -+INITIALIZE_PASS_BEGIN(SinkingLegacyPass, "sink", "Code sinking", false, false) -+INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) -+INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) -+INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass) -+INITIALIZE_PASS_END(SinkingLegacyPass, "sink", "Code sinking", false, false) -+ -+FunctionPass *llvm::createSinkingPass() { return new SinkingLegacyPass(); } - -commit 82077c4ab0b05980492f14b9cf31f6a4af35da34 -Author: Justin Bogner -Date: Fri Apr 22 19:54:04 2016 +0000 - - PM: Reorder the functions used for SinkingPass. NFC - - This will make the port to the new PM easier to follow. - - llvm-svn: 267198 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index eb09f584dc68..e5860328d04f 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -96,66 +96,6 @@ bool Sinking::AllUsesDominatedByBlock(Instruction *Inst, - return true; - } - --bool Sinking::runOnFunction(Function &F) { -- DT = &getAnalysis().getDomTree(); -- LI = &getAnalysis().getLoopInfo(); -- AA = &getAnalysis().getAAResults(); -- -- bool MadeChange, EverMadeChange = false; -- -- do { -- MadeChange = false; -- DEBUG(dbgs() << "Sinking iteration " << NumSinkIter << "\n"); -- // Process all basic blocks. -- for (Function::iterator I = F.begin(), E = F.end(); -- I != E; ++I) -- MadeChange |= ProcessBlock(*I); -- EverMadeChange |= MadeChange; -- NumSinkIter++; -- } while (MadeChange); -- -- return EverMadeChange; --} -- --bool Sinking::ProcessBlock(BasicBlock &BB) { -- // Can't sink anything out of a block that has less than two successors. -- if (BB.getTerminator()->getNumSuccessors() <= 1) return false; -- -- // Don't bother sinking code out of unreachable blocks. In addition to being -- // unprofitable, it can also lead to infinite looping, because in an -- // unreachable loop there may be nowhere to stop. -- if (!DT->isReachableFromEntry(&BB)) return false; -- -- bool MadeChange = false; -- -- // Walk the basic block bottom-up. Remember if we saw a store. -- BasicBlock::iterator I = BB.end(); -- --I; -- bool ProcessedBegin = false; -- SmallPtrSet Stores; -- do { -- Instruction *Inst = &*I; // The instruction to sink. -- -- // Predecrement I (if it's not begin) so that it isn't invalidated by -- // sinking. -- ProcessedBegin = I == BB.begin(); -- if (!ProcessedBegin) -- --I; -- -- if (isa(Inst)) -- continue; -- -- if (SinkInstruction(Inst, Stores)) { -- ++NumSunk; -- MadeChange = true; -- } -- -- // If we just processed the first instruction in the block, we're done. -- } while (!ProcessedBegin); -- -- return MadeChange; --} -- - static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, - SmallPtrSetImpl &Stores) { - -@@ -290,3 +230,63 @@ bool Sinking::SinkInstruction(Instruction *Inst, - Inst->moveBefore(&*SuccToSinkTo->getFirstInsertionPt()); - return true; - } -+ -+bool Sinking::ProcessBlock(BasicBlock &BB) { -+ // Can't sink anything out of a block that has less than two successors. -+ if (BB.getTerminator()->getNumSuccessors() <= 1) return false; -+ -+ // Don't bother sinking code out of unreachable blocks. In addition to being -+ // unprofitable, it can also lead to infinite looping, because in an -+ // unreachable loop there may be nowhere to stop. -+ if (!DT->isReachableFromEntry(&BB)) return false; -+ -+ bool MadeChange = false; -+ -+ // Walk the basic block bottom-up. Remember if we saw a store. -+ BasicBlock::iterator I = BB.end(); -+ --I; -+ bool ProcessedBegin = false; -+ SmallPtrSet Stores; -+ do { -+ Instruction *Inst = &*I; // The instruction to sink. -+ -+ // Predecrement I (if it's not begin) so that it isn't invalidated by -+ // sinking. -+ ProcessedBegin = I == BB.begin(); -+ if (!ProcessedBegin) -+ --I; -+ -+ if (isa(Inst)) -+ continue; -+ -+ if (SinkInstruction(Inst, Stores)) { -+ ++NumSunk; -+ MadeChange = true; -+ } -+ -+ // If we just processed the first instruction in the block, we're done. -+ } while (!ProcessedBegin); -+ -+ return MadeChange; -+} -+ -+bool Sinking::runOnFunction(Function &F) { -+ DT = &getAnalysis().getDomTree(); -+ LI = &getAnalysis().getLoopInfo(); -+ AA = &getAnalysis().getAAResults(); -+ -+ bool MadeChange, EverMadeChange = false; -+ -+ do { -+ MadeChange = false; -+ DEBUG(dbgs() << "Sinking iteration " << NumSinkIter << "\n"); -+ // Process all basic blocks. -+ for (Function::iterator I = F.begin(), E = F.end(); -+ I != E; ++I) -+ MadeChange |= ProcessBlock(*I); -+ EverMadeChange |= MadeChange; -+ NumSinkIter++; -+ } while (MadeChange); -+ -+ return EverMadeChange; -+} - -commit 7a08381403b54cd8998f3c922f18b65867e3c07c -Author: Richard Trieu -Date: Thu Feb 18 22:09:30 2016 +0000 - - Remove uses of builtin comma operator. - - Cleanup for upcoming Clang warning -Wcomma. No functionality change intended. - - llvm-svn: 261270 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 64109b2df117..eb09f584dc68 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -145,8 +145,10 @@ bool Sinking::ProcessBlock(BasicBlock &BB) { - if (isa(Inst)) - continue; - -- if (SinkInstruction(Inst, Stores)) -- ++NumSunk, MadeChange = true; -+ if (SinkInstruction(Inst, Stores)) { -+ ++NumSunk; -+ MadeChange = true; -+ } - - // If we just processed the first instruction in the block, we're done. - } while (!ProcessedBegin); - -commit 8a1c45d6e86d54c40835fa8638d1fd900071783c -Author: David Majnemer -Date: Sat Dec 12 05:38:55 2015 +0000 - - [IR] Reformulate LLVM's EH funclet IR - - While we have successfully implemented a funclet-oriented EH scheme on - top of LLVM IR, our scheme has some notable deficiencies: - - catchendpad and cleanupendpad are necessary in the current design - but they are difficult to explain to others, even to seasoned LLVM - experts. - - catchendpad and cleanupendpad are optimization barriers. They cannot - be split and force all potentially throwing call-sites to be invokes. - This has a noticable effect on the quality of our code generation. - - catchpad, while similar in some aspects to invoke, is fairly awkward. - It is unsplittable, starts a funclet, and has control flow to other - funclets. - - The nesting relationship between funclets is currently a property of - control flow edges. Because of this, we are forced to carefully - analyze the flow graph to see if there might potentially exist illegal - nesting among funclets. While we have logic to clone funclets when - they are illegally nested, it would be nicer if we had a - representation which forbade them upfront. - - Let's clean this up a bit by doing the following: - - Instead, make catchpad more like cleanuppad and landingpad: no control - flow, just a bunch of simple operands; catchpad would be splittable. - - Introduce catchswitch, a control flow instruction designed to model - the constraints of funclet oriented EH. - - Make funclet scoping explicit by having funclet instructions consume - the token produced by the funclet which contains them. - - Remove catchendpad and cleanupendpad. Their presence can be inferred - implicitly using coloring information. - - N.B. The state numbering code for the CLR has been updated but the - veracity of it's output cannot be spoken for. An expert should take a - look to make sure the results are reasonable. - - Reviewers: rnk, JosephTremoulet, andrew.w.kaylor - - Differential Revision: http://reviews.llvm.org/D15139 - - llvm-svn: 255422 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 7c0ac7aa6fae..64109b2df117 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -169,7 +169,8 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, - return false; - } - -- if (isa(Inst) || isa(Inst) || Inst->isEHPad()) -+ if (isa(Inst) || isa(Inst) || Inst->isEHPad() || -+ Inst->mayThrow()) - return false; - - // Convergent operations cannot be made control-dependent on additional -@@ -194,6 +195,11 @@ bool Sinking::IsAcceptableTarget(Instruction *Inst, - if (Inst->getParent() == SuccToSinkTo) - return false; - -+ // It's never legal to sink an instruction into a block which terminates in an -+ // EH-pad. -+ if (SuccToSinkTo->getTerminator()->isExceptional()) -+ return false; -+ - // If the block has multiple predecessors, this would introduce computation - // on different code paths. We could split the critical edge, but for now we - // just punt. - -commit 86c95b5642807d2aba091f437d11691b3a285439 -Author: Keno Fischer -Date: Mon Nov 16 04:47:58 2015 +0000 - - [Sink] Don't move landingpads - - Summary: Moving landingpads into successor basic blocks makes the - verifier sad. Teach Sink that much like PHI nodes and terminator - instructions, landingpads (and cleanuppads, etc.) may not be moved - between basic blocks. - - Reviewers: majnemer - - Subscribers: llvm-commits - - Differential Revision: http://reviews.llvm.org/D14475 - - llvm-svn: 253182 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index f6ccd999ea00..7c0ac7aa6fae 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -169,7 +169,7 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, - return false; - } - -- if (isa(Inst) || isa(Inst)) -+ if (isa(Inst) || isa(Inst) || Inst->isEHPad()) - return false; - - // Convergent operations cannot be made control-dependent on additional - -commit e0675fb8fbc78bd1e60bab0c1fac711eab96ab6e -Author: David Majnemer -Date: Thu Oct 22 20:29:08 2015 +0000 - - [Sink] Don't check BB.empty() - - As an invariant, BasicBlocks cannot be empty when passed to a transform. - This is not the case for MachineBasicBlocks and the Sink pass was ported - from the MachineSink pass which would explain the check's existence. - - llvm-svn: 251057 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 8b916347999c..f6ccd999ea00 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -119,7 +119,7 @@ bool Sinking::runOnFunction(Function &F) { - - bool Sinking::ProcessBlock(BasicBlock &BB) { - // Can't sink anything out of a block that has less than two successors. -- if (BB.getTerminator()->getNumSuccessors() <= 1 || BB.empty()) return false; -+ if (BB.getTerminator()->getNumSuccessors() <= 1) return false; - - // Don't bother sinking code out of unreachable blocks. In addition to being - // unprofitable, it can also lead to infinite looping, because in an - -commit be4d8cba1ccf6f0611db50e8c7ba366ce3a3137d -Author: Duncan P. N. Exon Smith -Date: Tue Oct 13 19:26:58 2015 +0000 - - Scalar: Remove remaining ilist iterator implicit conversions - - Remove remaining `ilist_iterator` implicit conversions from - LLVMScalarOpts. - - This change exposed some scary behaviour in - lib/Transforms/Scalar/SCCP.cpp around line 1770. This patch changes a - call from `Function::begin()` to `&Function::front()`, since the return - was immediately being passed into another function that takes a - `Function*`. `Function::front()` started to assert, since the function - was empty. Note that `Function::end()` does not point at a legal - `Function*` -- it points at an `ilist_half_node` -- so the other - function was getting garbage before. (I added the missing check for - `Function::isDeclaration()`.) - - Otherwise, no functionality change intended. - - llvm-svn: 250211 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 17a6858a0c00..8b916347999c 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -134,7 +134,7 @@ bool Sinking::ProcessBlock(BasicBlock &BB) { - bool ProcessedBegin = false; - SmallPtrSet Stores; - do { -- Instruction *Inst = I; // The instruction to sink. -+ Instruction *Inst = &*I; // The instruction to sink. - - // Predecrement I (if it's not begin) so that it isn't invalidated by - // sinking. -@@ -279,6 +279,6 @@ bool Sinking::SinkInstruction(Instruction *Inst, - dbgs() << ")\n"); - - // Move the instruction. -- Inst->moveBefore(SuccToSinkTo->getFirstInsertionPt()); -+ Inst->moveBefore(&*SuccToSinkTo->getFirstInsertionPt()); - return true; - } - -commit d95b08a0a72ef47268b94738360c9319dcdc4772 -Author: Owen Anderson -Date: Fri Oct 9 18:06:13 2015 +0000 - - Refine the definition of convergent to only disallow the addition of new control dependencies. - - This covers the common case of operations that cannot be sunk. - Operations that cannot be hoisted should already be handled properly via - the safe-to-speculate rules and mechanisms. - - llvm-svn: 249865 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index adc53b17bdf9..17a6858a0c00 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -172,7 +172,8 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, - if (isa(Inst) || isa(Inst)) - return false; - -- // Convergent operations can only be moved to control equivalent blocks. -+ // Convergent operations cannot be made control-dependent on additional -+ // values. - if (auto CS = CallSite(Inst)) { - if (CS.hasFnAttr(Attribute::Convergent)) - return false; - -commit 7b560d40bddfb60f162a7541288aeba3776f79f8 -Author: Chandler Carruth -Date: Wed Sep 9 17:55:00 2015 +0000 - - [PM/AA] Rebuild LLVM's alias analysis infrastructure in a way compatible - with the new pass manager, and no longer relying on analysis groups. - - This builds essentially a ground-up new AA infrastructure stack for - LLVM. The core ideas are the same that are used throughout the new pass - manager: type erased polymorphism and direct composition. The design is - as follows: - - - FunctionAAResults is a type-erasing alias analysis results aggregation - interface to walk a single query across a range of results from - different alias analyses. Currently this is function-specific as we - always assume that aliasing queries are *within* a function. - - - AAResultBase is a CRTP utility providing stub implementations of - various parts of the alias analysis result concept, notably in several - cases in terms of other more general parts of the interface. This can - be used to implement only a narrow part of the interface rather than - the entire interface. This isn't really ideal, this logic should be - hoisted into FunctionAAResults as currently it will cause - a significant amount of redundant work, but it faithfully models the - behavior of the prior infrastructure. - - - All the alias analysis passes are ported to be wrapper passes for the - legacy PM and new-style analysis passes for the new PM with a shared - result object. In some cases (most notably CFL), this is an extremely - naive approach that we should revisit when we can specialize for the - new pass manager. - - - BasicAA has been restructured to reflect that it is much more - fundamentally a function analysis because it uses dominator trees and - loop info that need to be constructed for each function. - - All of the references to getting alias analysis results have been - updated to use the new aggregation interface. All the preservation and - other pass management code has been updated accordingly. - - The way the FunctionAAResultsWrapperPass works is to detect the - available alias analyses when run, and add them to the results object. - This means that we should be able to continue to respect when various - passes are added to the pipeline, for example adding CFL or adding TBAA - passes should just cause their results to be available and to get folded - into this. The exception to this rule is BasicAA which really needs to - be a function pass due to using dominator trees and loop info. As - a consequence, the FunctionAAResultsWrapperPass directly depends on - BasicAA and always includes it in the aggregation. - - This has significant implications for preserving analyses. Generally, - most passes shouldn't bother preserving FunctionAAResultsWrapperPass - because rebuilding the results just updates the set of known AA passes. - The exception to this rule are LoopPass instances which need to preserve - all the function analyses that the loop pass manager will end up - needing. This means preserving both BasicAAWrapperPass and the - aggregating FunctionAAResultsWrapperPass. - - Now, when preserving an alias analysis, you do so by directly preserving - that analysis. This is only necessary for non-immutable-pass-provided - alias analyses though, and there are only three of interest: BasicAA, - GlobalsAA (formerly GlobalsModRef), and SCEVAA. Usually BasicAA is - preserved when needed because it (like DominatorTree and LoopInfo) is - marked as a CFG-only pass. I've expanded GlobalsAA into the preserved - set everywhere we previously were preserving all of AliasAnalysis, and - I've added SCEVAA in the intersection of that with where we preserve - SCEV itself. - - One significant challenge to all of this is that the CGSCC passes were - actually using the alias analysis implementations by taking advantage of - a pretty amazing set of loop holes in the old pass manager's analysis - management code which allowed analysis groups to slide through in many - cases. Moving away from analysis groups makes this problem much more - obvious. To fix it, I've leveraged the flexibility the design of the new - PM components provides to just directly construct the relevant alias - analyses for the relevant functions in the IPO passes that need them. - This is a bit hacky, but should go away with the new pass manager, and - is already in many ways cleaner than the prior state. - - Another significant challenge is that various facilities of the old - alias analysis infrastructure just don't fit any more. The most - significant of these is the alias analysis 'counter' pass. That pass - relied on the ability to snoop on AA queries at different points in the - analysis group chain. Instead, I'm planning to build printing - functionality directly into the aggregation layer. I've not included - that in this patch merely to keep it smaller. - - Note that all of this needs a nearly complete rewrite of the AA - documentation. I'm planning to do that, but I'd like to make sure the - new design settles, and to flesh out a bit more of what it looks like in - the new pass manager first. - - Differential Revision: http://reviews.llvm.org/D12080 - - llvm-svn: 247167 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 17684c04dc4d..adc53b17bdf9 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -48,7 +48,7 @@ namespace { - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.setPreservesCFG(); - FunctionPass::getAnalysisUsage(AU); -- AU.addRequired(); -+ AU.addRequired(); - AU.addRequired(); - AU.addRequired(); - AU.addPreserved(); -@@ -66,7 +66,7 @@ char Sinking::ID = 0; - INITIALIZE_PASS_BEGIN(Sinking, "sink", "Code sinking", false, false) - INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) - INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) --INITIALIZE_AG_DEPENDENCY(AliasAnalysis) -+INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass) - INITIALIZE_PASS_END(Sinking, "sink", "Code sinking", false, false) - - FunctionPass *llvm::createSinkingPass() { return new Sinking(); } -@@ -99,7 +99,7 @@ bool Sinking::AllUsesDominatedByBlock(Instruction *Inst, - bool Sinking::runOnFunction(Function &F) { - DT = &getAnalysis().getDomTree(); - LI = &getAnalysis().getLoopInfo(); -- AA = &getAnalysis(); -+ AA = &getAnalysis().getAAResults(); - - bool MadeChange, EverMadeChange = false; - - -commit 194f59ca5d2f48f1e0b7fa95971ae9f88e95ba95 -Author: Chandler Carruth -Date: Wed Jul 22 23:15:57 2015 +0000 - - [PM/AA] Extract the ModRef enums from the AliasAnalysis class in - preparation for de-coupling the AA implementations. - - In order to do this, they had to become fake-scoped using the - traditional LLVM pattern of a leading initialism. These can't be actual - scoped enumerations because they're bitfields and thus inherently we use - them as integers. - - I've also renamed the behavior enums that are specific to reasoning - about the mod/ref behavior of functions when called. This makes it more - clear that they have a very narrow domain of applicability. - - I think there is a significantly cleaner API for all of this, but - I don't want to try to do really substantive changes for now, I just - want to refactor the things away from analysis groups so I'm preserving - the exact original design and just cleaning up the names, style, and - lifting out of the class. - - Differential Revision: http://reviews.llvm.org/D10564 - - llvm-svn: 242963 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index f49f4eaaedcb..17684c04dc4d 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -165,7 +165,7 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, - if (LoadInst *L = dyn_cast(Inst)) { - MemoryLocation Loc = MemoryLocation::get(L); - for (Instruction *S : Stores) -- if (AA->getModRefInfo(S, Loc) & AliasAnalysis::Mod) -+ if (AA->getModRefInfo(S, Loc) & MRI_Mod) - return false; - } - - -commit ac80dc753228af5f1b415bc9fa9834aeba19122b -Author: Chandler Carruth -Date: Wed Jun 17 07:18:54 2015 +0000 - - [PM/AA] Remove the Location typedef from the AliasAnalysis class now - that it is its own entity in the form of MemoryLocation, and update all - the callers. - - This is an entirely mechanical change. References to "Location" within - AA subclases become "MemoryLocation", and elsewhere - "AliasAnalysis::Location" becomes "MemoryLocation". Hope that helps - out-of-tree folks update. - - llvm-svn: 239885 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 078c6a921a08..f49f4eaaedcb 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -163,7 +163,7 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, - } - - if (LoadInst *L = dyn_cast(Inst)) { -- AliasAnalysis::Location Loc = MemoryLocation::get(L); -+ MemoryLocation Loc = MemoryLocation::get(L); - for (Instruction *S : Stores) - if (AA->getModRefInfo(S, Loc) & AliasAnalysis::Mod) - return false; - -commit 70c61c1a8adad268f1058986aa501afb142ecb4c -Author: Chandler Carruth -Date: Thu Jun 4 02:03:15 2015 +0000 - - [PM/AA] Start refactoring AliasAnalysis to remove the analysis group and - port it to the new pass manager. - - All this does is extract the inner "location" class used by AA into its - own full fledged type. This seems *much* cleaner as MemoryDependence and - soon MemorySSA also use this heavily, and it doesn't make much sense - being inside the AA infrastructure. - - This will also make it much easier to break apart the AA infrastructure - into something that stands on its own rather than using the analysis - group design. - - There are a few places where this makes APIs not make sense -- they were - taking an AliasAnalysis pointer just to build locations. I'll try to - clean those up in follow-up commits. - - Differential Revision: http://reviews.llvm.org/D10228 - - llvm-svn: 239003 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index ec3a0186641e..078c6a921a08 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -163,7 +163,7 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, - } - - if (LoadInst *L = dyn_cast(Inst)) { -- AliasAnalysis::Location Loc = AA->getLocation(L); -+ AliasAnalysis::Location Loc = MemoryLocation::get(L); - for (Instruction *S : Stores) - if (AA->getModRefInfo(S, Loc) & AliasAnalysis::Mod) - return false; - -commit 15d180550448a7561e5d3c7e1ffa22602f2b3ed7 -Author: Owen Anderson -Date: Mon Jun 1 17:20:31 2015 +0000 - - Teach the IR Sink pass to (conservatively) respect convergent annotations. - - llvm-svn: 238762 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index b169d5612f00..ec3a0186641e 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -172,6 +172,12 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, - if (isa(Inst) || isa(Inst)) - return false; - -+ // Convergent operations can only be moved to control equivalent blocks. -+ if (auto CS = CallSite(Inst)) { -+ if (CS.hasFnAttr(Attribute::Convergent)) -+ return false; -+ } -+ - return true; - } - - -commit a28d91d81b5daa4d8b92452ea8203a57023b576f -Author: Mehdi Amini -Date: Tue Mar 10 02:37:25 2015 +0000 - - DataLayout is mandatory, update the API to reflect it with references. - - Summary: - Now that the DataLayout is a mandatory part of the module, let's start - cleaning the codebase. This patch is a first attempt at doing that. - - This patch is not exactly NFC as for instance some places were passing - a nullptr instead of the DataLayout, possibly just because there was a - default value on the DataLayout argument to many functions in the API. - Even though it is not purely NFC, there is no change in the - validation. - - I turned as many pointer to DataLayout to references, this helped - figuring out all the places where a nullptr could come up. - - I had initially a local version of this patch broken into over 30 - independant, commits but some later commit were cleaning the API and - touching part of the code modified in the previous commits, so it - seemed cleaner without the intermediate state. - - Test Plan: - - Reviewers: echristo - - Subscribers: llvm-commits - - From: Mehdi Amini - llvm-svn: 231740 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 4ba3f1949db6..b169d5612f00 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -36,7 +36,6 @@ namespace { - DominatorTree *DT; - LoopInfo *LI; - AliasAnalysis *AA; -- const DataLayout *DL; - - public: - static char ID; // Pass identification -@@ -101,7 +100,6 @@ bool Sinking::runOnFunction(Function &F) { - DT = &getAnalysis().getDomTree(); - LI = &getAnalysis().getLoopInfo(); - AA = &getAnalysis(); -- DL = &F.getParent()->getDataLayout(); - - bool MadeChange, EverMadeChange = false; - -@@ -196,7 +194,7 @@ bool Sinking::IsAcceptableTarget(Instruction *Inst, - if (SuccToSinkTo->getUniquePredecessor() != Inst->getParent()) { - // We cannot sink a load across a critical edge - there may be stores in - // other code paths. -- if (!isSafeToSpeculativelyExecute(Inst, DL)) -+ if (!isSafeToSpeculativelyExecute(Inst)) - return false; - - // We don't want to sink across a critical edge if we don't dominate the - -commit 46a43556db23edb514f190cc03b0ce7f68d40534 -Author: Mehdi Amini -Date: Wed Mar 4 18:43:29 2015 +0000 - - Make DataLayout Non-Optional in the Module - - Summary: - DataLayout keeps the string used for its creation. - - As a side effect it is no longer needed in the Module. - This is "almost" NFC, the string is no longer - canonicalized, you can't rely on two "equals" DataLayout - having the same string returned by getStringRepresentation(). - - Get rid of DataLayoutPass: the DataLayout is in the Module - - The DataLayout is "per-module", let's enforce this by not - duplicating it more than necessary. - One more step toward non-optionality of the DataLayout in the - module. - - Make DataLayout Non-Optional in the Module - - Module->getDataLayout() will never returns nullptr anymore. - - Reviewers: echristo - - Subscribers: resistor, llvm-commits, jholewinski - - Differential Revision: http://reviews.llvm.org/D7992 - - From: Mehdi Amini - llvm-svn: 231270 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index d0ee0a679b38..4ba3f1949db6 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -21,6 +21,7 @@ - #include "llvm/IR/DataLayout.h" - #include "llvm/IR/Dominators.h" - #include "llvm/IR/IntrinsicInst.h" -+#include "llvm/IR/Module.h" - #include "llvm/Support/Debug.h" - #include "llvm/Support/raw_ostream.h" - using namespace llvm; -@@ -100,8 +101,7 @@ bool Sinking::runOnFunction(Function &F) { - DT = &getAnalysis().getDomTree(); - LI = &getAnalysis().getLoopInfo(); - AA = &getAnalysis(); -- DataLayoutPass *DLP = getAnalysisIfAvailable(); -- DL = DLP ? &DLP->getDataLayout() : nullptr; -+ DL = &F.getParent()->getDataLayout(); - - bool MadeChange, EverMadeChange = false; - - -commit 4f8f307c77fa5b4de2eec8868b8734b2ab93dd22 -Author: Chandler Carruth -Date: Sat Jan 17 14:16:18 2015 +0000 - - [PM] Split the LoopInfo object apart from the legacy pass, creating - a LoopInfoWrapperPass to wire the object up to the legacy pass manager. - - This switches all the clients of LoopInfo over and paves the way to port - LoopInfo to the new pass manager. No functionality change is intended - with this iteration. - - llvm-svn: 226373 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 903b675fdd56..d0ee0a679b38 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -50,9 +50,9 @@ namespace { - FunctionPass::getAnalysisUsage(AU); - AU.addRequired(); - AU.addRequired(); -- AU.addRequired(); -+ AU.addRequired(); - AU.addPreserved(); -- AU.addPreserved(); -+ AU.addPreserved(); - } - private: - bool ProcessBlock(BasicBlock &BB); -@@ -64,7 +64,7 @@ namespace { - - char Sinking::ID = 0; - INITIALIZE_PASS_BEGIN(Sinking, "sink", "Code sinking", false, false) --INITIALIZE_PASS_DEPENDENCY(LoopInfo) -+INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) - INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) - INITIALIZE_AG_DEPENDENCY(AliasAnalysis) - INITIALIZE_PASS_END(Sinking, "sink", "Code sinking", false, false) -@@ -98,7 +98,7 @@ bool Sinking::AllUsesDominatedByBlock(Instruction *Inst, - - bool Sinking::runOnFunction(Function &F) { - DT = &getAnalysis().getDomTree(); -- LI = &getAnalysis(); -+ LI = &getAnalysis().getLoopInfo(); - AA = &getAnalysis(); - DataLayoutPass *DLP = getAnalysisIfAvailable(); - DL = DLP ? &DLP->getDataLayout() : nullptr; - -commit 4627679cece264a966faa82a7c5bb79f273d5b6e -Author: Craig Topper -Date: Sun Aug 24 23:23:06 2014 +0000 - - Use range based for loops to avoid needing to re-mention SmallPtrSet size. - - llvm-svn: 216351 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 2f4e23a7488b..903b675fdd56 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -166,9 +166,8 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, - - if (LoadInst *L = dyn_cast(Inst)) { - AliasAnalysis::Location Loc = AA->getLocation(L); -- for (SmallPtrSet::iterator I = Stores.begin(), -- E = Stores.end(); I != E; ++I) -- if (AA->getModRefInfo(*I, Loc) & AliasAnalysis::Mod) -+ for (Instruction *S : Stores) -+ if (AA->getModRefInfo(S, Loc) & AliasAnalysis::Mod) - return false; - } - - -commit 71b7b68b741a29c473479c64dbaca00b94e316ab -Author: Craig Topper -Date: Thu Aug 21 05:55:13 2014 +0000 - - Repace SmallPtrSet with SmallPtrSetImpl in function arguments to avoid needing to mention the size. - - llvm-svn: 216158 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 7348c45c5d37..2f4e23a7488b 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -56,7 +56,7 @@ namespace { - } - private: - bool ProcessBlock(BasicBlock &BB); -- bool SinkInstruction(Instruction *I, SmallPtrSet &Stores); -+ bool SinkInstruction(Instruction *I, SmallPtrSetImpl &Stores); - bool AllUsesDominatedByBlock(Instruction *Inst, BasicBlock *BB) const; - bool IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo) const; - }; -@@ -157,7 +157,7 @@ bool Sinking::ProcessBlock(BasicBlock &BB) { - } - - static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, -- SmallPtrSet &Stores) { -+ SmallPtrSetImpl &Stores) { - - if (Inst->mayWriteToMemory()) { - Stores.insert(Inst); -@@ -220,7 +220,7 @@ bool Sinking::IsAcceptableTarget(Instruction *Inst, - /// SinkInstruction - Determine whether it is safe to sink the specified machine - /// instruction out of its current block into a successor. - bool Sinking::SinkInstruction(Instruction *Inst, -- SmallPtrSet &Stores) { -+ SmallPtrSetImpl &Stores) { - - // Don't sink static alloca instructions. CodeGen assumes allocas outside the - // entry block are dynamically sized stack objects. - -commit 6230691c9186e95cd19dff07074a54fb70719957 -Author: Craig Topper -Date: Mon Aug 18 00:24:38 2014 +0000 - - Revert "Repace SmallPtrSet with SmallPtrSetImpl in function arguments to avoid needing to mention the size." - - Getting a weird buildbot failure that I need to investigate. - - llvm-svn: 215870 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 2f4e23a7488b..7348c45c5d37 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -56,7 +56,7 @@ namespace { - } - private: - bool ProcessBlock(BasicBlock &BB); -- bool SinkInstruction(Instruction *I, SmallPtrSetImpl &Stores); -+ bool SinkInstruction(Instruction *I, SmallPtrSet &Stores); - bool AllUsesDominatedByBlock(Instruction *Inst, BasicBlock *BB) const; - bool IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo) const; - }; -@@ -157,7 +157,7 @@ bool Sinking::ProcessBlock(BasicBlock &BB) { - } - - static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, -- SmallPtrSetImpl &Stores) { -+ SmallPtrSet &Stores) { - - if (Inst->mayWriteToMemory()) { - Stores.insert(Inst); -@@ -220,7 +220,7 @@ bool Sinking::IsAcceptableTarget(Instruction *Inst, - /// SinkInstruction - Determine whether it is safe to sink the specified machine - /// instruction out of its current block into a successor. - bool Sinking::SinkInstruction(Instruction *Inst, -- SmallPtrSetImpl &Stores) { -+ SmallPtrSet &Stores) { - - // Don't sink static alloca instructions. CodeGen assumes allocas outside the - // entry block are dynamically sized stack objects. - -commit 5229cfd1638705a7dbf668a840c6015f6b3ecbc6 -Author: Craig Topper -Date: Sun Aug 17 23:47:00 2014 +0000 - - Repace SmallPtrSet with SmallPtrSetImpl in function arguments to avoid needing to mention the size. - - llvm-svn: 215868 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 7348c45c5d37..2f4e23a7488b 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -56,7 +56,7 @@ namespace { - } - private: - bool ProcessBlock(BasicBlock &BB); -- bool SinkInstruction(Instruction *I, SmallPtrSet &Stores); -+ bool SinkInstruction(Instruction *I, SmallPtrSetImpl &Stores); - bool AllUsesDominatedByBlock(Instruction *Inst, BasicBlock *BB) const; - bool IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo) const; - }; -@@ -157,7 +157,7 @@ bool Sinking::ProcessBlock(BasicBlock &BB) { - } - - static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, -- SmallPtrSet &Stores) { -+ SmallPtrSetImpl &Stores) { - - if (Inst->mayWriteToMemory()) { - Stores.insert(Inst); -@@ -220,7 +220,7 @@ bool Sinking::IsAcceptableTarget(Instruction *Inst, - /// SinkInstruction - Determine whether it is safe to sink the specified machine - /// instruction out of its current block into a successor. - bool Sinking::SinkInstruction(Instruction *Inst, -- SmallPtrSet &Stores) { -+ SmallPtrSetImpl &Stores) { - - // Don't sink static alloca instructions. CodeGen assumes allocas outside the - // entry block are dynamically sized stack objects. - -commit 6c99015fe2c1814f793530adc96f48050081612e -Author: Duncan P. N. Exon Smith -Date: Mon Jul 21 17:06:51 2014 +0000 - - Revert "[C++11] Add predecessors(BasicBlock *) / successors(BasicBlock *) iterator ranges." - - This reverts commit r213474 (and r213475), which causes a miscompile on - a stage2 LTO build. I'll reply on the list in a moment. - - llvm-svn: 213562 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 2f7a9f9a65cf..7348c45c5d37 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -258,11 +258,10 @@ bool Sinking::SinkInstruction(Instruction *Inst, - - // If no suitable postdominator was found, look at all the successors and - // decide which one we should sink to, if any. -- for (BasicBlock *Succ : successors(Inst->getParent())) { -- if (SuccToSinkTo) -- break; -- if (IsAcceptableTarget(Inst, Succ)) -- SuccToSinkTo = Succ; -+ for (succ_iterator I = succ_begin(Inst->getParent()), -+ E = succ_end(Inst->getParent()); I != E && !SuccToSinkTo; ++I) { -+ if (IsAcceptableTarget(Inst, *I)) -+ SuccToSinkTo = *I; - } - - // If we couldn't find a block to sink to, ignore this instruction. - -commit d11beffef4f1117aceb9f2f5532b4a317c30c05a -Author: Manuel Jacob -Date: Sun Jul 20 09:10:11 2014 +0000 - - [C++11] Add predecessors(BasicBlock *) / successors(BasicBlock *) iterator ranges. - - Summary: This patch introduces two new iterator ranges and updates existing code to use it. No functional change intended. - - Test Plan: All tests (make check-all) still pass. - - Reviewers: dblaikie - - Reviewed By: dblaikie - - Subscribers: llvm-commits - - Differential Revision: http://reviews.llvm.org/D4481 - - llvm-svn: 213474 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 7348c45c5d37..2f7a9f9a65cf 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -258,10 +258,11 @@ bool Sinking::SinkInstruction(Instruction *Inst, - - // If no suitable postdominator was found, look at all the successors and - // decide which one we should sink to, if any. -- for (succ_iterator I = succ_begin(Inst->getParent()), -- E = succ_end(Inst->getParent()); I != E && !SuccToSinkTo; ++I) { -- if (IsAcceptableTarget(Inst, *I)) -- SuccToSinkTo = *I; -+ for (BasicBlock *Succ : successors(Inst->getParent())) { -+ if (SuccToSinkTo) -+ break; -+ if (IsAcceptableTarget(Inst, Succ)) -+ SuccToSinkTo = Succ; - } - - // If we couldn't find a block to sink to, ignore this instruction. - -commit 511fea7acdc360bc77978370cfbe0218738ea24c -Author: Hal Finkel -Date: Thu Jul 10 16:07:11 2014 +0000 - - Feeding isSafeToSpeculativelyExecute its DataLayout pointer (in Sink) - - This is the one remaining place I see where passing - isSafeToSpeculativelyExecute a DataLayout pointer might matter (at least for - loads) -- I think I got the others in r212720. Most of the other remaining - callers of isSafeToSpeculativelyExecute only use it for call sites (or - otherwise exclude loads). - - llvm-svn: 212730 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 482c33aa6e0b..7348c45c5d37 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -18,6 +18,7 @@ - #include "llvm/Analysis/LoopInfo.h" - #include "llvm/Analysis/ValueTracking.h" - #include "llvm/IR/CFG.h" -+#include "llvm/IR/DataLayout.h" - #include "llvm/IR/Dominators.h" - #include "llvm/IR/IntrinsicInst.h" - #include "llvm/Support/Debug.h" -@@ -34,6 +35,7 @@ namespace { - DominatorTree *DT; - LoopInfo *LI; - AliasAnalysis *AA; -+ const DataLayout *DL; - - public: - static char ID; // Pass identification -@@ -98,6 +100,8 @@ bool Sinking::runOnFunction(Function &F) { - DT = &getAnalysis().getDomTree(); - LI = &getAnalysis(); - AA = &getAnalysis(); -+ DataLayoutPass *DLP = getAnalysisIfAvailable(); -+ DL = DLP ? &DLP->getDataLayout() : nullptr; - - bool MadeChange, EverMadeChange = false; - -@@ -193,7 +197,7 @@ bool Sinking::IsAcceptableTarget(Instruction *Inst, - if (SuccToSinkTo->getUniquePredecessor() != Inst->getParent()) { - // We cannot sink a load across a critical edge - there may be stores in - // other code paths. -- if (!isSafeToSpeculativelyExecute(Inst)) -+ if (!isSafeToSpeculativelyExecute(Inst, DL)) - return false; - - // We don't want to sink across a critical edge if we don't dominate the - -commit f40110f4d80436071213ed7fcbe367d64aa52c71 -Author: Craig Topper -Date: Fri Apr 25 05:29:35 2014 +0000 - - [C++] Use 'nullptr'. Transforms edition. - - llvm-svn: 207196 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 121ee0923b39..482c33aa6e0b 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -204,7 +204,7 @@ bool Sinking::IsAcceptableTarget(Instruction *Inst, - // Don't sink instructions into a loop. - Loop *succ = LI->getLoopFor(SuccToSinkTo); - Loop *cur = LI->getLoopFor(Inst->getParent()); -- if (succ != 0 && succ != cur) -+ if (succ != nullptr && succ != cur) - return false; - } - -@@ -238,14 +238,14 @@ bool Sinking::SinkInstruction(Instruction *Inst, - - // SuccToSinkTo - This is the successor to sink this instruction to, once we - // decide. -- BasicBlock *SuccToSinkTo = 0; -+ BasicBlock *SuccToSinkTo = nullptr; - - // Instructions can only be sunk if all their uses are in blocks - // dominated by one of the successors. - // Look at all the postdominators and see if we can sink it in one. - DomTreeNode *DTN = DT->getNode(Inst->getParent()); - for (DomTreeNode::iterator I = DTN->begin(), E = DTN->end(); -- I != E && SuccToSinkTo == 0; ++I) { -+ I != E && SuccToSinkTo == nullptr; ++I) { - BasicBlock *Candidate = (*I)->getBlock(); - if ((*I)->getIDom()->getBlock() == Inst->getParent() && - IsAcceptableTarget(Inst, Candidate)) -@@ -255,13 +255,13 @@ bool Sinking::SinkInstruction(Instruction *Inst, - // If no suitable postdominator was found, look at all the successors and - // decide which one we should sink to, if any. - for (succ_iterator I = succ_begin(Inst->getParent()), -- E = succ_end(Inst->getParent()); I != E && SuccToSinkTo == 0; ++I) { -+ E = succ_end(Inst->getParent()); I != E && !SuccToSinkTo; ++I) { - if (IsAcceptableTarget(Inst, *I)) - SuccToSinkTo = *I; - } - - // If we couldn't find a block to sink to, ignore this instruction. -- if (SuccToSinkTo == 0) -+ if (!SuccToSinkTo) - return false; - - DEBUG(dbgs() << "Sink" << *Inst << " ("; - -commit 964daaaf192f76eccb4eb9fed849133c91b96bc5 -Author: Chandler Carruth -Date: Tue Apr 22 02:55:47 2014 +0000 - - [Modules] Fix potential ODR violations by sinking the DEBUG_TYPE - definition below all of the header #include lines, lib/Transforms/... - edition. - - This one is tricky for two reasons. We again have a couple of passes - that define something else before the includes as well. I've sunk their - name macros with the DEBUG_TYPE. - - Also, InstCombine contains headers that need DEBUG_TYPE, so now those - headers #define and #undef DEBUG_TYPE around their code, leaving them - well formed modular headers. Fixing these headers was a large motivation - for all of these changes, as "leaky" macros of this form are hard on the - modules implementation. - - llvm-svn: 206844 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 41073749abc7..121ee0923b39 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -12,7 +12,6 @@ - // - //===----------------------------------------------------------------------===// - --#define DEBUG_TYPE "sink" - #include "llvm/Transforms/Scalar.h" - #include "llvm/ADT/Statistic.h" - #include "llvm/Analysis/AliasAnalysis.h" -@@ -25,6 +24,8 @@ - #include "llvm/Support/raw_ostream.h" - using namespace llvm; - -+#define DEBUG_TYPE "sink" -+ - STATISTIC(NumSunk, "Number of instructions sunk"); - STATISTIC(NumSinkIter, "Number of sinking iterations"); - - -commit edfd81d9656217cc9d14d7854b401bb3d5d559f7 -Author: Tom Stellard -Date: Fri Mar 21 15:51:51 2014 +0000 - - Sink: Don't sink static allocas from the entry block - - CodeGen treats allocas outside the entry block as dynamically sized - stack objects. - - llvm-svn: 204473 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 5e1e4564bba9..41073749abc7 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -216,6 +216,13 @@ bool Sinking::IsAcceptableTarget(Instruction *Inst, - /// instruction out of its current block into a successor. - bool Sinking::SinkInstruction(Instruction *Inst, - SmallPtrSet &Stores) { -+ -+ // Don't sink static alloca instructions. CodeGen assumes allocas outside the -+ // entry block are dynamically sized stack objects. -+ if (AllocaInst *AI = dyn_cast(Inst)) -+ if (AI->isStaticAlloca()) -+ return false; -+ - // Check if it's safe to move the instruction. - if (!isSafeToMove(Inst, AA, Stores)) - return false; - -commit cdf4788401afff02e12279fc1fded94d6180639c -Author: Chandler Carruth -Date: Sun Mar 9 03:16:01 2014 +0000 - - [C++11] Add range based accessors for the Use-Def chain of a Value. - - This requires a number of steps. - 1) Move value_use_iterator into the Value class as an implementation - detail - 2) Change it to actually be a *Use* iterator rather than a *User* - iterator. - 3) Add an adaptor which is a User iterator that always looks through the - Use to the User. - 4) Wrap these in Value::use_iterator and Value::user_iterator typedefs. - 5) Add the range adaptors as Value::uses() and Value::users(). - 6) Update *all* of the callers to correctly distinguish between whether - they wanted a use_iterator (and to explicitly dig out the User when - needed), or a user_iterator which makes the Use itself totally - opaque. - - Because #6 requires churning essentially everything that walked the - Use-Def chains, I went ahead and added all of the range adaptors and - switched them to range-based loops where appropriate. Also because the - renaming requires at least churning every line of code, it didn't make - any sense to split these up into multiple commits -- all of which would - touch all of the same lies of code. - - The result is still not quite optimal. The Value::use_iterator is a nice - regular iterator, but Value::user_iterator is an iterator over User*s - rather than over the User objects themselves. As a consequence, it fits - a bit awkwardly into the range-based world and it has the weird - extra-dereferencing 'operator->' that so many of our iterators have. - I think this could be fixed by providing something which transforms - a range of T&s into a range of T*s, but that *can* be separated into - another patch, and it isn't yet 100% clear whether this is the right - move. - - However, this change gets us most of the benefit and cleans up - a substantial amount of code around Use and User. =] - - llvm-svn: 203364 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 643a5957cf91..5e1e4564bba9 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -76,15 +76,14 @@ bool Sinking::AllUsesDominatedByBlock(Instruction *Inst, - // This may leave a referencing dbg_value in the original block, before - // the definition of the vreg. Dwarf generator handles this although the - // user might not get the right info at runtime. -- for (Value::use_iterator I = Inst->use_begin(), -- E = Inst->use_end(); I != E; ++I) { -+ for (Use &U : Inst->uses()) { - // Determine the block of the use. -- Instruction *UseInst = cast(*I); -+ Instruction *UseInst = cast(U.getUser()); - BasicBlock *UseBlock = UseInst->getParent(); - if (PHINode *PN = dyn_cast(UseInst)) { - // PHI nodes use the operand in the predecessor block, not the block with - // the PHI. -- unsigned Num = PHINode::getIncomingValueNumForOperand(I.getOperandNo()); -+ unsigned Num = PHINode::getIncomingValueNumForOperand(U.getOperandNo()); - UseBlock = PN->getIncomingBlock(Num); - } - // Check that it dominates. - -commit 3e4c697ca1314da24ac34e42293cc28d88fdc134 -Author: Craig Topper -Date: Wed Mar 5 09:10:37 2014 +0000 - - [C++11] Add 'override' keyword to virtual methods that override their base class. - - llvm-svn: 202953 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 287bd5b7d617..643a5957cf91 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -40,9 +40,9 @@ namespace { - initializeSinkingPass(*PassRegistry::getPassRegistry()); - } - -- virtual bool runOnFunction(Function &F); -+ bool runOnFunction(Function &F) override; - -- virtual void getAnalysisUsage(AnalysisUsage &AU) const { -+ void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.setPreservesCFG(); - FunctionPass::getAnalysisUsage(AU); - AU.addRequired(); - -commit 1305dc3351d93e2377b538feff62ccf9518b0291 -Author: Chandler Carruth -Date: Tue Mar 4 11:45:46 2014 +0000 - - [Modules] Move CFG.h to the IR library as it defines graph traits over - IR types. - - llvm-svn: 202827 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index e500c3b24e71..287bd5b7d617 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -18,9 +18,9 @@ - #include "llvm/Analysis/AliasAnalysis.h" - #include "llvm/Analysis/LoopInfo.h" - #include "llvm/Analysis/ValueTracking.h" -+#include "llvm/IR/CFG.h" - #include "llvm/IR/Dominators.h" - #include "llvm/IR/IntrinsicInst.h" --#include "llvm/Support/CFG.h" - #include "llvm/Support/Debug.h" - #include "llvm/Support/raw_ostream.h" - using namespace llvm; - -commit 73523021d0a97c150a76a5cf4a91e99cd03b9efb -Author: Chandler Carruth -Date: Mon Jan 13 13:07:17 2014 +0000 - - [PM] Split DominatorTree into a concrete analysis result object which - can be used by both the new pass manager and the old. - - This removes it from any of the virtual mess of the pass interfaces and - lets it derive cleanly from the DominatorTreeBase<> template. In turn, - tons of boilerplate interface can be nuked and it turns into a very - straightforward extension of the base DominatorTree interface. - - The old analysis pass is now a simple wrapper. The names and style of - this split should match the split between CallGraph and - CallGraphWrapperPass. All of the users of DominatorTree have been - updated to match using many of the same tricks as with CallGraph. The - goal is that the common type remains the resulting DominatorTree rather - than the pass. This will make subsequent work toward the new pass - manager significantly easier. - - Also in numerous places things became cleaner because I switched from - re-running the pass (!!! mid way through some other passes run!!!) to - directly recomputing the domtree. - - llvm-svn: 199104 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index d4c5c73c0332..e500c3b24e71 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -46,9 +46,9 @@ namespace { - AU.setPreservesCFG(); - FunctionPass::getAnalysisUsage(AU); - AU.addRequired(); -- AU.addRequired(); -+ AU.addRequired(); - AU.addRequired(); -- AU.addPreserved(); -+ AU.addPreserved(); - AU.addPreserved(); - } - private: -@@ -62,7 +62,7 @@ namespace { - char Sinking::ID = 0; - INITIALIZE_PASS_BEGIN(Sinking, "sink", "Code sinking", false, false) - INITIALIZE_PASS_DEPENDENCY(LoopInfo) --INITIALIZE_PASS_DEPENDENCY(DominatorTree) -+INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) - INITIALIZE_AG_DEPENDENCY(AliasAnalysis) - INITIALIZE_PASS_END(Sinking, "sink", "Code sinking", false, false) - -@@ -95,7 +95,7 @@ bool Sinking::AllUsesDominatedByBlock(Instruction *Inst, - } - - bool Sinking::runOnFunction(Function &F) { -- DT = &getAnalysis(); -+ DT = &getAnalysis().getDomTree(); - LI = &getAnalysis(); - AA = &getAnalysis(); - - -commit 5ad5f15cffe022de72d0e710714f852ad8a1c6fe -Author: Chandler Carruth -Date: Mon Jan 13 09:26:24 2014 +0000 - - [cleanup] Move the Dominators.h and Verifier.h headers into the IR - directory. These passes are already defined in the IR library, and it - doesn't make any sense to have the headers in Analysis. - - Long term, I think there is going to be a much better way to divide - these matters. The dominators code should be fully separated into the - abstract graph algorithm and have that put in Support where it becomes - obvious that evn Clang's CFGBlock's can use it. Then the verifier can - manually construct dominance information from the Support-driven - interface while the Analysis library can provide a pass which both - caches, reconstructs, and supports a nice update API. - - But those are very long term, and so I don't want to leave the really - confusing structure until that day arrives. - - llvm-svn: 199082 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index a5096da46a08..d4c5c73c0332 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -16,9 +16,9 @@ - #include "llvm/Transforms/Scalar.h" - #include "llvm/ADT/Statistic.h" - #include "llvm/Analysis/AliasAnalysis.h" --#include "llvm/Analysis/Dominators.h" - #include "llvm/Analysis/LoopInfo.h" - #include "llvm/Analysis/ValueTracking.h" -+#include "llvm/IR/Dominators.h" - #include "llvm/IR/IntrinsicInst.h" - #include "llvm/Support/CFG.h" - #include "llvm/Support/Debug.h" - -commit d48cdbf0c3ee31bcac2d8304da2ee5dc16c35056 -Author: Chandler Carruth -Date: Thu Jan 9 02:29:41 2014 +0000 - - Put the functionality for printing a value to a raw_ostream as an - operand into the Value interface just like the core print method is. - That gives a more conistent organization to the IR printing interfaces - -- they are all attached to the IR objects themselves. Also, update all - the users. - - This removes the 'Writer.h' header which contained only a single function - declaration. - - llvm-svn: 198836 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index cf8e5b75ab4d..a5096da46a08 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -20,7 +20,6 @@ - #include "llvm/Analysis/LoopInfo.h" - #include "llvm/Analysis/ValueTracking.h" - #include "llvm/IR/IntrinsicInst.h" --#include "llvm/IR/Writer.h" - #include "llvm/Support/CFG.h" - #include "llvm/Support/Debug.h" - #include "llvm/Support/raw_ostream.h" -@@ -259,9 +258,9 @@ bool Sinking::SinkInstruction(Instruction *Inst, - return false; - - DEBUG(dbgs() << "Sink" << *Inst << " ("; -- WriteAsOperand(dbgs(), Inst->getParent(), false); -+ Inst->getParent()->printAsOperand(dbgs(), false); - dbgs() << " -> "; -- WriteAsOperand(dbgs(), SuccToSinkTo, false); -+ SuccToSinkTo->printAsOperand(dbgs(), false); - dbgs() << ")\n"); - - // Move the instruction. - -commit 9aca918df941788c12f9bef50e5ca0d6f57d2429 -Author: Chandler Carruth -Date: Tue Jan 7 12:34:26 2014 +0000 - - Move the LLVM IR asm writer header files into the IR directory, as they - are part of the core IR library in order to support dumping and other - basic functionality. - - Rename the 'Assembly' include directory to 'AsmParser' to match the - library name and the only functionality left their -- printing has been - in the core IR library for quite some time. - - Update all of the #includes to match. - - All of this started because I wanted to have the layering in good shape - before I started adding support for printing LLVM IR using the new pass - infrastructure, and commandline support for the new pass infrastructure. - - llvm-svn: 198688 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index d4595bb373e6..cf8e5b75ab4d 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -19,8 +19,8 @@ - #include "llvm/Analysis/Dominators.h" - #include "llvm/Analysis/LoopInfo.h" - #include "llvm/Analysis/ValueTracking.h" --#include "llvm/Assembly/Writer.h" - #include "llvm/IR/IntrinsicInst.h" -+#include "llvm/IR/Writer.h" - #include "llvm/Support/CFG.h" - #include "llvm/Support/Debug.h" - #include "llvm/Support/raw_ostream.h" - -commit 9fb823bbd484eebe4f8756338b14ed3725261997 -Author: Chandler Carruth -Date: Wed Jan 2 11:36:10 2013 +0000 - - Move all of the header files which are involved in modelling the LLVM IR - into their new header subdirectory: include/llvm/IR. This matches the - directory structure of lib, and begins to correct a long standing point - of file layout clutter in LLVM. - - There are still more header files to move here, but I wanted to handle - them in separate commits to make tracking what files make sense at each - layer easier. - - The only really questionable files here are the target intrinsic - tablegen files. But that's a battle I'd rather not fight today. - - I've updated both CMake and Makefile build systems (I think, and my - tests think, but I may have missed something). - - I've also re-sorted the includes throughout the project. I'll be - committing updates to Clang, DragonEgg, and Polly momentarily. - - llvm-svn: 171366 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index cde9c178ad8c..d4595bb373e6 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -20,7 +20,7 @@ - #include "llvm/Analysis/LoopInfo.h" - #include "llvm/Analysis/ValueTracking.h" - #include "llvm/Assembly/Writer.h" --#include "llvm/IntrinsicInst.h" -+#include "llvm/IR/IntrinsicInst.h" - #include "llvm/Support/CFG.h" - #include "llvm/Support/Debug.h" - #include "llvm/Support/raw_ostream.h" - -commit ed0881b2a67c530079dfd4141dbd9a899e6c1a7c -Author: Chandler Carruth -Date: Mon Dec 3 16:50:05 2012 +0000 - - Use the new script to sort the includes of every file under lib. - - Sooooo many of these had incorrect or strange main module includes. - I have manually inspected all of these, and fixed the main module - include to be the nearest plausible thing I could find. If you own or - care about any of these source files, I encourage you to take some time - and check that these edits were sensible. I can't have broken anything - (I strictly added headers, and reordered them, never removed), but they - may not be the headers you'd really like to identify as containing the - API being implemented. - - Many forward declarations and missing includes were added to a header - files to allow them to parse cleanly when included first. The main - module rule does in fact have its merits. =] - - llvm-svn: 169131 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 34f1d6c6221a..cde9c178ad8c 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -14,13 +14,13 @@ - - #define DEBUG_TYPE "sink" - #include "llvm/Transforms/Scalar.h" --#include "llvm/IntrinsicInst.h" -+#include "llvm/ADT/Statistic.h" -+#include "llvm/Analysis/AliasAnalysis.h" - #include "llvm/Analysis/Dominators.h" - #include "llvm/Analysis/LoopInfo.h" --#include "llvm/Analysis/AliasAnalysis.h" - #include "llvm/Analysis/ValueTracking.h" - #include "llvm/Assembly/Writer.h" --#include "llvm/ADT/Statistic.h" -+#include "llvm/IntrinsicInst.h" - #include "llvm/Support/CFG.h" - #include "llvm/Support/Debug.h" - #include "llvm/Support/raw_ostream.h" - -commit 465834c85f97666559d7acae8c028cb4ee3012f6 -Author: Nadav Rotem -Date: Tue Jul 24 10:51:42 2012 +0000 - - Clean whitespaces. - - llvm-svn: 160668 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index d6ec65169dee..34f1d6c6221a 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -40,9 +40,9 @@ namespace { - Sinking() : FunctionPass(ID) { - initializeSinkingPass(*PassRegistry::getPassRegistry()); - } -- -+ - virtual bool runOnFunction(Function &F); -- -+ - virtual void getAnalysisUsage(AnalysisUsage &AU) const { - AU.setPreservesCFG(); - FunctionPass::getAnalysisUsage(AU); -@@ -59,7 +59,7 @@ namespace { - bool IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo) const; - }; - } // end anonymous namespace -- -+ - char Sinking::ID = 0; - INITIALIZE_PASS_BEGIN(Sinking, "sink", "Code sinking", false, false) - INITIALIZE_PASS_DEPENDENCY(LoopInfo) -@@ -71,7 +71,7 @@ FunctionPass *llvm::createSinkingPass() { return new Sinking(); } - - /// AllUsesDominatedByBlock - Return true if all uses of the specified value - /// occur in blocks dominated by the specified block. --bool Sinking::AllUsesDominatedByBlock(Instruction *Inst, -+bool Sinking::AllUsesDominatedByBlock(Instruction *Inst, - BasicBlock *BB) const { - // Ignoring debug uses is necessary so debug info doesn't affect the code. - // This may leave a referencing dbg_value in the original block, before -@@ -101,18 +101,18 @@ bool Sinking::runOnFunction(Function &F) { - AA = &getAnalysis(); - - bool MadeChange, EverMadeChange = false; -- -+ - do { - MadeChange = false; - DEBUG(dbgs() << "Sinking iteration " << NumSinkIter << "\n"); - // Process all basic blocks. -- for (Function::iterator I = F.begin(), E = F.end(); -+ for (Function::iterator I = F.begin(), E = F.end(); - I != E; ++I) - MadeChange |= ProcessBlock(*I); - EverMadeChange |= MadeChange; - NumSinkIter++; - } while (MadeChange); -- -+ - return EverMadeChange; - } - -@@ -121,8 +121,8 @@ bool Sinking::ProcessBlock(BasicBlock &BB) { - if (BB.getTerminator()->getNumSuccessors() <= 1 || BB.empty()) return false; - - // Don't bother sinking code out of unreachable blocks. In addition to being -- // unprofitable, it can also lead to infinite looping, because in an unreachable -- // loop there may be nowhere to stop. -+ // unprofitable, it can also lead to infinite looping, because in an -+ // unreachable loop there may be nowhere to stop. - if (!DT->isReachableFromEntry(&BB)) return false; - - bool MadeChange = false; -@@ -134,7 +134,7 @@ bool Sinking::ProcessBlock(BasicBlock &BB) { - SmallPtrSet Stores; - do { - Instruction *Inst = I; // The instruction to sink. -- -+ - // Predecrement I (if it's not begin) so that it isn't invalidated by - // sinking. - ProcessedBegin = I == BB.begin(); -@@ -146,10 +146,10 @@ bool Sinking::ProcessBlock(BasicBlock &BB) { - - if (SinkInstruction(Inst, Stores)) - ++NumSunk, MadeChange = true; -- -+ - // If we just processed the first instruction in the block, we're done. - } while (!ProcessedBegin); -- -+ - return MadeChange; - } - -@@ -177,16 +177,17 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, - - /// IsAcceptableTarget - Return true if it is possible to sink the instruction - /// in the specified basic block. --bool Sinking::IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo) const { -+bool Sinking::IsAcceptableTarget(Instruction *Inst, -+ BasicBlock *SuccToSinkTo) const { - assert(Inst && "Instruction to be sunk is null"); - assert(SuccToSinkTo && "Candidate sink target is null"); -- -+ - // It is not possible to sink an instruction into its own block. This can - // happen with loops. - if (Inst->getParent() == SuccToSinkTo) - return false; -- -- // If the block has multiple predecessors, this would introduce computation -+ -+ // If the block has multiple predecessors, this would introduce computation - // on different code paths. We could split the critical edge, but for now we - // just punt. - // FIXME: Split critical edges if not backedges. -@@ -195,18 +196,19 @@ bool Sinking::IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo) co - // other code paths. - if (!isSafeToSpeculativelyExecute(Inst)) - return false; -- -+ - // We don't want to sink across a critical edge if we don't dominate the - // successor. We could be introducing calculations to new code paths. - if (!DT->dominates(Inst->getParent(), SuccToSinkTo)) - return false; -- -+ - // Don't sink instructions into a loop. -- Loop *succ = LI->getLoopFor(SuccToSinkTo), *cur = LI->getLoopFor(Inst->getParent()); -+ Loop *succ = LI->getLoopFor(SuccToSinkTo); -+ Loop *cur = LI->getLoopFor(Inst->getParent()); - if (succ != 0 && succ != cur) - return false; - } -- -+ - // Finally, check that all the uses of the instruction are actually - // dominated by the candidate - return AllUsesDominatedByBlock(Inst, SuccToSinkTo); -@@ -219,7 +221,7 @@ bool Sinking::SinkInstruction(Instruction *Inst, - // Check if it's safe to move the instruction. - if (!isSafeToMove(Inst, AA, Stores)) - return false; -- -+ - // FIXME: This should include support for sinking instructions within the - // block they are currently in to shorten the live ranges. We often get - // instructions sunk into the top of a large block, but it would be better to -@@ -227,41 +229,41 @@ bool Sinking::SinkInstruction(Instruction *Inst, - // be careful not to *increase* register pressure though, e.g. sinking - // "x = y + z" down if it kills y and z would increase the live ranges of y - // and z and only shrink the live range of x. -- -+ - // SuccToSinkTo - This is the successor to sink this instruction to, once we - // decide. - BasicBlock *SuccToSinkTo = 0; -- -+ - // Instructions can only be sunk if all their uses are in blocks - // dominated by one of the successors. - // Look at all the postdominators and see if we can sink it in one. - DomTreeNode *DTN = DT->getNode(Inst->getParent()); -- for (DomTreeNode::iterator I = DTN->begin(), E = DTN->end(); -+ for (DomTreeNode::iterator I = DTN->begin(), E = DTN->end(); - I != E && SuccToSinkTo == 0; ++I) { - BasicBlock *Candidate = (*I)->getBlock(); -- if ((*I)->getIDom()->getBlock() == Inst->getParent() && -+ if ((*I)->getIDom()->getBlock() == Inst->getParent() && - IsAcceptableTarget(Inst, Candidate)) - SuccToSinkTo = Candidate; - } - -- // If no suitable postdominator was found, look at all the successors and -+ // If no suitable postdominator was found, look at all the successors and - // decide which one we should sink to, if any. -- for (succ_iterator I = succ_begin(Inst->getParent()), -+ for (succ_iterator I = succ_begin(Inst->getParent()), - E = succ_end(Inst->getParent()); I != E && SuccToSinkTo == 0; ++I) { - if (IsAcceptableTarget(Inst, *I)) - SuccToSinkTo = *I; - } -- -+ - // If we couldn't find a block to sink to, ignore this instruction. - if (SuccToSinkTo == 0) - return false; -- -+ - DEBUG(dbgs() << "Sink" << *Inst << " ("; -- WriteAsOperand(dbgs(), Inst->getParent(), false); -+ WriteAsOperand(dbgs(), Inst->getParent(), false); - dbgs() << " -> "; -- WriteAsOperand(dbgs(), SuccToSinkTo, false); -+ WriteAsOperand(dbgs(), SuccToSinkTo, false); - dbgs() << ")\n"); -- -+ - // Move the instruction. - Inst->moveBefore(SuccToSinkTo->getFirstInsertionPt()); - return true; - -commit 339bb61e32593aa393ceda3c7168c24814a27161 -Author: Duncan Sands -Date: Thu May 31 08:09:49 2012 +0000 - - Enhance the sinking code to handle diamond patterns. Patch by - Carlo Alberto Ferraris. - - llvm-svn: 157736 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index ef65c0a3a907..d6ec65169dee 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -27,6 +27,7 @@ - using namespace llvm; - - STATISTIC(NumSunk, "Number of instructions sunk"); -+STATISTIC(NumSinkIter, "Number of sinking iterations"); - - namespace { - class Sinking : public FunctionPass { -@@ -55,6 +56,7 @@ namespace { - bool ProcessBlock(BasicBlock &BB); - bool SinkInstruction(Instruction *I, SmallPtrSet &Stores); - bool AllUsesDominatedByBlock(Instruction *Inst, BasicBlock *BB) const; -+ bool IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo) const; - }; - } // end anonymous namespace - -@@ -98,20 +100,19 @@ bool Sinking::runOnFunction(Function &F) { - LI = &getAnalysis(); - AA = &getAnalysis(); - -- bool EverMadeChange = false; -+ bool MadeChange, EverMadeChange = false; - -- while (1) { -- bool MadeChange = false; -- -+ do { -+ MadeChange = false; -+ DEBUG(dbgs() << "Sinking iteration " << NumSinkIter << "\n"); - // Process all basic blocks. - for (Function::iterator I = F.begin(), E = F.end(); - I != E; ++I) - MadeChange |= ProcessBlock(*I); -- -- // If this iteration over the code changed anything, keep iterating. -- if (!MadeChange) break; -- EverMadeChange = true; -- } -+ EverMadeChange |= MadeChange; -+ NumSinkIter++; -+ } while (MadeChange); -+ - return EverMadeChange; - } - -@@ -174,6 +175,43 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, - return true; - } - -+/// IsAcceptableTarget - Return true if it is possible to sink the instruction -+/// in the specified basic block. -+bool Sinking::IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo) const { -+ assert(Inst && "Instruction to be sunk is null"); -+ assert(SuccToSinkTo && "Candidate sink target is null"); -+ -+ // It is not possible to sink an instruction into its own block. This can -+ // happen with loops. -+ if (Inst->getParent() == SuccToSinkTo) -+ return false; -+ -+ // If the block has multiple predecessors, this would introduce computation -+ // on different code paths. We could split the critical edge, but for now we -+ // just punt. -+ // FIXME: Split critical edges if not backedges. -+ if (SuccToSinkTo->getUniquePredecessor() != Inst->getParent()) { -+ // We cannot sink a load across a critical edge - there may be stores in -+ // other code paths. -+ if (!isSafeToSpeculativelyExecute(Inst)) -+ return false; -+ -+ // We don't want to sink across a critical edge if we don't dominate the -+ // successor. We could be introducing calculations to new code paths. -+ if (!DT->dominates(Inst->getParent(), SuccToSinkTo)) -+ return false; -+ -+ // Don't sink instructions into a loop. -+ Loop *succ = LI->getLoopFor(SuccToSinkTo), *cur = LI->getLoopFor(Inst->getParent()); -+ if (succ != 0 && succ != cur) -+ return false; -+ } -+ -+ // Finally, check that all the uses of the instruction are actually -+ // dominated by the candidate -+ return AllUsesDominatedByBlock(Inst, SuccToSinkTo); -+} -+ - /// SinkInstruction - Determine whether it is safe to sink the specified machine - /// instruction out of its current block into a successor. - bool Sinking::SinkInstruction(Instruction *Inst, -@@ -190,85 +228,41 @@ bool Sinking::SinkInstruction(Instruction *Inst, - // "x = y + z" down if it kills y and z would increase the live ranges of y - // and z and only shrink the live range of x. - -- // Loop over all the operands of the specified instruction. If there is -- // anything we can't handle, bail out. -- BasicBlock *ParentBlock = Inst->getParent(); -- - // SuccToSinkTo - This is the successor to sink this instruction to, once we - // decide. - BasicBlock *SuccToSinkTo = 0; - -- // FIXME: This picks a successor to sink into based on having one -- // successor that dominates all the uses. However, there are cases where -- // sinking can happen but where the sink point isn't a successor. For -- // example: -- // x = computation -- // if () {} else {} -- // use x -- // the instruction could be sunk over the whole diamond for the -- // if/then/else (or loop, etc), allowing it to be sunk into other blocks -- // after that. -- - // Instructions can only be sunk if all their uses are in blocks - // dominated by one of the successors. -- // Look at all the successors and decide which one -- // we should sink to. -- for (succ_iterator SI = succ_begin(ParentBlock), -- E = succ_end(ParentBlock); SI != E; ++SI) { -- if (AllUsesDominatedByBlock(Inst, *SI)) { -- SuccToSinkTo = *SI; -- break; -- } -+ // Look at all the postdominators and see if we can sink it in one. -+ DomTreeNode *DTN = DT->getNode(Inst->getParent()); -+ for (DomTreeNode::iterator I = DTN->begin(), E = DTN->end(); -+ I != E && SuccToSinkTo == 0; ++I) { -+ BasicBlock *Candidate = (*I)->getBlock(); -+ if ((*I)->getIDom()->getBlock() == Inst->getParent() && -+ IsAcceptableTarget(Inst, Candidate)) -+ SuccToSinkTo = Candidate; -+ } -+ -+ // If no suitable postdominator was found, look at all the successors and -+ // decide which one we should sink to, if any. -+ for (succ_iterator I = succ_begin(Inst->getParent()), -+ E = succ_end(Inst->getParent()); I != E && SuccToSinkTo == 0; ++I) { -+ if (IsAcceptableTarget(Inst, *I)) -+ SuccToSinkTo = *I; - } - - // If we couldn't find a block to sink to, ignore this instruction. - if (SuccToSinkTo == 0) - return false; - -- // It is not possible to sink an instruction into its own block. This can -- // happen with loops. -- if (Inst->getParent() == SuccToSinkTo) -- return false; -- -- DEBUG(dbgs() << "Sink instr " << *Inst); -- DEBUG(dbgs() << "to block "; -- WriteAsOperand(dbgs(), SuccToSinkTo, false)); -- -- // If the block has multiple predecessors, this would introduce computation on -- // a path that it doesn't already exist. We could split the critical edge, -- // but for now we just punt. -- // FIXME: Split critical edges if not backedges. -- if (SuccToSinkTo->getUniquePredecessor() != ParentBlock) { -- // We cannot sink a load across a critical edge - there may be stores in -- // other code paths. -- if (!isSafeToSpeculativelyExecute(Inst)) { -- DEBUG(dbgs() << " *** PUNTING: Wont sink load along critical edge.\n"); -- return false; -- } -- -- // We don't want to sink across a critical edge if we don't dominate the -- // successor. We could be introducing calculations to new code paths. -- if (!DT->dominates(ParentBlock, SuccToSinkTo)) { -- DEBUG(dbgs() << " *** PUNTING: Critical edge found\n"); -- return false; -- } -- -- // Don't sink instructions into a loop. -- if (LI->isLoopHeader(SuccToSinkTo)) { -- DEBUG(dbgs() << " *** PUNTING: Loop header found\n"); -- return false; -- } -- -- // Otherwise we are OK with sinking along a critical edge. -- DEBUG(dbgs() << "Sinking along critical edge.\n"); -- } -- -- // Determine where to insert into. Skip phi nodes. -- BasicBlock::iterator InsertPos = SuccToSinkTo->begin(); -- while (InsertPos != SuccToSinkTo->end() && isa(InsertPos)) -- ++InsertPos; -+ DEBUG(dbgs() << "Sink" << *Inst << " ("; -+ WriteAsOperand(dbgs(), Inst->getParent(), false); -+ dbgs() << " -> "; -+ WriteAsOperand(dbgs(), SuccToSinkTo, false); -+ dbgs() << ")\n"); - - // Move the instruction. -- Inst->moveBefore(InsertPos); -+ Inst->moveBefore(SuccToSinkTo->getFirstInsertionPt()); - return true; - } - -commit 75d7d5e988539819d596f345d99c26a7aa3bd09b -Author: Dan Gohman -Date: Wed Dec 14 23:49:11 2011 +0000 - - Move Instruction::isSafeToSpeculativelyExecute out of VMCore and - into Analysis as a standalone function, since there's no need for - it to be in VMCore. Also, update it to use isKnownNonZero and - other goodies available in Analysis, making it more precise, - enabling more aggressive optimization. - - llvm-svn: 146610 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index c83f56c4d2d7..ef65c0a3a907 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -18,6 +18,7 @@ - #include "llvm/Analysis/Dominators.h" - #include "llvm/Analysis/LoopInfo.h" - #include "llvm/Analysis/AliasAnalysis.h" -+#include "llvm/Analysis/ValueTracking.h" - #include "llvm/Assembly/Writer.h" - #include "llvm/ADT/Statistic.h" - #include "llvm/Support/CFG.h" -@@ -240,7 +241,7 @@ bool Sinking::SinkInstruction(Instruction *Inst, - if (SuccToSinkTo->getUniquePredecessor() != ParentBlock) { - // We cannot sink a load across a critical edge - there may be stores in - // other code paths. -- if (!Inst->isSafeToSpeculativelyExecute()) { -+ if (!isSafeToSpeculativelyExecute(Inst)) { - DEBUG(dbgs() << " *** PUNTING: Wont sink load along critical edge.\n"); - return false; - } - -commit 71f5c2f1585e4bec0cc676e0476738af999dba70 -Author: Eli Friedman -Date: Thu Sep 1 21:21:24 2011 +0000 - - Fix an issue with the IR sink pass found by inspection. (I'm not sure anyone is actually using this, but might as well fix it since I found the issue.) - - llvm-svn: 138965 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 705f44204900..c83f56c4d2d7 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -153,9 +153,13 @@ bool Sinking::ProcessBlock(BasicBlock &BB) { - - static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, - SmallPtrSet &Stores) { -- if (LoadInst *L = dyn_cast(Inst)) { -- if (L->isVolatile()) return false; - -+ if (Inst->mayWriteToMemory()) { -+ Stores.insert(Inst); -+ return false; -+ } -+ -+ if (LoadInst *L = dyn_cast(Inst)) { - AliasAnalysis::Location Loc = AA->getLocation(L); - for (SmallPtrSet::iterator I = Stores.begin(), - E = Stores.end(); I != E; ++I) -@@ -163,11 +167,6 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, - return false; - } - -- if (Inst->mayWriteToMemory()) { -- Stores.insert(Inst); -- return false; -- } -- - if (isa(Inst) || isa(Inst)) - return false; - - -commit 65316d674914067bd0b6da080f8a7cf7c1aa0e78 -Author: Dan Gohman -Date: Thu Nov 11 21:50:19 2010 +0000 - - Add helper functions for computing the Location of load, store, - and vaarg instructions. - - llvm-svn: 118845 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index a54ba8e0ae54..705f44204900 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -15,7 +15,6 @@ - #define DEBUG_TYPE "sink" - #include "llvm/Transforms/Scalar.h" - #include "llvm/IntrinsicInst.h" --#include "llvm/LLVMContext.h" - #include "llvm/Analysis/Dominators.h" - #include "llvm/Analysis/LoopInfo.h" - #include "llvm/Analysis/AliasAnalysis.h" -@@ -157,10 +156,7 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, - if (LoadInst *L = dyn_cast(Inst)) { - if (L->isVolatile()) return false; - -- Value *Ptr = L->getPointerOperand(); -- uint64_t Size = AA->getTypeStoreSize(L->getType()); -- const MDNode *TBAAInfo = L->getMetadata(LLVMContext::MD_tbaa); -- AliasAnalysis::Location Loc(Ptr, Size, TBAAInfo); -+ AliasAnalysis::Location Loc = AA->getLocation(L); - for (SmallPtrSet::iterator I = Stores.begin(), - E = Stores.end(); I != E; ++I) - if (AA->getModRefInfo(*I, Loc) & AliasAnalysis::Mod) - -commit 0cc4c7516e2e5b1feaa9850de03615b6329ef919 -Author: Dan Gohman -Date: Thu Nov 11 16:21:47 2010 +0000 - - Make Sink tbaa-aware. - - llvm-svn: 118788 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index d6f1e93a812d..a54ba8e0ae54 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -15,6 +15,7 @@ - #define DEBUG_TYPE "sink" - #include "llvm/Transforms/Scalar.h" - #include "llvm/IntrinsicInst.h" -+#include "llvm/LLVMContext.h" - #include "llvm/Analysis/Dominators.h" - #include "llvm/Analysis/LoopInfo.h" - #include "llvm/Analysis/AliasAnalysis.h" -@@ -158,9 +159,11 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, - - Value *Ptr = L->getPointerOperand(); - uint64_t Size = AA->getTypeStoreSize(L->getType()); -+ const MDNode *TBAAInfo = L->getMetadata(LLVMContext::MD_tbaa); -+ AliasAnalysis::Location Loc(Ptr, Size, TBAAInfo); - for (SmallPtrSet::iterator I = Stores.begin(), - E = Stores.end(); I != E; ++I) -- if (AA->getModRefInfo(*I, Ptr, Size) & AliasAnalysis::Mod) -+ if (AA->getModRefInfo(*I, Loc) & AliasAnalysis::Mod) - return false; - } - - -commit c3b4ea7b7d7e1c6f2e29ef3c85f798d94741111a -Author: Dan Gohman -Date: Thu Nov 11 16:20:28 2010 +0000 - - It's safe to sink some instructions which are not safe to speculatively - execute. Make Sink's predicate more precise. - - llvm-svn: 118787 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 1aca908267b4..d6f1e93a812d 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -169,7 +169,10 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, - return false; - } - -- return Inst->isSafeToSpeculativelyExecute(); -+ if (isa(Inst) || isa(Inst)) -+ return false; -+ -+ return true; - } - - /// SinkInstruction - Determine whether it is safe to sink the specified machine - -commit f372cf869b7795d72843fb3a097af9d03b5c2b42 -Author: Dan Gohman -Date: Tue Oct 19 22:54:46 2010 +0000 - - Reapply r116831 and r116839, converting AliasAnalysis to use - uint64_t, plus fixes for places I missed before. - - llvm-svn: 116875 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 7306ee5e2e45..1aca908267b4 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -157,7 +157,7 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, - if (L->isVolatile()) return false; - - Value *Ptr = L->getPointerOperand(); -- unsigned Size = AA->getTypeStoreSize(L->getType()); -+ uint64_t Size = AA->getTypeStoreSize(L->getType()); - for (SmallPtrSet::iterator I = Stores.begin(), - E = Stores.end(); I != E; ++I) - if (AA->getModRefInfo(*I, Ptr, Size) & AliasAnalysis::Mod) - -commit 6c18d1aac08df0143d9a9810261421faeac81d4a -Author: Owen Anderson -Date: Tue Oct 19 17:21:58 2010 +0000 - - Get rid of static constructors for pass registration. Instead, every pass exposes an initializeMyPassFunction(), which - must be called in the pass's constructor. This function uses static dependency declarations to recursively initialize - the pass's dependencies. - - Clients that only create passes through the createFooPass() APIs will require no changes. Clients that want to use the - CommandLine options for passes will need to manually call the appropriate initialization functions in PassInitialization.h - before parsing commandline arguments. - - I have tested this with all standard configurations of clang and llvm-gcc on Darwin. It is possible that there are problems - with the static dependencies that will only be visible with non-standard options. If you encounter any crash in pass - registration/creation, please send the testcase to me directly. - - llvm-svn: 116820 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 0071428354e6..7306ee5e2e45 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -35,7 +35,9 @@ namespace { - - public: - static char ID; // Pass identification -- Sinking() : FunctionPass(ID) {} -+ Sinking() : FunctionPass(ID) { -+ initializeSinkingPass(*PassRegistry::getPassRegistry()); -+ } - - virtual bool runOnFunction(Function &F); - - -commit 8ac477ffb509943c940ce37f45b8429388dfdf58 -Author: Owen Anderson -Date: Tue Oct 12 19:48:12 2010 +0000 - - Begin adding static dependence information to passes, which will allow us to - perform initialization without static constructors AND without explicit initialization - by the client. For the moment, passes are required to initialize both their - (potential) dependencies and any passes they preserve. I hope to be able to relax - the latter requirement in the future. - - llvm-svn: 116334 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 6dc52a6f8e71..0071428354e6 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -56,7 +56,11 @@ namespace { - } // end anonymous namespace - - char Sinking::ID = 0; --INITIALIZE_PASS(Sinking, "sink", "Code sinking", false, false) -+INITIALIZE_PASS_BEGIN(Sinking, "sink", "Code sinking", false, false) -+INITIALIZE_PASS_DEPENDENCY(LoopInfo) -+INITIALIZE_PASS_DEPENDENCY(DominatorTree) -+INITIALIZE_AG_DEPENDENCY(AliasAnalysis) -+INITIALIZE_PASS_END(Sinking, "sink", "Code sinking", false, false) - - FunctionPass *llvm::createSinkingPass() { return new Sinking(); } - - -commit df7a4f2515ce59b487c24e8bb8ea98c10b3edabf -Author: Owen Anderson -Date: Thu Oct 7 22:25:06 2010 +0000 - - Now with fewer extraneous semicolons! - - llvm-svn: 115996 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 95d3dedfb62d..6dc52a6f8e71 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -56,7 +56,7 @@ namespace { - } // end anonymous namespace - - char Sinking::ID = 0; --INITIALIZE_PASS(Sinking, "sink", "Code sinking", false, false); -+INITIALIZE_PASS(Sinking, "sink", "Code sinking", false, false) - - FunctionPass *llvm::createSinkingPass() { return new Sinking(); } - - -commit a7aed18624f7783b7c31b06069c43bec89f1813f -Author: Owen Anderson -Date: Fri Aug 6 18:33:48 2010 +0000 - - Reapply r110396, with fixes to appease the Linux buildbot gods. - - llvm-svn: 110460 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 2448312673ba..95d3dedfb62d 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -35,7 +35,7 @@ namespace { - - public: - static char ID; // Pass identification -- Sinking() : FunctionPass(&ID) {} -+ Sinking() : FunctionPass(ID) {} - - virtual bool runOnFunction(Function &F); - - -commit bda59bd247b1153e4bc19f85dee4cb594b9c2b32 -Author: Owen Anderson -Date: Fri Aug 6 00:23:35 2010 +0000 - - Revert r110396 to fix buildbots. - - llvm-svn: 110410 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 95d3dedfb62d..2448312673ba 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -35,7 +35,7 @@ namespace { - - public: - static char ID; // Pass identification -- Sinking() : FunctionPass(ID) {} -+ Sinking() : FunctionPass(&ID) {} - - virtual bool runOnFunction(Function &F); - - -commit 755aceb5d0df842b5132052d474c361b5605aedb -Author: Owen Anderson -Date: Thu Aug 5 23:42:04 2010 +0000 - - Don't use PassInfo* as a type identifier for passes. Instead, use the address of the static - ID member as the sole unique type identifier. Clean up APIs related to this change. - - llvm-svn: 110396 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index 2448312673ba..95d3dedfb62d 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -35,7 +35,7 @@ namespace { - - public: - static char ID; // Pass identification -- Sinking() : FunctionPass(&ID) {} -+ Sinking() : FunctionPass(ID) {} - - virtual bool runOnFunction(Function &F); - - -commit a57b97e7e7d4bd44ebc90c743e6db318fa5348d6 -Author: Owen Anderson -Date: Wed Jul 21 22:09:45 2010 +0000 - - Fix batch of converting RegisterPass<> to INTIALIZE_PASS(). - - llvm-svn: 109045 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -index b88ba4850509..2448312673ba 100644 ---- a/llvm/lib/Transforms/Scalar/Sink.cpp -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -56,8 +56,7 @@ namespace { - } // end anonymous namespace - - char Sinking::ID = 0; --static RegisterPass --X("sink", "Code sinking"); -+INITIALIZE_PASS(Sinking, "sink", "Code sinking", false, false); - - FunctionPass *llvm::createSinkingPass() { return new Sinking(); } - - -commit 5d5b8b1b8c8719d0ac362b8bc12957fc79de4595 -Author: Dan Gohman -Date: Fri May 7 15:40:13 2010 +0000 - - Add an LLVM IR version of code sinking. This uses the same simple algorithm - as MachineSink, but it isn't constrained by MachineInstr-level details. - - llvm-svn: 103257 - -diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp -new file mode 100644 -index 000000000000..b88ba4850509 ---- /dev/null -+++ b/llvm/lib/Transforms/Scalar/Sink.cpp -@@ -0,0 +1,267 @@ -+//===-- Sink.cpp - Code Sinking -------------------------------------------===// -+// -+// The LLVM Compiler Infrastructure -+// -+// This file is distributed under the University of Illinois Open Source -+// License. See LICENSE.TXT for details. -+// -+//===----------------------------------------------------------------------===// -+// -+// This pass moves instructions into successor blocks, when possible, so that -+// they aren't executed on paths where their results aren't needed. -+// -+//===----------------------------------------------------------------------===// -+ -+#define DEBUG_TYPE "sink" -+#include "llvm/Transforms/Scalar.h" -+#include "llvm/IntrinsicInst.h" -+#include "llvm/Analysis/Dominators.h" -+#include "llvm/Analysis/LoopInfo.h" -+#include "llvm/Analysis/AliasAnalysis.h" -+#include "llvm/Assembly/Writer.h" -+#include "llvm/ADT/Statistic.h" -+#include "llvm/Support/CFG.h" -+#include "llvm/Support/Debug.h" -+#include "llvm/Support/raw_ostream.h" -+using namespace llvm; -+ -+STATISTIC(NumSunk, "Number of instructions sunk"); -+ -+namespace { -+ class Sinking : public FunctionPass { -+ DominatorTree *DT; -+ LoopInfo *LI; -+ AliasAnalysis *AA; -+ -+ public: -+ static char ID; // Pass identification -+ Sinking() : FunctionPass(&ID) {} -+ -+ virtual bool runOnFunction(Function &F); -+ -+ virtual void getAnalysisUsage(AnalysisUsage &AU) const { -+ AU.setPreservesCFG(); -+ FunctionPass::getAnalysisUsage(AU); -+ AU.addRequired(); -+ AU.addRequired(); -+ AU.addRequired(); -+ AU.addPreserved(); -+ AU.addPreserved(); -+ } -+ private: -+ bool ProcessBlock(BasicBlock &BB); -+ bool SinkInstruction(Instruction *I, SmallPtrSet &Stores); -+ bool AllUsesDominatedByBlock(Instruction *Inst, BasicBlock *BB) const; -+ }; -+} // end anonymous namespace -+ -+char Sinking::ID = 0; -+static RegisterPass -+X("sink", "Code sinking"); -+ -+FunctionPass *llvm::createSinkingPass() { return new Sinking(); } -+ -+/// AllUsesDominatedByBlock - Return true if all uses of the specified value -+/// occur in blocks dominated by the specified block. -+bool Sinking::AllUsesDominatedByBlock(Instruction *Inst, -+ BasicBlock *BB) const { -+ // Ignoring debug uses is necessary so debug info doesn't affect the code. -+ // This may leave a referencing dbg_value in the original block, before -+ // the definition of the vreg. Dwarf generator handles this although the -+ // user might not get the right info at runtime. -+ for (Value::use_iterator I = Inst->use_begin(), -+ E = Inst->use_end(); I != E; ++I) { -+ // Determine the block of the use. -+ Instruction *UseInst = cast(*I); -+ BasicBlock *UseBlock = UseInst->getParent(); -+ if (PHINode *PN = dyn_cast(UseInst)) { -+ // PHI nodes use the operand in the predecessor block, not the block with -+ // the PHI. -+ unsigned Num = PHINode::getIncomingValueNumForOperand(I.getOperandNo()); -+ UseBlock = PN->getIncomingBlock(Num); -+ } -+ // Check that it dominates. -+ if (!DT->dominates(BB, UseBlock)) -+ return false; -+ } -+ return true; -+} -+ -+bool Sinking::runOnFunction(Function &F) { -+ DT = &getAnalysis(); -+ LI = &getAnalysis(); -+ AA = &getAnalysis(); -+ -+ bool EverMadeChange = false; -+ -+ while (1) { -+ bool MadeChange = false; -+ -+ // Process all basic blocks. -+ for (Function::iterator I = F.begin(), E = F.end(); -+ I != E; ++I) -+ MadeChange |= ProcessBlock(*I); -+ -+ // If this iteration over the code changed anything, keep iterating. -+ if (!MadeChange) break; -+ EverMadeChange = true; -+ } -+ return EverMadeChange; -+} -+ -+bool Sinking::ProcessBlock(BasicBlock &BB) { -+ // Can't sink anything out of a block that has less than two successors. -+ if (BB.getTerminator()->getNumSuccessors() <= 1 || BB.empty()) return false; -+ -+ // Don't bother sinking code out of unreachable blocks. In addition to being -+ // unprofitable, it can also lead to infinite looping, because in an unreachable -+ // loop there may be nowhere to stop. -+ if (!DT->isReachableFromEntry(&BB)) return false; -+ -+ bool MadeChange = false; -+ -+ // Walk the basic block bottom-up. Remember if we saw a store. -+ BasicBlock::iterator I = BB.end(); -+ --I; -+ bool ProcessedBegin = false; -+ SmallPtrSet Stores; -+ do { -+ Instruction *Inst = I; // The instruction to sink. -+ -+ // Predecrement I (if it's not begin) so that it isn't invalidated by -+ // sinking. -+ ProcessedBegin = I == BB.begin(); -+ if (!ProcessedBegin) -+ --I; -+ -+ if (isa(Inst)) -+ continue; -+ -+ if (SinkInstruction(Inst, Stores)) -+ ++NumSunk, MadeChange = true; -+ -+ // If we just processed the first instruction in the block, we're done. -+ } while (!ProcessedBegin); -+ -+ return MadeChange; -+} -+ -+static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, -+ SmallPtrSet &Stores) { -+ if (LoadInst *L = dyn_cast(Inst)) { -+ if (L->isVolatile()) return false; -+ -+ Value *Ptr = L->getPointerOperand(); -+ unsigned Size = AA->getTypeStoreSize(L->getType()); -+ for (SmallPtrSet::iterator I = Stores.begin(), -+ E = Stores.end(); I != E; ++I) -+ if (AA->getModRefInfo(*I, Ptr, Size) & AliasAnalysis::Mod) -+ return false; -+ } -+ -+ if (Inst->mayWriteToMemory()) { -+ Stores.insert(Inst); -+ return false; -+ } -+ -+ return Inst->isSafeToSpeculativelyExecute(); -+} -+ -+/// SinkInstruction - Determine whether it is safe to sink the specified machine -+/// instruction out of its current block into a successor. -+bool Sinking::SinkInstruction(Instruction *Inst, -+ SmallPtrSet &Stores) { -+ // Check if it's safe to move the instruction. -+ if (!isSafeToMove(Inst, AA, Stores)) -+ return false; -+ -+ // FIXME: This should include support for sinking instructions within the -+ // block they are currently in to shorten the live ranges. We often get -+ // instructions sunk into the top of a large block, but it would be better to -+ // also sink them down before their first use in the block. This xform has to -+ // be careful not to *increase* register pressure though, e.g. sinking -+ // "x = y + z" down if it kills y and z would increase the live ranges of y -+ // and z and only shrink the live range of x. -+ -+ // Loop over all the operands of the specified instruction. If there is -+ // anything we can't handle, bail out. -+ BasicBlock *ParentBlock = Inst->getParent(); -+ -+ // SuccToSinkTo - This is the successor to sink this instruction to, once we -+ // decide. -+ BasicBlock *SuccToSinkTo = 0; -+ -+ // FIXME: This picks a successor to sink into based on having one -+ // successor that dominates all the uses. However, there are cases where -+ // sinking can happen but where the sink point isn't a successor. For -+ // example: -+ // x = computation -+ // if () {} else {} -+ // use x -+ // the instruction could be sunk over the whole diamond for the -+ // if/then/else (or loop, etc), allowing it to be sunk into other blocks -+ // after that. -+ -+ // Instructions can only be sunk if all their uses are in blocks -+ // dominated by one of the successors. -+ // Look at all the successors and decide which one -+ // we should sink to. -+ for (succ_iterator SI = succ_begin(ParentBlock), -+ E = succ_end(ParentBlock); SI != E; ++SI) { -+ if (AllUsesDominatedByBlock(Inst, *SI)) { -+ SuccToSinkTo = *SI; -+ break; -+ } -+ } -+ -+ // If we couldn't find a block to sink to, ignore this instruction. -+ if (SuccToSinkTo == 0) -+ return false; -+ -+ // It is not possible to sink an instruction into its own block. This can -+ // happen with loops. -+ if (Inst->getParent() == SuccToSinkTo) -+ return false; -+ -+ DEBUG(dbgs() << "Sink instr " << *Inst); -+ DEBUG(dbgs() << "to block "; -+ WriteAsOperand(dbgs(), SuccToSinkTo, false)); -+ -+ // If the block has multiple predecessors, this would introduce computation on -+ // a path that it doesn't already exist. We could split the critical edge, -+ // but for now we just punt. -+ // FIXME: Split critical edges if not backedges. -+ if (SuccToSinkTo->getUniquePredecessor() != ParentBlock) { -+ // We cannot sink a load across a critical edge - there may be stores in -+ // other code paths. -+ if (!Inst->isSafeToSpeculativelyExecute()) { -+ DEBUG(dbgs() << " *** PUNTING: Wont sink load along critical edge.\n"); -+ return false; -+ } -+ -+ // We don't want to sink across a critical edge if we don't dominate the -+ // successor. We could be introducing calculations to new code paths. -+ if (!DT->dominates(ParentBlock, SuccToSinkTo)) { -+ DEBUG(dbgs() << " *** PUNTING: Critical edge found\n"); -+ return false; -+ } -+ -+ // Don't sink instructions into a loop. -+ if (LI->isLoopHeader(SuccToSinkTo)) { -+ DEBUG(dbgs() << " *** PUNTING: Loop header found\n"); -+ return false; -+ } -+ -+ // Otherwise we are OK with sinking along a critical edge. -+ DEBUG(dbgs() << "Sinking along critical edge.\n"); -+ } -+ -+ // Determine where to insert into. Skip phi nodes. -+ BasicBlock::iterator InsertPos = SuccToSinkTo->begin(); -+ while (InsertPos != SuccToSinkTo->end() && isa(InsertPos)) -+ ++InsertPos; -+ -+ // Move the instruction. -+ Inst->moveBefore(InsertPos); -+ return true; -+} From 97cd81bfddf30de7ba0366b9f82f14beb77a9b7d Mon Sep 17 00:00:00 2001 From: John Lu Date: Thu, 17 Apr 2025 20:20:12 -0500 Subject: [PATCH 08/14] Use BatchAA Signed-off-by: John Lu --- llvm/lib/Transforms/Scalar/Sink.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp index a5404956f1c94..18076ddacf3fd 100644 --- a/llvm/lib/Transforms/Scalar/Sink.cpp +++ b/llvm/lib/Transforms/Scalar/Sink.cpp @@ -29,14 +29,16 @@ STATISTIC(NumSinkIter, "Number of sinking iterations"); static bool hasStoreConflict(Instruction *Inst, AliasAnalysis &AA, SmallPtrSetImpl &Stores) { + BatchAAResults BatchAA(AA); + if (LoadInst *L = dyn_cast(Inst)) { MemoryLocation Loc = MemoryLocation::get(L); for (Instruction *S : Stores) - if (isModSet(AA.getModRefInfo(S, Loc))) + if (isModSet(BatchAA.getModRefInfo(S, Loc))) return true; } else if (auto *Call = dyn_cast(Inst)) { for (Instruction *S : Stores) - if (isModSet(AA.getModRefInfo(S, Call))) + if (isModSet(BatchAA.getModRefInfo(S, Call))) return true; } return false; From 1539a5cdc30e7d7aa02ccdc317e1fe2e009d9abc Mon Sep 17 00:00:00 2001 From: John Lu Date: Fri, 18 Apr 2025 13:03:38 -0500 Subject: [PATCH 09/14] If finding stores is too complicated assume there is a conflict Signed-off-by: John Lu --- llvm/lib/Transforms/Scalar/Sink.cpp | 31 ++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp index 18076ddacf3fd..3d016cb0d8798 100644 --- a/llvm/lib/Transforms/Scalar/Sink.cpp +++ b/llvm/lib/Transforms/Scalar/Sink.cpp @@ -17,6 +17,7 @@ #include "llvm/Analysis/LoopInfo.h" #include "llvm/IR/Dominators.h" #include "llvm/InitializePasses.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Scalar.h" @@ -77,18 +78,36 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis &AA, return true; } +static cl::opt + SinkLoadBlockLimit("sink-load-block-limit", cl::Hidden, cl::init(15), + cl::desc("Maximum number of descendant blocks that will " + "be analyzed when attempting to sink a load.")); + +static cl::opt SinkLoadStoreLimit( + "sink-load-store-limit", cl::Hidden, cl::init(3), + cl::desc("Maximum number of stores in descendant blocks that will be " + "analyzed when attempting to sink a load.")); + using BlocksSet = SmallPtrSet; -static void findStores(SmallPtrSetImpl &Stores, +// Return false if finding stores is too complex. True otherwise. +static bool findStores(SmallPtrSetImpl &Stores, BasicBlock *LoadBB, BasicBlock *BB, BlocksSet &VisitedBlocksSet) { if (BB == LoadBB || !VisitedBlocksSet.insert(BB).second) - return; + return true; + if (VisitedBlocksSet.size() > SinkLoadBlockLimit) + return false; for (Instruction &Inst : *BB) - if (Inst.mayWriteToMemory()) + if (Inst.mayWriteToMemory()) { Stores.insert(&Inst); + if (Stores.size() > SinkLoadStoreLimit) + return false; + } for (BasicBlock *Pred : predecessors(BB)) - findStores(Stores, LoadBB, Pred, VisitedBlocksSet); + if (!findStores(Stores, LoadBB, Pred, VisitedBlocksSet)) + return false; + return true; } static bool hasConflictingStoreBeforeSuccToSinkTo(AliasAnalysis &AA, @@ -98,7 +117,9 @@ static bool hasConflictingStoreBeforeSuccToSinkTo(AliasAnalysis &AA, SmallPtrSet Stores; BasicBlock *LoadBB = ReadMemInst->getParent(); for (BasicBlock *Pred : predecessors(SuccToSinkTo)) - findStores(Stores, LoadBB, Pred, VisitedBlocksSet); + // If finding stores is too complex, assume there is a conflict. + if (!findStores(Stores, LoadBB, Pred, VisitedBlocksSet)) + return true; return hasStoreConflict(ReadMemInst, AA, Stores); } From e6cec74eaf3d11f59e8ebdda29a4324e96cee3b4 Mon Sep 17 00:00:00 2001 From: John Lu Date: Thu, 24 Apr 2025 12:07:54 -0500 Subject: [PATCH 10/14] Use MemorySSA to find stores Signed-off-by: John Lu --- llvm/lib/Transforms/Scalar/Sink.cpp | 119 ++++++++++++++-------------- 1 file changed, 60 insertions(+), 59 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp index 3d016cb0d8798..3a77b044fcf78 100644 --- a/llvm/lib/Transforms/Scalar/Sink.cpp +++ b/llvm/lib/Transforms/Scalar/Sink.cpp @@ -15,6 +15,8 @@ #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/MemorySSA.h" +#include "llvm/Analysis/MemorySSAUpdater.h" #include "llvm/IR/Dominators.h" #include "llvm/InitializePasses.h" #include "llvm/Support/CommandLine.h" @@ -28,23 +30,6 @@ using namespace llvm; STATISTIC(NumSunk, "Number of instructions sunk"); STATISTIC(NumSinkIter, "Number of sinking iterations"); -static bool hasStoreConflict(Instruction *Inst, AliasAnalysis &AA, - SmallPtrSetImpl &Stores) { - BatchAAResults BatchAA(AA); - - if (LoadInst *L = dyn_cast(Inst)) { - MemoryLocation Loc = MemoryLocation::get(L); - for (Instruction *S : Stores) - if (isModSet(BatchAA.getModRefInfo(S, Loc))) - return true; - } else if (auto *Call = dyn_cast(Inst)) { - for (Instruction *S : Stores) - if (isModSet(BatchAA.getModRefInfo(S, Call))) - return true; - } - return false; -} - static bool isSafeToMove(Instruction *Inst, AliasAnalysis &AA, SmallPtrSetImpl &Stores) { @@ -78,56 +63,62 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis &AA, return true; } -static cl::opt - SinkLoadBlockLimit("sink-load-block-limit", cl::Hidden, cl::init(15), - cl::desc("Maximum number of descendant blocks that will " - "be analyzed when attempting to sink a load.")); - static cl::opt SinkLoadStoreLimit( - "sink-load-store-limit", cl::Hidden, cl::init(3), + "sink-load-store-limit", cl::Hidden, cl::init(4), cl::desc("Maximum number of stores in descendant blocks that will be " "analyzed when attempting to sink a load.")); using BlocksSet = SmallPtrSet; -// Return false if finding stores is too complex. True otherwise. -static bool findStores(SmallPtrSetImpl &Stores, - BasicBlock *LoadBB, BasicBlock *BB, - BlocksSet &VisitedBlocksSet) { +static bool hasStoreConflict(BasicBlock *LoadBB, BasicBlock *BB, + BlocksSet &VisitedBlocksSet, + MemorySSAUpdater &MSSAU, BatchAAResults &BAA, + Instruction *ReadMemInst, unsigned &StoreCnt) { if (BB == LoadBB || !VisitedBlocksSet.insert(BB).second) - return true; - - if (VisitedBlocksSet.size() > SinkLoadBlockLimit) return false; - for (Instruction &Inst : *BB) - if (Inst.mayWriteToMemory()) { - Stores.insert(&Inst); - if (Stores.size() > SinkLoadStoreLimit) - return false; - } + if (auto *Accesses = MSSAU.getMemorySSA()->getBlockDefs(BB)) { + StoreCnt += Accesses->size(); + if (StoreCnt > SinkLoadStoreLimit) + return true; + for (auto &MA : *Accesses) + if (auto *MD = dyn_cast(&MA)) { + Instruction *S = MD->getMemoryInst(); + if (LoadInst *L = dyn_cast(ReadMemInst)) { + MemoryLocation Loc = MemoryLocation::get(L); + if (isModSet(BAA.getModRefInfo(S, Loc))) + return true; + } else if (auto *Call = dyn_cast(ReadMemInst)) { + if (isModSet(BAA.getModRefInfo(S, Call))) + return true; + } + } + } for (BasicBlock *Pred : predecessors(BB)) - if (!findStores(Stores, LoadBB, Pred, VisitedBlocksSet)) - return false; - return true; + if (hasStoreConflict(LoadBB, Pred, VisitedBlocksSet, MSSAU, BAA, + ReadMemInst, StoreCnt)) + return true; + return false; } -static bool hasConflictingStoreBeforeSuccToSinkTo(AliasAnalysis &AA, - Instruction *ReadMemInst, - BasicBlock *SuccToSinkTo) { +static bool hasConflictingStoreBeforeSuccToSinkTo(Instruction *ReadMemInst, + BasicBlock *SuccToSinkTo, + MemorySSAUpdater &MSSAU, + BatchAAResults &BAA) { BlocksSet VisitedBlocksSet; - SmallPtrSet Stores; BasicBlock *LoadBB = ReadMemInst->getParent(); + unsigned StoreCnt{0}; + for (BasicBlock *Pred : predecessors(SuccToSinkTo)) - // If finding stores is too complex, assume there is a conflict. - if (!findStores(Stores, LoadBB, Pred, VisitedBlocksSet)) + if (hasStoreConflict(LoadBB, Pred, VisitedBlocksSet, MSSAU, BAA, + ReadMemInst, StoreCnt)) return true; - return hasStoreConflict(ReadMemInst, AA, Stores); + return false; } /// IsAcceptableTarget - Return true if it is possible to sink the instruction /// in the specified basic block. -static bool IsAcceptableTarget(AliasAnalysis &AA, Instruction *Inst, - BasicBlock *SuccToSinkTo, DominatorTree &DT, - LoopInfo &LI) { +static bool IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo, + DominatorTree &DT, LoopInfo &LI, + MemorySSAUpdater &MSSAU, BatchAAResults &BAA) { assert(Inst && "Instruction to be sunk is null"); assert(SuccToSinkTo && "Candidate sink target is null"); @@ -143,7 +134,7 @@ static bool IsAcceptableTarget(AliasAnalysis &AA, Instruction *Inst, // Ensure that there is no conflicting store on any path to SuccToSinkTo. if (Inst->mayReadFromMemory() && !Inst->hasMetadata(LLVMContext::MD_invariant_load) && - hasConflictingStoreBeforeSuccToSinkTo(AA, Inst, SuccToSinkTo)) + hasConflictingStoreBeforeSuccToSinkTo(Inst, SuccToSinkTo, MSSAU, BAA)) return false; // We don't want to sink across a critical edge if we don't dominate the @@ -165,7 +156,8 @@ static bool IsAcceptableTarget(AliasAnalysis &AA, Instruction *Inst, /// instruction out of its current block into a successor. static bool SinkInstruction(Instruction *Inst, SmallPtrSetImpl &Stores, - DominatorTree &DT, LoopInfo &LI, AAResults &AA) { + DominatorTree &DT, LoopInfo &LI, AAResults &AA, + MemorySSAUpdater &MSSAU) { // Don't sink static alloca instructions. CodeGen assumes allocas outside the // entry block are dynamically sized stack objects. @@ -216,8 +208,9 @@ static bool SinkInstruction(Instruction *Inst, if (SuccToSinkTo) { // The nearest common dominator may be in a parent loop of BB, which may not // be beneficial. Find an ancestor. + BatchAAResults BAA(AA); while (SuccToSinkTo != BB && - !IsAcceptableTarget(AA, Inst, SuccToSinkTo, DT, LI)) + !IsAcceptableTarget(Inst, SuccToSinkTo, DT, LI, MSSAU, BAA)) SuccToSinkTo = DT.getNode(SuccToSinkTo)->getIDom()->getBlock(); if (SuccToSinkTo == BB) SuccToSinkTo = nullptr; @@ -233,11 +226,15 @@ static bool SinkInstruction(Instruction *Inst, // Move the instruction. Inst->moveBefore(SuccToSinkTo->getFirstInsertionPt()); + if (MemoryUseOrDef *OldMemAcc = cast_or_null( + MSSAU.getMemorySSA()->getMemoryAccess(Inst))) + MSSAU.moveToPlace(OldMemAcc, SuccToSinkTo, MemorySSA::Beginning); + return true; } static bool ProcessBlock(BasicBlock &BB, DominatorTree &DT, LoopInfo &LI, - AAResults &AA) { + AAResults &AA, MemorySSAUpdater &MSSAU) { // Don't bother sinking code out of unreachable blocks. In addition to being // unprofitable, it can also lead to infinite looping, because in an // unreachable loop there may be nowhere to stop. @@ -262,7 +259,7 @@ static bool ProcessBlock(BasicBlock &BB, DominatorTree &DT, LoopInfo &LI, if (Inst->isDebugOrPseudoInst()) continue; - if (SinkInstruction(Inst, Stores, DT, LI, AA)) { + if (SinkInstruction(Inst, Stores, DT, LI, AA, MSSAU)) { ++NumSunk; MadeChange = true; } @@ -274,7 +271,8 @@ static bool ProcessBlock(BasicBlock &BB, DominatorTree &DT, LoopInfo &LI, } static bool iterativelySinkInstructions(Function &F, DominatorTree &DT, - LoopInfo &LI, AAResults &AA) { + LoopInfo &LI, AAResults &AA, + MemorySSAUpdater &MSSAU) { bool MadeChange, EverMadeChange = false; do { @@ -282,7 +280,7 @@ static bool iterativelySinkInstructions(Function &F, DominatorTree &DT, LLVM_DEBUG(dbgs() << "Sinking iteration " << NumSinkIter << "\n"); // Process all basic blocks. for (BasicBlock &I : F) - MadeChange |= ProcessBlock(I, DT, LI, AA); + MadeChange |= ProcessBlock(I, DT, LI, AA, MSSAU); EverMadeChange |= MadeChange; NumSinkIter++; } while (MadeChange); @@ -294,8 +292,10 @@ PreservedAnalyses SinkingPass::run(Function &F, FunctionAnalysisManager &AM) { auto &DT = AM.getResult(F); auto &LI = AM.getResult(F); auto &AA = AM.getResult(F); + MemorySSA &MSSA = AM.getResult(F).getMSSA(); + MemorySSAUpdater MSSAU(&MSSA); - if (!iterativelySinkInstructions(F, DT, LI, AA)) + if (!iterativelySinkInstructions(F, DT, LI, AA, MSSAU)) return PreservedAnalyses::all(); PreservedAnalyses PA; @@ -315,8 +315,9 @@ namespace { auto &DT = getAnalysis().getDomTree(); auto &LI = getAnalysis().getLoopInfo(); auto &AA = getAnalysis().getAAResults(); - - return iterativelySinkInstructions(F, DT, LI, AA); + MemorySSA *MSSA = &getAnalysis().getMSSA(); + MemorySSAUpdater MSSAU(MSSA); + return iterativelySinkInstructions(F, DT, LI, AA, MSSAU); } void getAnalysisUsage(AnalysisUsage &AU) const override { From e71736fe12b18958b6ec20e41de2f14024c6e15f Mon Sep 17 00:00:00 2001 From: John Lu Date: Thu, 24 Apr 2025 15:11:04 -0500 Subject: [PATCH 11/14] Add MemorySSA pass bookkeeping code Signed-off-by: John Lu --- llvm/lib/Transforms/Scalar/Sink.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp index 3a77b044fcf78..9fee85ee5adc5 100644 --- a/llvm/lib/Transforms/Scalar/Sink.cpp +++ b/llvm/lib/Transforms/Scalar/Sink.cpp @@ -300,6 +300,7 @@ PreservedAnalyses SinkingPass::run(Function &F, FunctionAnalysisManager &AM) { PreservedAnalyses PA; PA.preserveSet(); + PA.preserve(); return PA; } @@ -326,8 +327,10 @@ namespace { AU.addRequired(); AU.addRequired(); AU.addRequired(); + AU.addRequired(); AU.addPreserved(); AU.addPreserved(); + AU.addPreserved(); } }; } // end anonymous namespace @@ -336,6 +339,7 @@ char SinkingLegacyPass::ID = 0; INITIALIZE_PASS_BEGIN(SinkingLegacyPass, "sink", "Code sinking", false, false) INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) +INITIALIZE_PASS_DEPENDENCY(MemorySSAWrapperPass) INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass) INITIALIZE_PASS_END(SinkingLegacyPass, "sink", "Code sinking", false, false) From 9be673cf75798f88ca89f7bd02ffd1dc5f133a49 Mon Sep 17 00:00:00 2001 From: John Lu Date: Fri, 25 Apr 2025 00:00:38 -0500 Subject: [PATCH 12/14] Add Memory SSA to checks Signed-off-by: John Lu --- llvm/test/CodeGen/AMDGPU/llc-pipeline.ll | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/llvm/test/CodeGen/AMDGPU/llc-pipeline.ll b/llvm/test/CodeGen/AMDGPU/llc-pipeline.ll index 7179f687c70f2..0d6fa3a80b883 100644 --- a/llvm/test/CodeGen/AMDGPU/llc-pipeline.ll +++ b/llvm/test/CodeGen/AMDGPU/llc-pipeline.ll @@ -249,6 +249,7 @@ ; GCN-O1-NEXT: Basic Alias Analysis (stateless AA impl) ; GCN-O1-NEXT: Function Alias Analysis Results ; GCN-O1-NEXT: Natural Loop Information +; GCN-O1-NEXT: Memory SSA ; GCN-O1-NEXT: Code sinking ; GCN-O1-NEXT: Cycle Info Analysis ; GCN-O1-NEXT: Uniformity Analysis @@ -550,6 +551,7 @@ ; GCN-O1-OPTS-NEXT: Basic Alias Analysis (stateless AA impl) ; GCN-O1-OPTS-NEXT: Function Alias Analysis Results ; GCN-O1-OPTS-NEXT: Natural Loop Information +; GCN-O1-OPTS-NEXT: Memory SSA ; GCN-O1-OPTS-NEXT: Code sinking ; GCN-O1-OPTS-NEXT: Cycle Info Analysis ; GCN-O1-OPTS-NEXT: Uniformity Analysis @@ -863,6 +865,7 @@ ; GCN-O2-NEXT: Basic Alias Analysis (stateless AA impl) ; GCN-O2-NEXT: Function Alias Analysis Results ; GCN-O2-NEXT: Natural Loop Information +; GCN-O2-NEXT: Memory SSA ; GCN-O2-NEXT: Code sinking ; GCN-O2-NEXT: Cycle Info Analysis ; GCN-O2-NEXT: Uniformity Analysis @@ -1191,6 +1194,7 @@ ; GCN-O3-NEXT: Basic Alias Analysis (stateless AA impl) ; GCN-O3-NEXT: Function Alias Analysis Results ; GCN-O3-NEXT: Natural Loop Information +; GCN-O3-NEXT: Memory SSA ; GCN-O3-NEXT: Code sinking ; GCN-O3-NEXT: Cycle Info Analysis ; GCN-O3-NEXT: Uniformity Analysis From de8d2a4d7e8f0a89f519130a66e8535ed82bbdf1 Mon Sep 17 00:00:00 2001 From: John Lu Date: Sat, 26 Apr 2025 07:52:59 -0500 Subject: [PATCH 13/14] Add braces. Signed-off-by: John Lu --- llvm/lib/Transforms/Scalar/Sink.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp index 9fee85ee5adc5..07554857c2c97 100644 --- a/llvm/lib/Transforms/Scalar/Sink.cpp +++ b/llvm/lib/Transforms/Scalar/Sink.cpp @@ -79,7 +79,7 @@ static bool hasStoreConflict(BasicBlock *LoadBB, BasicBlock *BB, StoreCnt += Accesses->size(); if (StoreCnt > SinkLoadStoreLimit) return true; - for (auto &MA : *Accesses) + for (auto &MA : *Accesses) { if (auto *MD = dyn_cast(&MA)) { Instruction *S = MD->getMemoryInst(); if (LoadInst *L = dyn_cast(ReadMemInst)) { @@ -91,11 +91,13 @@ static bool hasStoreConflict(BasicBlock *LoadBB, BasicBlock *BB, return true; } } + } } - for (BasicBlock *Pred : predecessors(BB)) + for (BasicBlock *Pred : predecessors(BB)) { if (hasStoreConflict(LoadBB, Pred, VisitedBlocksSet, MSSAU, BAA, ReadMemInst, StoreCnt)) return true; + } return false; } From 6aba0eaeeefdfa4bf2921266e78f92ee5ecc7cfb Mon Sep 17 00:00:00 2001 From: John Lu Date: Tue, 29 Apr 2025 08:54:49 -0500 Subject: [PATCH 14/14] Test -sink-load-store-limit Signed-off-by: John Lu --- llvm/test/Transforms/Sink/loadsink-limit.ll | 67 +++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 llvm/test/Transforms/Sink/loadsink-limit.ll diff --git a/llvm/test/Transforms/Sink/loadsink-limit.ll b/llvm/test/Transforms/Sink/loadsink-limit.ll new file mode 100644 index 0000000000000..471b912390625 --- /dev/null +++ b/llvm/test/Transforms/Sink/loadsink-limit.ll @@ -0,0 +1,67 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 +; RUN: opt -S < %s -passes=sink -sink-load-store-limit=2 | FileCheck %s --check-prefix=CHECK_LIMIT_2 +; RUN: opt -S < %s -passes=sink -sink-load-store-limit=3 | FileCheck %s --check-prefix=CHECK_LIMIT_3 + +; Test -sink-load-store-limit option + +; Load can be sunk if -sink-load-store-limit >=3. There are 3 stores to analyze in block thenA. +define void @load_can_sink_noalias(i1 %condReturn, i1 %condA, i1 %condB, ptr noalias %a, ptr %b, ptr %c, ptr %d) { +; CHECK_LIMIT_2-LABEL: define void @load_can_sink_noalias( +; CHECK_LIMIT_2-SAME: i1 [[CONDRETURN:%.*]], i1 [[CONDA:%.*]], i1 [[CONDB:%.*]], ptr noalias [[A:%.*]], ptr [[B:%.*]], ptr [[C:%.*]], ptr [[D:%.*]]) { +; CHECK_LIMIT_2-NEXT: [[ENTRY:.*:]] +; CHECK_LIMIT_2-NEXT: br i1 [[CONDRETURN]], label %[[IFA:.*]], label %[[RETURN_BLOCK:.*]] +; CHECK_LIMIT_2: [[IFA]]: +; CHECK_LIMIT_2-NEXT: [[VALUE:%.*]] = load i32, ptr [[A]], align 4 +; CHECK_LIMIT_2-NEXT: br i1 [[CONDA]], label %[[THENA:.*]], label %[[IFB:.*]] +; CHECK_LIMIT_2: [[THENA]]: +; CHECK_LIMIT_2-NEXT: store i32 0, ptr [[B]], align 4 +; CHECK_LIMIT_2-NEXT: store i32 1, ptr [[C]], align 4 +; CHECK_LIMIT_2-NEXT: store i32 2, ptr [[D]], align 4 +; CHECK_LIMIT_2-NEXT: br label %[[IFB]] +; CHECK_LIMIT_2: [[IFB]]: +; CHECK_LIMIT_2-NEXT: br i1 [[CONDB]], label %[[THENB:.*]], label %[[RETURN_BLOCK]] +; CHECK_LIMIT_2: [[THENB]]: +; CHECK_LIMIT_2-NEXT: store i32 [[VALUE]], ptr [[B]], align 4 +; CHECK_LIMIT_2-NEXT: br label %[[RETURN_BLOCK]] +; CHECK_LIMIT_2: [[RETURN_BLOCK]]: +; CHECK_LIMIT_2-NEXT: ret void +; +; CHECK_LIMIT_3-LABEL: define void @load_can_sink_noalias( +; CHECK_LIMIT_3-SAME: i1 [[CONDRETURN:%.*]], i1 [[CONDA:%.*]], i1 [[CONDB:%.*]], ptr noalias [[A:%.*]], ptr [[B:%.*]], ptr [[C:%.*]], ptr [[D:%.*]]) { +; CHECK_LIMIT_3-NEXT: [[ENTRY:.*:]] +; CHECK_LIMIT_3-NEXT: br i1 [[CONDRETURN]], label %[[IFA:.*]], label %[[RETURN_BLOCK:.*]] +; CHECK_LIMIT_3: [[IFA]]: +; CHECK_LIMIT_3-NEXT: br i1 [[CONDA]], label %[[THENA:.*]], label %[[IFB:.*]] +; CHECK_LIMIT_3: [[THENA]]: +; CHECK_LIMIT_3-NEXT: store i32 0, ptr [[B]], align 4 +; CHECK_LIMIT_3-NEXT: store i32 1, ptr [[C]], align 4 +; CHECK_LIMIT_3-NEXT: store i32 2, ptr [[D]], align 4 +; CHECK_LIMIT_3-NEXT: br label %[[IFB]] +; CHECK_LIMIT_3: [[IFB]]: +; CHECK_LIMIT_3-NEXT: br i1 [[CONDB]], label %[[THENB:.*]], label %[[RETURN_BLOCK]] +; CHECK_LIMIT_3: [[THENB]]: +; CHECK_LIMIT_3-NEXT: [[VALUE:%.*]] = load i32, ptr [[A]], align 4 +; CHECK_LIMIT_3-NEXT: store i32 [[VALUE]], ptr [[B]], align 4 +; CHECK_LIMIT_3-NEXT: br label %[[RETURN_BLOCK]] +; CHECK_LIMIT_3: [[RETURN_BLOCK]]: +; CHECK_LIMIT_3-NEXT: ret void +; +entry: + %value = load i32, ptr %a, align 4 + br i1 %condReturn, label %ifA, label %return_block +ifA: + br i1 %condA, label %thenA, label %ifB +thenA: + store i32 0, ptr %b + store i32 1, ptr %c + store i32 2, ptr %d + br label %ifB +ifB: + br i1 %condB, label %thenB, label %return_block +thenB: + store i32 %value, ptr %b + br label %return_block +return_block: + ret void +} +