-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[SimplifyCFG] Treat umul + extract pattern as cheap single instruction. #124933
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
838e617
31dcf40
134ad7b
3fb1a07
5634169
3ed3573
63a3125
4d014d5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3286,7 +3286,21 @@ bool SimplifyCFGOpt::speculativelyExecuteBB(BranchInst *BI, | |
|
|
||
| SmallVector<Instruction *, 4> SpeculatedDbgIntrinsics; | ||
|
|
||
| // The number of already examined instructions. Debug instructions don't | ||
| // count! | ||
| unsigned SpeculatedInstructions = 0; | ||
| // By default the number of instructions that may be speculatevly executed is | ||
spaits marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| // one. Whenever a pattern is found in the basic block, that is cheap for sure | ||
| // we increase this number to the size of the pattern (how many instructions | ||
| // are there in that pattern). | ||
spaits marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| unsigned MaxSpeculatedInstructionsToHoist = 1; | ||
antoniofrighetto marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| // In case we have found a cheap pattern, we don't want to do cost checking | ||
| // anymore. We are sure we want to hoist the pattern. To know, that we are | ||
| // only hoisting the cheap pattern only and not other expensive instructions | ||
| // too, we have the `MaxSpeculatedInstructionsToHoist` variable to track that | ||
| // the basic block truly only contains that pattern. | ||
| bool PartialInst = false; | ||
spaits marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| bool HoistLoadsStores = HoistLoadsStoresWithCondFaulting && | ||
| Options.HoistLoadsStoresWithCondFaulting; | ||
| SmallVector<Instruction *, 2> SpeculatedConditionalLoadsStores; | ||
|
|
@@ -3316,34 +3330,45 @@ bool SimplifyCFGOpt::speculativelyExecuteBB(BranchInst *BI, | |
| if (EphTracker.track(&I)) | ||
| continue; | ||
|
|
||
| // Only speculatively execute a single instruction (not counting the | ||
| // terminator) for now. | ||
| bool IsSafeCheapLoadStore = HoistLoadsStores && | ||
| isSafeCheapLoadStore(&I, TTI) && | ||
| SpeculatedConditionalLoadsStores.size() < | ||
| HoistLoadsStoresWithCondFaultingThreshold; | ||
|
|
||
| // Overflow arithmetic instruction plus extract value are usually generated | ||
| // when a division is being replaced, but the zero check may still be there. | ||
| // In that case hoist these two instructions out of this basic block, and | ||
| // let later optimizations take care of the unnecessary zero checks. | ||
| WithOverflowInst *OverflowI; | ||
| if (match(&I, m_ExtractValue<1>(m_OneUse(m_WithOverflowInst(OverflowI))))) { | ||
| MaxSpeculatedInstructionsToHoist = 2; | ||
| PartialInst = true; | ||
| } | ||
| // Not count load/store into cost if target supports conditional faulting | ||
| // b/c it's cheap to speculate it. | ||
| if (IsSafeCheapLoadStore) | ||
| SpeculatedConditionalLoadsStores.push_back(&I); | ||
| else | ||
| ++SpeculatedInstructions; | ||
|
|
||
| if (SpeculatedInstructions > 1) | ||
| return false; | ||
|
|
||
| // Don't hoist the instruction if it's unsafe or expensive. | ||
| if (!IsSafeCheapLoadStore && | ||
| !isSafeToSpeculativelyExecute(&I, BI, Options.AC) && | ||
| !(HoistCondStores && !SpeculatedStoreValue && | ||
| (SpeculatedStoreValue = | ||
| isSafeToSpeculateStore(&I, BB, ThenBB, EndBB)))) | ||
| return false; | ||
| if (!IsSafeCheapLoadStore && !SpeculatedStoreValue && | ||
|
|
||
| if (!PartialInst && !IsSafeCheapLoadStore && !SpeculatedStoreValue && | ||
| computeSpeculationCost(&I, TTI) > | ||
| PHINodeFoldingThreshold * TargetTransformInfo::TCC_Basic) | ||
| return false; | ||
|
|
||
| // The number of instrcutions to be speculatively executed is limited. | ||
spaits marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| // This limit is dependent on the found patterns. | ||
| if (SpeculatedInstructions > MaxSpeculatedInstructionsToHoist) | ||
| return false; | ||
|
||
|
|
||
| // Store the store speculation candidate. | ||
| if (!SpeculatedStore && SpeculatedStoreValue) | ||
| SpeculatedStore = cast<StoreInst>(&I); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py | ||
| ; RUN: opt -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S < %s | FileCheck %s | ||
| target triple = "riscv64-unknown-unknown-elf" | ||
|
|
||
| define i16 @func2(i64 %x, i64 %y) { | ||
| ; CHECK-LABEL: @func2( | ||
| ; CHECK-NEXT: entry: | ||
| ; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i64 [[Y:%.*]], 0 | ||
| ; CHECK-NEXT: [[MUL:%.*]] = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[Y]], i64 [[X:%.*]]) | ||
| ; CHECK-NEXT: [[MUL_OV:%.*]] = extractvalue { i64, i1 } [[MUL]], 1 | ||
| ; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[CMP_NOT]], i1 false, i1 [[MUL_OV]] | ||
| ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[SPEC_SELECT]] to i16 | ||
| ; CHECK-NEXT: ret i16 [[CONV]] | ||
| ; | ||
| entry: | ||
| %cmp.not = icmp eq i64 %y, 0 | ||
| br i1 %cmp.not, label %land.end, label %land.rhs | ||
|
|
||
| land.rhs: ; preds = %entry | ||
| %mul = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %y, i64 %x) | ||
| %mul.ov = extractvalue { i64, i1 } %mul, 1 | ||
| br label %land.end | ||
|
|
||
| land.end: ; preds = %land.rhs, %entry | ||
| %0 = phi i1 [ false, %entry ], [ %mul.ov, %land.rhs ] | ||
| %conv = zext i1 %0 to i16 | ||
| ret i16 %conv | ||
| } | ||
|
|
||
| define i16 @noHoist(i64 %x, i64 %y) { | ||
| ; CHECK-LABEL: @noHoist( | ||
| ; CHECK-NEXT: entry: | ||
| ; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i64 [[Y:%.*]], 0 | ||
| ; CHECK-NEXT: br i1 [[CMP_NOT]], label [[LAND_END:%.*]], label [[LAND_RHS:%.*]] | ||
| ; CHECK: land.rhs: | ||
| ; CHECK-NEXT: [[ADD2:%.*]] = add nsw i64 [[Y]], [[X:%.*]] | ||
| ; CHECK-NEXT: [[MUL:%.*]] = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[ADD2]], i64 [[X]]) | ||
| ; CHECK-NEXT: [[MUL_OV:%.*]] = extractvalue { i64, i1 } [[MUL]], 1 | ||
| ; CHECK-NEXT: br label [[LAND_END]] | ||
| ; CHECK: land.end: | ||
| ; CHECK-NEXT: [[SPEC_SELECT:%.*]] = phi i1 [ false, [[ENTRY:%.*]] ], [ [[MUL_OV]], [[LAND_RHS]] ] | ||
| ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[SPEC_SELECT]] to i16 | ||
| ; CHECK-NEXT: ret i16 [[CONV]] | ||
| ; | ||
| entry: | ||
| %cmp.not = icmp eq i64 %y, 0 | ||
| br i1 %cmp.not, label %land.end, label %land.rhs | ||
|
|
||
| land.rhs: ; preds = %entry | ||
| %add = add nsw i64 %y, %x | ||
spaits marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| %mul = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %add, i64 %x) | ||
| %mul.ov = extractvalue { i64, i1 } %mul, 1 | ||
| br label %land.end | ||
|
|
||
| land.end: ; preds = %land.rhs, %entry | ||
| %0 = phi i1 [ false, %entry ], [ %mul.ov, %land.rhs ] | ||
| %conv = zext i1 %0 to i16 | ||
| ret i16 %conv | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.