@@ -85,8 +85,6 @@ using namespace PatternMatch;
85
85
86
86
STATISTIC (NumSimplified, " Number of library calls simplified" );
87
87
88
-
89
-
90
88
static cl::opt<unsigned > GuardWideningWindow (
91
89
" instcombine-guard-widening-window" ,
92
90
cl::init (3 ),
@@ -2989,20 +2987,6 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
2989
2987
}
2990
2988
break ;
2991
2989
}
2992
- case Intrinsic::amdgcn_ballot: {
2993
- // Optimize ballot intrinsics when the condition is known to be uniform
2994
- Value *Condition = II->getArgOperand (0 );
2995
-
2996
- // If the condition is a constant, we can evaluate the ballot directly
2997
- if (auto *ConstCond = dyn_cast<ConstantInt>(Condition)) {
2998
- // ballot(true) -> -1 (all lanes active)
2999
- // ballot(false) -> 0 (no lanes active)
3000
- uint64_t Result = ConstCond->isOne () ? ~0ULL : 0ULL ;
3001
- return replaceInstUsesWith (*II, ConstantInt::get (II->getType (), Result));
3002
- }
3003
-
3004
- break ;
3005
- }
3006
2990
case Intrinsic::ldexp: {
3007
2991
// ldexp(ldexp(x, a), b) -> ldexp(x, a + b)
3008
2992
//
@@ -3556,8 +3540,6 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
3556
3540
}
3557
3541
}
3558
3542
3559
-
3560
-
3561
3543
// If there is a dominating assume with the same condition as this one,
3562
3544
// then this one is redundant, and should be removed.
3563
3545
KnownBits Known (1 );
@@ -3571,7 +3553,9 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
3571
3553
return eraseInstFromFunction (*II);
3572
3554
}
3573
3555
3574
-
3556
+ // Try to extract uniformity information from the assume and optimize
3557
+ // dominated uses of any variables that are established as uniform.
3558
+ optimizeAssumedUniformValues (cast<AssumeInst>(II));
3575
3559
3576
3560
// Update the cache of affected values for this assumption (we might be
3577
3561
// here because we just simplified the condition).
@@ -5026,3 +5010,117 @@ InstCombinerImpl::transformCallThroughTrampoline(CallBase &Call,
5026
5010
Call.setCalledFunction (FTy, NestF);
5027
5011
return &Call;
5028
5012
}
5013
+
5014
+ // / Extract uniformity information from assume and optimize dominated uses.
5015
+ // / This works with any assume pattern that establishes value uniformity.
5016
+ void InstCombinerImpl::optimizeAssumedUniformValues (AssumeInst *Assume) {
5017
+ Value *AssumedCondition = Assume->getArgOperand (0 );
5018
+
5019
+ // Map of uniform values to their uniform constants
5020
+ SmallDenseMap<Value *, Constant *> UniformValues;
5021
+
5022
+ // Pattern 1: assume(icmp eq (X, C)) -> X is uniform and equals C
5023
+ if (auto *ICmp = dyn_cast<ICmpInst>(AssumedCondition)) {
5024
+ if (ICmp->getPredicate () == ICmpInst::ICMP_EQ) {
5025
+ Value *LHS = ICmp->getOperand (0 );
5026
+ Value *RHS = ICmp->getOperand (1 );
5027
+
5028
+ // X == constant -> X is uniform and equals constant
5029
+ if (auto *C = dyn_cast<Constant>(RHS)) {
5030
+ UniformValues[LHS] = C;
5031
+ } else if (auto *C = dyn_cast<Constant>(LHS)) {
5032
+ UniformValues[RHS] = C;
5033
+ }
5034
+
5035
+ // Handle intrinsic patterns in equality comparisons
5036
+ // Pattern: assume(ballot(cmp) == -1) -> cmp is uniform and true
5037
+ if (auto *IntrinsicCall = dyn_cast<IntrinsicInst>(LHS)) {
5038
+ if (IntrinsicCall->getIntrinsicID () == Intrinsic::amdgcn_ballot) {
5039
+ if (match (RHS, m_AllOnes ())) {
5040
+ Value *BallotArg = IntrinsicCall->getArgOperand (0 );
5041
+ if (BallotArg->getType ()->isIntegerTy (1 )) {
5042
+ UniformValues[BallotArg] = ConstantInt::getTrue (BallotArg->getType ());
5043
+
5044
+ // Special case: if BallotArg is an equality comparison,
5045
+ // we know the operands are equal
5046
+ if (auto *CmpInst = dyn_cast<ICmpInst>(BallotArg)) {
5047
+ if (CmpInst->getPredicate () == ICmpInst::ICMP_EQ) {
5048
+ Value *CmpLHS = CmpInst->getOperand (0 );
5049
+ Value *CmpRHS = CmpInst->getOperand (1 );
5050
+
5051
+ // If one operand is constant, the other is uniform and equals that constant
5052
+ if (auto *C = dyn_cast<Constant>(CmpRHS)) {
5053
+ UniformValues[CmpLHS] = C;
5054
+ } else if (auto *C = dyn_cast<Constant>(CmpLHS)) {
5055
+ UniformValues[CmpRHS] = C;
5056
+ }
5057
+ // TODO: Handle case where both operands are variables
5058
+ }
5059
+ }
5060
+ }
5061
+ }
5062
+ } else if (IntrinsicCall->getIntrinsicID () == Intrinsic::amdgcn_readfirstlane) {
5063
+ // assume(readfirstlane(x) == c) -> x is uniform and equals c
5064
+ if (auto *C = dyn_cast<Constant>(RHS)) {
5065
+ Value *ReadFirstLaneArg = IntrinsicCall->getArgOperand (0 );
5066
+ UniformValues[ReadFirstLaneArg] = C;
5067
+ }
5068
+ }
5069
+ }
5070
+
5071
+ // Handle the reverse case too
5072
+ if (auto *IntrinsicCall = dyn_cast<IntrinsicInst>(RHS)) {
5073
+ if (IntrinsicCall->getIntrinsicID () == Intrinsic::amdgcn_ballot) {
5074
+ if (match (LHS, m_AllOnes ())) {
5075
+ Value *BallotArg = IntrinsicCall->getArgOperand (0 );
5076
+ if (BallotArg->getType ()->isIntegerTy (1 )) {
5077
+ UniformValues[BallotArg] = ConstantInt::getTrue (BallotArg->getType ());
5078
+ }
5079
+ }
5080
+ } else if (IntrinsicCall->getIntrinsicID () == Intrinsic::amdgcn_readfirstlane) {
5081
+ if (auto *C = dyn_cast<Constant>(LHS)) {
5082
+ Value *ReadFirstLaneArg = IntrinsicCall->getArgOperand (0 );
5083
+ UniformValues[ReadFirstLaneArg] = C;
5084
+ }
5085
+ }
5086
+ }
5087
+ }
5088
+ }
5089
+
5090
+ // Pattern 2: assume(X) where X is i1 -> X is uniform and equals true
5091
+ if (AssumedCondition->getType ()->isIntegerTy (1 ) && !isa<ICmpInst>(AssumedCondition)) {
5092
+ UniformValues[AssumedCondition] = ConstantInt::getTrue (AssumedCondition->getType ());
5093
+ }
5094
+
5095
+ // Now optimize dominated uses of all discovered uniform values
5096
+ for (auto &[UniformValue, UniformConstant] : UniformValues) {
5097
+ SmallVector<Use *, 8 > DominatedUses;
5098
+
5099
+ // Find all uses dominated by the assume
5100
+ // Skip if the value doesn't have a use list (e.g., constants)
5101
+ if (!UniformValue->hasUseList ())
5102
+ continue ;
5103
+
5104
+ for (Use &U : UniformValue->uses ()) {
5105
+ Instruction *UseInst = dyn_cast<Instruction>(U.getUser ());
5106
+ if (!UseInst || UseInst == Assume)
5107
+ continue ;
5108
+
5109
+ // Critical: Check dominance using InstCombine's infrastructure
5110
+ if (isValidAssumeForContext (Assume, UseInst, &DT)) {
5111
+ DominatedUses.push_back (&U);
5112
+ }
5113
+ }
5114
+
5115
+ // Replace only dominated uses with the uniform constant
5116
+ for (Use *U : DominatedUses) {
5117
+ U->set (UniformConstant);
5118
+ Worklist.pushValue (U->getUser ());
5119
+ }
5120
+
5121
+ // Mark for further optimization if we made changes
5122
+ if (!DominatedUses.empty ()) {
5123
+ Worklist.pushValue (UniformValue);
5124
+ }
5125
+ }
5126
+ }
0 commit comments