Skip to content

Commit 137be18

Browse files
authored
Merge pull request #682 from JuliaLLVM/tb/ir-transforms
Instruction simplification, block splitting and inlining
2 parents b8cf02d + 29d87ec commit 137be18

16 files changed

Lines changed: 967 additions & 40 deletions

‎deps/LLVMExtra/include/LLVMExtra.h‎

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1083,12 +1083,24 @@ LLVMBool LLVMExtraDominatorTreeBlockDominates(LLVMDominatorTreeRef Tree, LLVMBas
10831083
void LLVMExtraDominatorTreeRecalculate(LLVMDominatorTreeRef Tree, LLVMValueRef F);
10841084
// split the block containing `SplitBefore` before it, and insert a conditional branch on
10851085
// `Cond` to a new block that ends with a branch to the tail of the split block (or with an
1086-
// unreachable). Returns the terminator of the new block. If `Tree` is not NULL, it is
1086+
// unreachable). Returns the terminator of the new block. The conditional branch gets
1087+
// `!prof` branch weights if NumBranchWeights is not 0. If `Tree` is not NULL, it is
10871088
// updated for the changes to the CFG; returns NULL (without changing anything) if it is
10881089
// not a tree for the current entry block of the function containing `SplitBefore`.
10891090
LLVMValueRef LLVMExtraSplitBlockAndInsertIfThen(LLVMValueRef Cond, LLVMValueRef SplitBefore,
10901091
LLVMBool Unreachable,
1092+
const unsigned *BranchWeights,
1093+
unsigned NumBranchWeights,
10911094
LLVMDominatorTreeRef Tree);
1095+
// like LLVMExtraSplitBlockAndInsertIfThen, but branching to one of two new blocks, whose
1096+
// terminators are written to ThenTerm and ElseTerm. Returns false (without changing
1097+
// anything) if `Tree` is not a tree for the function containing `SplitBefore`.
1098+
LLVMBool LLVMExtraSplitBlockAndInsertIfThenElse(LLVMValueRef Cond, LLVMValueRef SplitBefore,
1099+
const unsigned *BranchWeights,
1100+
unsigned NumBranchWeights,
1101+
LLVMDominatorTreeRef Tree,
1102+
LLVMValueRef *ThenTerm,
1103+
LLVMValueRef *ElseTerm);
10921104

10931105
// whether an instruction is unused and has no side effects, and delete such an instruction
10941106
// together with the operands that become trivially dead (returns false if the instruction
@@ -1114,6 +1126,26 @@ LLVMBool LLVMExtraPromoteMemToReg(LLVMValueRef *Allocas, unsigned NumAllocas,
11141126
LLVMBool LLVMExtraConstantFoldCastOperand(LLVMOpcode Opcode, LLVMValueRef C,
11151127
LLVMTypeRef DestTy, LLVMTargetDataRef TD,
11161128
LLVMValueRef *Result);
1129+
// simplify an instruction, like InstSimplify, without changing it: returns a simpler value
1130+
// that it is equivalent to, or NULL
1131+
LLVMValueRef LLVMExtraSimplifyInstruction(LLVMValueRef Inst);
1132+
1133+
// split a basic block before an instruction (with the head bit of the iterator, as for
1134+
// LLVMExtraMoveInstruction), moving the instructions from there on to a new block that the
1135+
// original one branches to, like BasicBlock::splitBasicBlock. Returns the new block.
1136+
LLVMBasicBlockRef LLVMExtraSplitBasicBlock(LLVMBasicBlockRef BB, LLVMValueRef Before,
1137+
LLVMBool Head, const char *Name);
1138+
// inline a call site, like InlineFunction (without updating a call graph or using alias
1139+
// analysis). Returns whether the call was inlined; if not, nothing is changed, and if
1140+
// FailureReason is not NULL, it is set to a message (to be disposed of using
1141+
// LLVMDisposeMessage) that describes why. Like InlineFunction, this doesn't check whether
1142+
// the body of the called function can be inlined (see LLVMExtraIsInlineViable).
1143+
LLVMBool LLVMExtraInlineFunction(LLVMValueRef Call, LLVMBool MergeAttributes,
1144+
LLVMBool InsertLifetime, char **FailureReason);
1145+
// whether the body of a function can be inlined into other functions, like isInlineViable;
1146+
// if not, and FailureReason is not NULL, it is set to a message (to be disposed of using
1147+
// LLVMDisposeMessage) that describes why.
1148+
LLVMBool LLVMExtraIsInlineViable(LLVMValueRef Fn, char **FailureReason);
11171149

11181150
// target triples, parsed like llvm::Triple(Str) (without normalizing them). The names of
11191151
// the components are those of llvm::Triple::get*TypeName.

‎deps/LLVMExtra/lib/Analysis.cpp‎

Lines changed: 125 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
#include "LLVMExtra.h"
22

33
#include <llvm/ADT/APInt.h>
4+
#include <llvm/ADT/SmallPtrSet.h>
45
#include <llvm/Analysis/AssumptionCache.h>
56
#include <llvm/Analysis/ConstantFolding.h>
67
#include <llvm/Analysis/DomTreeUpdater.h>
8+
#include <llvm/Analysis/InlineCost.h>
9+
#include <llvm/Analysis/InstructionSimplify.h>
710
#include <llvm/Analysis/LazyValueInfo.h>
811
#include <llvm/Analysis/LoopInfo.h>
912
#include <llvm/Analysis/ScalarEvolution.h>
@@ -13,6 +16,7 @@
1316
#include <llvm/Analysis/SimplifyQuery.h>
1417
#endif
1518
#include <llvm/IR/Attributes.h>
19+
#include <llvm/IR/CFG.h>
1620
#include <llvm/IR/ConstantRange.h>
1721
#include <llvm/IR/Dominators.h>
1822
#include <llvm/IR/IntrinsicInst.h>
@@ -24,6 +28,7 @@
2428
#include <llvm/IR/Operator.h>
2529
#include <llvm/Support/KnownBits.h>
2630
#include <llvm/Transforms/Utils/BasicBlockUtils.h>
31+
#include <llvm/Transforms/Utils/Cloning.h>
2732
#include <llvm/Transforms/Utils/Local.h>
2833
#include <llvm/Transforms/Utils/PromoteMemToReg.h>
2934

@@ -807,22 +812,79 @@ void LLVMExtraDominatorTreeRecalculate(LLVMDominatorTreeRef Tree, LLVMValueRef F
807812
unwrap(Tree)->recalculate(*unwrap<Function>(F));
808813
}
809814

815+
// the `!prof` node for the given branch weights, or NULL without weights
816+
static MDNode *createBranchWeights(LLVMContext &C, const unsigned *Weights,
817+
unsigned NumWeights) {
818+
if (NumWeights == 0)
819+
return nullptr;
820+
SmallVector<uint32_t, 2> W(Weights, Weights + NumWeights);
821+
return MDBuilder(C).createBranchWeights(W);
822+
}
823+
824+
// whether a dominator tree is one of the function containing an instruction. the root of a
825+
// tree is the entry block of its function (compared without dereferencing it, as the tree
826+
// may be stale), and LLVM asserts that blocks are of that function
827+
static bool isTreeOf(LLVMDominatorTreeRef Tree, Instruction *I) {
828+
return unwrap(Tree)->getRoot() == &I->getFunction()->getEntryBlock();
829+
}
830+
810831
LLVMValueRef LLVMExtraSplitBlockAndInsertIfThen(LLVMValueRef Cond, LLVMValueRef SplitBefore,
811832
LLVMBool Unreachable,
833+
const unsigned *BranchWeights,
834+
unsigned NumBranchWeights,
812835
LLVMDominatorTreeRef Tree) {
813836
Instruction *I = unwrap<Instruction>(SplitBefore);
814837
std::optional<DomTreeUpdater> DTU;
815838
if (Tree) {
816-
// the root of a tree is the entry block of its function (compared without dereferencing
817-
// it, as the tree may be stale), and LLVM asserts that blocks are of that function
818-
if (unwrap(Tree)->getRoot() != &I->getFunction()->getEntryBlock())
839+
if (!isTreeOf(Tree, I))
819840
return nullptr;
820841
DTU.emplace(*unwrap(Tree), DomTreeUpdater::UpdateStrategy::Eager);
821842
}
843+
MDNode *Weights = createBranchWeights(I->getContext(), BranchWeights, NumBranchWeights);
822844
// the overload taking an instruction and a DomTreeUpdater exists in every version
823845
DomTreeUpdater *Updater = DTU ? &*DTU : nullptr;
824-
return wrap(SplitBlockAndInsertIfThen(unwrap(Cond), I, Unreachable,
825-
/*BranchWeights=*/nullptr, Updater));
846+
return wrap(SplitBlockAndInsertIfThen(unwrap(Cond), I, Unreachable, Weights, Updater));
847+
}
848+
849+
LLVMBool LLVMExtraSplitBlockAndInsertIfThenElse(LLVMValueRef Cond, LLVMValueRef SplitBefore,
850+
const unsigned *BranchWeights,
851+
unsigned NumBranchWeights,
852+
LLVMDominatorTreeRef Tree,
853+
LLVMValueRef *ThenTerm,
854+
LLVMValueRef *ElseTerm) {
855+
Instruction *I = unwrap<Instruction>(SplitBefore);
856+
if (Tree && !isTreeOf(Tree, I))
857+
return false;
858+
MDNode *Weights = createBranchWeights(I->getContext(), BranchWeights, NumBranchWeights);
859+
Instruction *Then, *Else;
860+
#if LLVM_VERSION_MAJOR >= 16
861+
std::optional<DomTreeUpdater> DTU;
862+
if (Tree)
863+
DTU.emplace(*unwrap(Tree), DomTreeUpdater::UpdateStrategy::Eager);
864+
DomTreeUpdater *Updater = DTU ? &*DTU : nullptr;
865+
SplitBlockAndInsertIfThenElse(unwrap(Cond), I, &Then, &Else, Weights, Updater);
866+
#else
867+
// LLVM 15 can't update a dominator tree here, so apply the updates that LLVM 16 does
868+
BasicBlock *Head = I->getParent();
869+
SmallPtrSet<BasicBlock *, 8> UniqueOrigSuccessors(succ_begin(Head), succ_end(Head));
870+
SplitBlockAndInsertIfThenElse(unwrap(Cond), I, &Then, &Else, Weights);
871+
if (Tree) {
872+
BasicBlock *Tail = I->getParent();
873+
SmallVector<DominatorTree::UpdateType, 8> Updates;
874+
for (BasicBlock *Succ : successors(Head)) {
875+
Updates.push_back({DominatorTree::Insert, Head, Succ});
876+
Updates.push_back({DominatorTree::Insert, Succ, Tail});
877+
}
878+
for (BasicBlock *Succ : UniqueOrigSuccessors)
879+
Updates.push_back({DominatorTree::Insert, Tail, Succ});
880+
for (BasicBlock *Succ : UniqueOrigSuccessors)
881+
Updates.push_back({DominatorTree::Delete, Head, Succ});
882+
DomTreeUpdater(*unwrap(Tree), DomTreeUpdater::UpdateStrategy::Eager).applyUpdates(Updates);
883+
}
884+
#endif
885+
*ThenTerm = wrap(Then);
886+
*ElseTerm = wrap(Else);
887+
return true;
826888
}
827889

828890

@@ -886,3 +948,61 @@ LLVMBool LLVMExtraConstantFoldCastOperand(LLVMOpcode Opcode, LLVMValueRef C,
886948
*Result = wrap(ConstantFoldCastOperand(Op, Const, Ty, *unwrap(TD)));
887949
return true;
888950
}
951+
952+
LLVMValueRef LLVMExtraSimplifyInstruction(LLVMValueRef Inst) {
953+
Instruction *I = unwrap<Instruction>(Inst);
954+
return wrap(simplifyInstruction(I, SimplifyQuery(I->getModule()->getDataLayout(), I)));
955+
}
956+
957+
958+
// Control flow
959+
960+
LLVMBasicBlockRef LLVMExtraSplitBasicBlock(LLVMBasicBlockRef BB, LLVMValueRef Before,
961+
LLVMBool Head, const char *Name) {
962+
BasicBlock::iterator It = unwrap<Instruction>(Before)->getIterator();
963+
#if LLVM_VERSION_MAJOR >= 19
964+
It.setHeadBit(Head);
965+
#endif
966+
return wrap(unwrap(BB)->splitBasicBlock(It, Name));
967+
}
968+
969+
970+
// Inlining
971+
972+
LLVMBool LLVMExtraInlineFunction(LLVMValueRef Call, LLVMBool MergeAttributes,
973+
LLVMBool InsertLifetime, char **FailureReason) {
974+
CallBase *CB = unwrap<CallBase>(Call);
975+
Function *Caller = CB->getCaller();
976+
InlineFunctionInfo IFI;
977+
#if LLVM_VERSION_MAJOR < 22
978+
// before checking the personality functions, InlineFunction gives a caller without a GC
979+
// strategy the one of the callee, which it doesn't undo when it then fails. it changes
980+
// nothing else before failing (it only sets the personality function of a caller that
981+
// has none, after which it can't fail anymore), so undo that to leave the IR unchanged.
982+
bool CallerHadGC = Caller->hasGC();
983+
#endif
984+
#if LLVM_VERSION_MAJOR >= 16
985+
InlineResult Result =
986+
InlineFunction(*CB, IFI, MergeAttributes, /*CalleeAAR=*/nullptr, InsertLifetime);
987+
#else
988+
// InlineFunction doesn't merge the attributes yet, which its callers did instead
989+
Function *Callee = CB->getCalledFunction();
990+
InlineResult Result = InlineFunction(*CB, IFI, /*CalleeAAR=*/nullptr, InsertLifetime);
991+
if (Result.isSuccess() && MergeAttributes)
992+
AttributeFuncs::mergeAttributesForInlining(*Caller, *Callee);
993+
#endif
994+
#if LLVM_VERSION_MAJOR < 22
995+
if (!Result.isSuccess() && !CallerHadGC)
996+
Caller->clearGC();
997+
#endif
998+
if (FailureReason)
999+
*FailureReason = Result.isSuccess() ? nullptr : strdup(Result.getFailureReason());
1000+
return Result.isSuccess();
1001+
}
1002+
1003+
LLVMBool LLVMExtraIsInlineViable(LLVMValueRef Fn, char **FailureReason) {
1004+
InlineResult Result = isInlineViable(*unwrap<Function>(Fn));
1005+
if (FailureReason)
1006+
*FailureReason = Result.isSuccess() ? nullptr : strdup(Result.getFailureReason());
1007+
return Result.isSuccess();
1008+
}

‎docs/src/lib/analyses.md‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,16 @@ PostDomTree
1616
dispose(::PostDomTree)
1717
dominates
1818
recalculate!
19+
split_block!
1920
split_block_and_insert_if_then!
21+
split_block_and_insert_if_then_else!
2022
```
2123

22-
## Constant folding
24+
## Constant folding and simplification
2325

2426
```@docs
2527
constant_fold_cast
28+
simplify_instruction
2629
```
2730

2831
## Constant ranges and known bits

‎docs/src/lib/transforms.md‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,10 @@ LLVM.collect_flat_address_operands
7171
clone_into!
7272
clone
7373
```
74+
75+
## Inlining
76+
77+
```@docs
78+
inline!
79+
inline_viability
80+
```

‎docs/src/man/blocks.md‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,13 @@ The control flow between basic blocks can be inspected using the following prope
4444
terminator. This view is mutable: `bb.successors[i] = other` changes the destination of
4545
the terminator.
4646

47+
To create control flow, `split_block!(inst, name)` splits a block in two before an
48+
instruction, with the first part branching to the second, and
49+
`split_block_and_insert_if_then!(cond, inst)` additionally inserts a block that only
50+
executes if a condition holds, and `split_block_and_insert_if_then_else!(cond, inst)` one
51+
for either outcome. Both can attach branch weights (`weights=(1, 9)`) to the conditional
52+
branch, and update a dominator tree.
53+
4754

4855
## Instructions
4956

‎lib/15/libLLVM_extra.jl‎

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1242,8 +1242,12 @@ function LLVMExtraDominatorTreeRecalculate(Tree, F)
12421242
ccall((:LLVMExtraDominatorTreeRecalculate, libLLVMExtra), Cvoid, (LLVMDominatorTreeRef, LLVMValueRef), Tree, F)
12431243
end
12441244

1245-
function LLVMExtraSplitBlockAndInsertIfThen(Cond, SplitBefore, Unreachable, Tree)
1246-
ccall((:LLVMExtraSplitBlockAndInsertIfThen, libLLVMExtra), LLVMValueRef, (LLVMValueRef, LLVMValueRef, LLVMBool, LLVMDominatorTreeRef), Cond, SplitBefore, Unreachable, Tree)
1245+
function LLVMExtraSplitBlockAndInsertIfThen(Cond, SplitBefore, Unreachable, BranchWeights, NumBranchWeights, Tree)
1246+
ccall((:LLVMExtraSplitBlockAndInsertIfThen, libLLVMExtra), LLVMValueRef, (LLVMValueRef, LLVMValueRef, LLVMBool, Ptr{Cuint}, Cuint, LLVMDominatorTreeRef), Cond, SplitBefore, Unreachable, BranchWeights, NumBranchWeights, Tree)
1247+
end
1248+
1249+
function LLVMExtraSplitBlockAndInsertIfThenElse(Cond, SplitBefore, BranchWeights, NumBranchWeights, Tree, ThenTerm, ElseTerm)
1250+
ccall((:LLVMExtraSplitBlockAndInsertIfThenElse, libLLVMExtra), LLVMBool, (LLVMValueRef, LLVMValueRef, Ptr{Cuint}, Cuint, LLVMDominatorTreeRef, Ptr{LLVMValueRef}, Ptr{LLVMValueRef}), Cond, SplitBefore, BranchWeights, NumBranchWeights, Tree, ThenTerm, ElseTerm)
12471251
end
12481252

12491253
function LLVMExtraIsInstructionTriviallyDead(Inst)
@@ -1270,6 +1274,22 @@ function LLVMExtraConstantFoldCastOperand(Opcode, C, DestTy, TD, Result)
12701274
ccall((:LLVMExtraConstantFoldCastOperand, libLLVMExtra), LLVMBool, (LLVMOpcode, LLVMValueRef, LLVMTypeRef, LLVMTargetDataRef, Ptr{LLVMValueRef}), Opcode, C, DestTy, TD, Result)
12711275
end
12721276

1277+
function LLVMExtraSimplifyInstruction(Inst)
1278+
ccall((:LLVMExtraSimplifyInstruction, libLLVMExtra), LLVMValueRef, (LLVMValueRef,), Inst)
1279+
end
1280+
1281+
function LLVMExtraSplitBasicBlock(BB, Before, Head, Name)
1282+
ccall((:LLVMExtraSplitBasicBlock, libLLVMExtra), LLVMBasicBlockRef, (LLVMBasicBlockRef, LLVMValueRef, LLVMBool, Cstring), BB, Before, Head, Name)
1283+
end
1284+
1285+
function LLVMExtraInlineFunction(Call, MergeAttributes, InsertLifetime, FailureReason)
1286+
ccall((:LLVMExtraInlineFunction, libLLVMExtra), LLVMBool, (LLVMValueRef, LLVMBool, LLVMBool, Ptr{Cstring}), Call, MergeAttributes, InsertLifetime, FailureReason)
1287+
end
1288+
1289+
function LLVMExtraIsInlineViable(Fn, FailureReason)
1290+
ccall((:LLVMExtraIsInlineViable, libLLVMExtra), LLVMBool, (LLVMValueRef, Ptr{Cstring}), Fn, FailureReason)
1291+
end
1292+
12731293
function LLVMExtraTripleGetArchTypeName(Triple)
12741294
ccall((:LLVMExtraTripleGetArchTypeName, libLLVMExtra), Cstring, (Cstring,), Triple)
12751295
end

‎lib/16/libLLVM_extra.jl‎

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1282,8 +1282,12 @@ function LLVMExtraDominatorTreeRecalculate(Tree, F)
12821282
ccall((:LLVMExtraDominatorTreeRecalculate, libLLVMExtra), Cvoid, (LLVMDominatorTreeRef, LLVMValueRef), Tree, F)
12831283
end
12841284

1285-
function LLVMExtraSplitBlockAndInsertIfThen(Cond, SplitBefore, Unreachable, Tree)
1286-
ccall((:LLVMExtraSplitBlockAndInsertIfThen, libLLVMExtra), LLVMValueRef, (LLVMValueRef, LLVMValueRef, LLVMBool, LLVMDominatorTreeRef), Cond, SplitBefore, Unreachable, Tree)
1285+
function LLVMExtraSplitBlockAndInsertIfThen(Cond, SplitBefore, Unreachable, BranchWeights, NumBranchWeights, Tree)
1286+
ccall((:LLVMExtraSplitBlockAndInsertIfThen, libLLVMExtra), LLVMValueRef, (LLVMValueRef, LLVMValueRef, LLVMBool, Ptr{Cuint}, Cuint, LLVMDominatorTreeRef), Cond, SplitBefore, Unreachable, BranchWeights, NumBranchWeights, Tree)
1287+
end
1288+
1289+
function LLVMExtraSplitBlockAndInsertIfThenElse(Cond, SplitBefore, BranchWeights, NumBranchWeights, Tree, ThenTerm, ElseTerm)
1290+
ccall((:LLVMExtraSplitBlockAndInsertIfThenElse, libLLVMExtra), LLVMBool, (LLVMValueRef, LLVMValueRef, Ptr{Cuint}, Cuint, LLVMDominatorTreeRef, Ptr{LLVMValueRef}, Ptr{LLVMValueRef}), Cond, SplitBefore, BranchWeights, NumBranchWeights, Tree, ThenTerm, ElseTerm)
12871291
end
12881292

12891293
function LLVMExtraIsInstructionTriviallyDead(Inst)
@@ -1310,6 +1314,22 @@ function LLVMExtraConstantFoldCastOperand(Opcode, C, DestTy, TD, Result)
13101314
ccall((:LLVMExtraConstantFoldCastOperand, libLLVMExtra), LLVMBool, (LLVMOpcode, LLVMValueRef, LLVMTypeRef, LLVMTargetDataRef, Ptr{LLVMValueRef}), Opcode, C, DestTy, TD, Result)
13111315
end
13121316

1317+
function LLVMExtraSimplifyInstruction(Inst)
1318+
ccall((:LLVMExtraSimplifyInstruction, libLLVMExtra), LLVMValueRef, (LLVMValueRef,), Inst)
1319+
end
1320+
1321+
function LLVMExtraSplitBasicBlock(BB, Before, Head, Name)
1322+
ccall((:LLVMExtraSplitBasicBlock, libLLVMExtra), LLVMBasicBlockRef, (LLVMBasicBlockRef, LLVMValueRef, LLVMBool, Cstring), BB, Before, Head, Name)
1323+
end
1324+
1325+
function LLVMExtraInlineFunction(Call, MergeAttributes, InsertLifetime, FailureReason)
1326+
ccall((:LLVMExtraInlineFunction, libLLVMExtra), LLVMBool, (LLVMValueRef, LLVMBool, LLVMBool, Ptr{Cstring}), Call, MergeAttributes, InsertLifetime, FailureReason)
1327+
end
1328+
1329+
function LLVMExtraIsInlineViable(Fn, FailureReason)
1330+
ccall((:LLVMExtraIsInlineViable, libLLVMExtra), LLVMBool, (LLVMValueRef, Ptr{Cstring}), Fn, FailureReason)
1331+
end
1332+
13131333
function LLVMExtraTripleGetArchTypeName(Triple)
13141334
ccall((:LLVMExtraTripleGetArchTypeName, libLLVMExtra), Cstring, (Cstring,), Triple)
13151335
end

0 commit comments

Comments
 (0)