legacy inliner pass. Backend stack coloring should handle cases alloca
merging initially set out to handle.
-* InstructionSimplify APIs now require instructions be inserted into a
- parent function.
-
Changes to building LLVM
------------------------
// values. This will prevent other code from seeing the same undef uses and
// resolving them to different values.
//
-// They require that all the IR that they encounter be valid and inserted into a
-// parent function.
+// These routines are designed to tolerate moderately incomplete IR, such as
+// instructions that are not connected to basic blocks yet. However, they do
+// require that all the IR that they encounter be valid. In particular, they
+// require that all non-constant values be defined in the same function, and the
+// same call context of that function (and not split between caller and callee
+// contexts of a directly recursive call, for example).
//
// Additionally, these routines can't simplify to the instructions that are not
// def-reachable, meaning we can't just scan the basic block for instructions
/// Unlink this basic block from its current function and insert it into
/// the function that \p MovePos lives in, right before \p MovePos.
- inline void moveBefore(BasicBlock *MovePos) {
- moveBefore(MovePos->getIterator());
- }
- void moveBefore(SymbolTableList<BasicBlock>::iterator MovePos);
+ void moveBefore(BasicBlock *MovePos);
/// Unlink this basic block from its current function and insert it
/// right after \p MovePos in the function \p MovePos lives in.
ArrayRef<Value *> NewOps,
const SimplifyQuery &SQ,
unsigned MaxRecurse) {
- assert(I->getFunction() && "instruction should be inserted in a function");
const SimplifyQuery Q = SQ.CxtI ? SQ : SQ.getWithInstruction(I);
switch (I->getOpcode()) {
return getParent()->getBasicBlockList().erase(getIterator());
}
-void BasicBlock::moveBefore(SymbolTableList<BasicBlock>::iterator MovePos) {
- getParent()->splice(MovePos, getParent(), getIterator());
+void BasicBlock::moveBefore(BasicBlock *MovePos) {
+ MovePos->getParent()->splice(MovePos->getIterator(), getParent(),
+ getIterator());
}
void BasicBlock::moveAfter(BasicBlock *MovePos) {
// mapping and using it to remap operands in the cloned instructions.
for (; BI != BB->end(); ++BI) {
Instruction *New = BI->clone();
- New->insertInto(PredBB, OldPredBranch->getIterator());
// Remap operands to patch up intra-block references.
for (unsigned i = 0, e = New->getNumOperands(); i != e; ++i)
{BB->getModule()->getDataLayout(), TLI, nullptr, nullptr, New})) {
ValueMapping[&*BI] = IV;
if (!New->mayHaveSideEffects()) {
- New->eraseFromParent();
+ New->deleteValue();
New = nullptr;
}
} else {
if (New) {
// Otherwise, insert the new instruction into the block.
New->setName(BI->getName());
+ New->insertInto(PredBB, OldPredBranch->getIterator());
// Update Dominance from simplified New instruction operands.
for (unsigned i = 0, e = New->getNumOperands(); i != e; ++i)
if (BasicBlock *SuccBB = dyn_cast<BasicBlock>(New->getOperand(i)))
// Nope, clone it now.
BasicBlock *NewBB;
- Twine NewName(BB->hasName() ? Twine(BB->getName()) + NameSuffix : "");
- BBEntry = NewBB = BasicBlock::Create(BB->getContext(), NewName, NewFunc);
+ BBEntry = NewBB = BasicBlock::Create(BB->getContext());
+ if (BB->hasName())
+ NewBB->setName(BB->getName() + NameSuffix);
// It is only legal to clone a function if a block address within that
// function is never referenced outside of the function. Given that, we
++II) {
Instruction *NewInst = cloneInstruction(II);
- NewInst->insertInto(NewBB, NewBB->end());
if (HostFuncIsStrictFP) {
// All function calls in the inlined function must get 'strictfp'
// If we can simplify this instruction to some other value, simply add
// a mapping to that value rather than inserting a new instruction into
// the basic block.
+ //
+ // FIXME: simplifyInstruction should know the context of the new function.
if (Value *V =
simplifyInstruction(NewInst, BB->getModule()->getDataLayout())) {
// On the off-chance that this simplifies to an instruction in the old
if (!NewInst->mayHaveSideEffects()) {
VMap[&*II] = V;
- NewInst->eraseFromParent();
+ NewInst->deleteValue();
continue;
}
}
if (II->hasName())
NewInst->setName(II->getName() + NameSuffix);
VMap[&*II] = NewInst; // Add instruction map to value.
+ NewInst->insertInto(NewBB, NewBB->end());
if (isa<CallInst>(II) && !II->isDebugOrPseudoInst()) {
hasCalls = true;
hasMemProfMetadata |= II->hasMetadata(LLVMContext::MD_memprof);
if (!NewBB)
continue; // Dead block.
- // Move the new block to preserve the order in the original function.
- NewBB->moveBefore(NewFunc->end());
+ // Add the new block to the new function.
+ NewFunc->insert(NewFunc->end(), NewBB);
// Handle PHI nodes specially, as we have to remove references to dead
// blocks.
// Otherwise, create a duplicate of the instruction.
Instruction *C = Inst->clone();
- C->insertBefore(LoopEntryBranch);
-
++NumInstrsDuplicated;
// Eagerly remap the operands of the instruction.
// Avoid inserting the same intrinsic twice.
if (auto *DII = dyn_cast<DbgVariableIntrinsic>(C))
if (DbgIntrinsics.count(makeHash(DII))) {
- C->eraseFromParent();
+ C->deleteValue();
continue;
}
// in the map.
InsertNewValueIntoMap(ValueMap, Inst, V);
if (!C->mayHaveSideEffects()) {
- C->eraseFromParent();
+ C->deleteValue();
C = nullptr;
}
} else {
if (C) {
// Otherwise, stick the new instruction into the new block!
C->setName(Inst->getName());
+ C->insertBefore(LoopEntryBranch);
if (auto *II = dyn_cast<AssumeInst>(C))
AC->registerAssumption(II);
}
// Clone the instruction.
Instruction *N = BBI->clone();
- // Insert the new instruction into its new home.
- N->insertInto(EdgeBB, InsertPt);
-
if (BBI->hasName())
N->setName(BBI->getName() + ".c");
if (!BBI->use_empty())
TranslateMap[&*BBI] = V;
if (!N->mayHaveSideEffects()) {
- N->eraseFromParent(); // Instruction folded away, don't need actual
- // inst
+ N->deleteValue(); // Instruction folded away, don't need actual inst
N = nullptr;
}
} else {
TranslateMap[&*BBI] = N;
}
if (N) {
+ // Insert the new instruction into its new home.
+ N->insertInto(EdgeBB, InsertPt);
+
// Register the new instruction with the assumption cache if necessary.
if (auto *Assume = dyn_cast<AssumeInst>(N))
if (AC)
ret ptr %1
}
-define ptr @caller() null_pointer_is_valid {
-; CHECK-LABEL: define ptr @caller
-; CHECK-SAME: () #[[ATTR1:[0-9]+]] {
+define ptr @caller() {
+; CHECK-LABEL: define ptr @caller() {
; CHECK-NEXT: [[TMP1:%.*]] = call ptr @llvm.strip.invariant.group.p0(ptr null)
; CHECK-NEXT: ret ptr [[TMP1]]
;
; CHECK-LABEL: define i1 @simplify_fcmp_ord_fdiv_caller
; CHECK-SAME: (double nofpclass(nan inf zero) [[I0:%.*]], double nofpclass(nan inf zero) [[I1:%.*]]) {
; CHECK-NEXT: [[SUB_DOUBLE_SUB_I:%.*]] = fdiv double [[I0]], [[I1]]
-; CHECK-NEXT: ret i1 true
+; CHECK-NEXT: [[CMP_I:%.*]] = fcmp ord double [[SUB_DOUBLE_SUB_I]], 0.000000e+00
+; CHECK-NEXT: ret i1 [[CMP_I]]
;
%call = call i1 @simplify_fcmp_ord_fdiv_callee(double %i0, double %i1)
ret i1 %call
; CHECK-LABEL: define i1 @simplify_fcmp_ord_frem_caller
; CHECK-SAME: (double nofpclass(nan inf zero) [[I0:%.*]], double nofpclass(nan inf zero) [[I1:%.*]]) {
; CHECK-NEXT: [[SUB_DOUBLE_SUB_I:%.*]] = frem double [[I0]], [[I1]]
-; CHECK-NEXT: ret i1 true
+; CHECK-NEXT: [[CMP_I:%.*]] = fcmp ord double [[SUB_DOUBLE_SUB_I]], 0.000000e+00
+; CHECK-NEXT: ret i1 [[CMP_I]]
;
%call = call i1 @simplify_fcmp_ord_frem_callee(double %i0, double %i1)
ret i1 %call
; CHECK-LABEL: define i1 @simplify_fcmp_ord_fmul_caller
; CHECK-SAME: (double nofpclass(nan inf zero) [[I0:%.*]], double nofpclass(nan inf zero) [[I1:%.*]]) {
; CHECK-NEXT: [[SUB_DOUBLE_SUB_I:%.*]] = fmul double [[I0]], [[I1]]
-; CHECK-NEXT: ret i1 true
+; CHECK-NEXT: [[CMP_I:%.*]] = fcmp ord double [[SUB_DOUBLE_SUB_I]], 0.000000e+00
+; CHECK-NEXT: ret i1 [[CMP_I]]
;
%call = call i1 @simplify_fcmp_ord_fmul_callee(double %i0, double %i1)
ret i1 %call
; CHECK: L0.preheader:
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 0, 0
; CHECK-NEXT: [[INC:%.*]] = zext i1 [[CMP]] to i32
-; CHECK-NEXT: [[TOBOOL3_NOT1:%.*]] = icmp eq i32 [[INC]], 0
-; CHECK-NEXT: br i1 [[TOBOOL3_NOT1]], label [[L0_PREHEADER_LOOPEXIT]], label [[L1_PREHEADER_LR_PH:%.*]]
+; CHECK-NEXT: [[SPEC_SELECT1:%.*]] = add nsw i32 0, [[INC]]
+; CHECK-NEXT: [[TOBOOL3_NOT2:%.*]] = icmp eq i32 [[SPEC_SELECT1]], 0
+; CHECK-NEXT: br i1 [[TOBOOL3_NOT2]], label [[L0_PREHEADER_LOOPEXIT]], label [[L1_PREHEADER_LR_PH:%.*]]
; CHECK: L1.preheader.lr.ph:
; CHECK-NEXT: br label [[L1_PREHEADER:%.*]]
; CHECK: L1.preheader:
-; CHECK-NEXT: [[SPEC_SELECT3:%.*]] = phi i32 [ [[INC]], [[L1_PREHEADER_LR_PH]] ], [ [[SPEC_SELECT:%.*]], [[L0_LATCH:%.*]] ]
-; CHECK-NEXT: [[K_02:%.*]] = phi i32 [ 0, [[L1_PREHEADER_LR_PH]] ], [ [[SPEC_SELECT3]], [[L0_LATCH]] ]
-; CHECK-NEXT: [[TOBOOL8_NOT:%.*]] = icmp eq i32 [[K_02]], 0
+; CHECK-NEXT: [[SPEC_SELECT4:%.*]] = phi i32 [ [[SPEC_SELECT1]], [[L1_PREHEADER_LR_PH]] ], [ [[SPEC_SELECT:%.*]], [[L0_LATCH:%.*]] ]
+; CHECK-NEXT: [[K_03:%.*]] = phi i32 [ 0, [[L1_PREHEADER_LR_PH]] ], [ [[SPEC_SELECT4]], [[L0_LATCH]] ]
+; CHECK-NEXT: [[TOBOOL8_NOT:%.*]] = icmp eq i32 [[K_03]], 0
; CHECK-NEXT: br label [[L0_LATCH]]
; CHECK: L0.latch:
-; CHECK-NEXT: [[SPEC_SELECT]] = add nsw i32 [[SPEC_SELECT3]], [[INC]]
+; CHECK-NEXT: [[SPEC_SELECT]] = add nsw i32 [[SPEC_SELECT4]], [[INC]]
; CHECK-NEXT: [[TOBOOL3_NOT:%.*]] = icmp eq i32 [[SPEC_SELECT]], 0
; CHECK-NEXT: br i1 [[TOBOOL3_NOT]], label [[L0_L0_PREHEADER_LOOPEXIT_CRIT_EDGE:%.*]], label [[L1_PREHEADER]]
;
; INLINE-ALL-NEXT: Getting callee context for instr: %call.i = tail call i32 @_Z8funcLeafi
; INLINE-ALL-NEXT: Callee context found: main:3 @ _Z5funcAi:1 @ _Z8funcLeafi
; INLINE-ALL-NEXT: Marking context profile as inlined: main:3 @ _Z5funcAi:1 @ _Z8funcLeafi
-; INLINE-ALL-NEXT: Getting callee context for instr: %call.i2 = tail call i32 @_Z3fibi
+; INLINE-ALL-NEXT: Getting callee context for instr: %call.i1 = tail call i32 @_Z3fibi
; INLINE-ALL-NEXT: Getting callee context for instr: %call5.i = tail call i32 @_Z3fibi
; INLINE-ALL-DAG: Getting base profile for function: _Z5funcAi
; INLINE-ALL-DAG-NEXT: Merging context profile into base profile: _Z5funcAi
; CHECK: 5: call void @llvm.pseudoprobe(i64 -2624081020897602054, i64 5, i32 0, i64 -1), !dbg ![[#]] - weight: 0 - factor: 1.00)
; CHECK: 1: call void @llvm.pseudoprobe(i64 6699318081062747564, i64 1, i32 0, i64 -1), !dbg ![[#]] - weight: 112 - factor: 1.00)
; CHECK: 2: call void @llvm.pseudoprobe(i64 6699318081062747564, i64 2, i32 0, i64 -1), !dbg ![[#]] - weight: 101 - factor: 1.00)
-; CHECK: 5: %call.i8 = call i32 @bar(i32 noundef %1), !dbg ![[#]] - weight: 101 - factor: 1.00)
+; CHECK: 5: %call.i3 = call i32 @bar(i32 noundef %1), !dbg ![[#]] - weight: 101 - factor: 1.00)
; CHECK: 3: call void @llvm.pseudoprobe(i64 6699318081062747564, i64 3, i32 0, i64 -1), !dbg ![[#]] - weight: 13 - factor: 1.00)
-; CHECK: 6: %call1.i5 = call i32 @bar(i32 noundef %add.i4), !dbg ![[#]] - weight: 13 - factor: 1.00)
+; CHECK: 6: %call1.i6 = call i32 @bar(i32 noundef %add.i5), !dbg ![[#]] - weight: 13 - factor: 1.00)
; CHECK: 4: call void @llvm.pseudoprobe(i64 6699318081062747564, i64 4, i32 0, i64 -1), !dbg ![[#]] - weight: 112 - factor: 1.00)
; CHECK: 14: %call2 = call i32 @bar(i32 noundef %3), !dbg ![[#]] - weight: 124 - factor: 1.00)
; CHECK: 8: call void @llvm.pseudoprobe(i64 -2624081020897602054, i64 8, i32 0, i64 -1), !dbg ![[#]] - weight: 0 - factor: 1.00)
; CHECK: common.ret:
; CHECK-NEXT: ret void
; CHECK: true2.critedge:
-; CHECK-NEXT: call void @dummy(i32 0)
+; CHECK-NEXT: [[CMP2_C:%.*]] = icmp sgt i32 [[X]], 0
+; CHECK-NEXT: [[EXT_C:%.*]] = zext i1 [[CMP2_C]] to i32
+; CHECK-NEXT: call void @dummy(i32 [[EXT_C]])
; CHECK-NEXT: call void @dummy(i32 2)
; CHECK-NEXT: br label [[COMMON_RET]]
;
verifyDebugValuesAreSalvaged();
}
+TEST(Local, SimplifyVScaleWithRange) {
+ LLVMContext C;
+ Module M("Module", C);
+
+ IntegerType *Ty = Type::getInt32Ty(C);
+ Function *VScale = Intrinsic::getDeclaration(&M, Intrinsic::vscale, {Ty});
+ auto *CI = CallInst::Create(VScale, {}, "vscale");
+
+ // Test that simplifyCall won't try to query it's parent function for
+ // vscale_range attributes in order to simplify llvm.vscale -> constant.
+ EXPECT_EQ(simplifyCall(CI, VScale, {}, SimplifyQuery(M.getDataLayout())),
+ nullptr);
+ delete CI;
+}
+
TEST(Local, wouldInstructionBeTriviallyDead) {
LLVMContext Ctx;
std::unique_ptr<Module> M = parseIR(Ctx,