Skip to content

Commit c5f82f7

Browse files
authored
ValueTracking: introduce llvm::isNotCrossLaneOperation (llvm#112011)
Factor out and unify common code from InstSimplify and InstCombine that partially guard against cross-lane vector operations into llvm::isNotCrossLaneOperation in ValueTracking. Alive2 proofs for changed tests: https://alive2.llvm.org/ce/z/68H4ka
1 parent fdf2b0a commit c5f82f7

File tree

7 files changed

+37
-41
lines changed

7 files changed

+37
-41
lines changed

llvm/include/llvm/Analysis/ValueTracking.h

+3
Original file line numberDiff line numberDiff line change
@@ -791,6 +791,9 @@ bool onlyUsedByLifetimeMarkers(const Value *V);
791791
/// droppable instructions.
792792
bool onlyUsedByLifetimeMarkersOrDroppableInsts(const Value *V);
793793

794+
/// Return true if the instruction doesn't potentially cross vector lanes.
795+
bool isNotCrossLaneOperation(const Instruction *I);
796+
794797
/// Return true if the instruction does not have any effects besides
795798
/// calculating the result and does not have undefined behavior.
796799
///

llvm/lib/Analysis/InstructionSimplify.cpp

+4-7
Original file line numberDiff line numberDiff line change
@@ -4343,13 +4343,10 @@ static Value *simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
43434343
if (isa<PHINode>(I))
43444344
return nullptr;
43454345

4346-
if (Op->getType()->isVectorTy()) {
4347-
// For vector types, the simplification must hold per-lane, so forbid
4348-
// potentially cross-lane operations like shufflevector.
4349-
if (!I->getType()->isVectorTy() || isa<ShuffleVectorInst>(I) ||
4350-
isa<CallBase>(I) || isa<BitCastInst>(I))
4351-
return nullptr;
4352-
}
4346+
// For vector types, the simplification must hold per-lane, so forbid
4347+
// potentially cross-lane operations like shufflevector.
4348+
if (Op->getType()->isVectorTy() && !isNotCrossLaneOperation(I))
4349+
return nullptr;
43534350

43544351
// Don't fold away llvm.is.constant checks based on assumptions.
43554352
if (match(I, m_Intrinsic<Intrinsic::is_constant>()))

llvm/lib/Analysis/ValueTracking.cpp

+23
Original file line numberDiff line numberDiff line change
@@ -6947,6 +6947,29 @@ bool llvm::onlyUsedByLifetimeMarkersOrDroppableInsts(const Value *V) {
69476947
V, /* AllowLifetime */ true, /* AllowDroppable */ true);
69486948
}
69496949

6950+
bool llvm::isNotCrossLaneOperation(const Instruction *I) {
6951+
if (auto *II = dyn_cast<IntrinsicInst>(I)) {
6952+
switch (II->getIntrinsicID()) {
6953+
// TODO: expand this list.
6954+
case Intrinsic::ctlz:
6955+
case Intrinsic::cttz:
6956+
case Intrinsic::ctpop:
6957+
case Intrinsic::umin:
6958+
case Intrinsic::umax:
6959+
case Intrinsic::smin:
6960+
case Intrinsic::smax:
6961+
case Intrinsic::usub_sat:
6962+
case Intrinsic::uadd_sat:
6963+
case Intrinsic::ssub_sat:
6964+
case Intrinsic::sadd_sat:
6965+
return true;
6966+
default:
6967+
return false;
6968+
}
6969+
}
6970+
return !isa<CallBase, BitCastInst, ShuffleVectorInst, ExtractElementInst>(I);
6971+
}
6972+
69506973
bool llvm::isSafeToSpeculativelyExecute(const Instruction *Inst,
69516974
const Instruction *CtxI,
69526975
AssumptionCache *AC,

llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp

+2-16
Original file line numberDiff line numberDiff line change
@@ -3636,26 +3636,12 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
36363636
// * The intrinsic is speculatable.
36373637
// * The select condition is not a vector, or the intrinsic does not
36383638
// perform cross-lane operations.
3639-
switch (IID) {
3640-
case Intrinsic::ctlz:
3641-
case Intrinsic::cttz:
3642-
case Intrinsic::ctpop:
3643-
case Intrinsic::umin:
3644-
case Intrinsic::umax:
3645-
case Intrinsic::smin:
3646-
case Intrinsic::smax:
3647-
case Intrinsic::usub_sat:
3648-
case Intrinsic::uadd_sat:
3649-
case Intrinsic::ssub_sat:
3650-
case Intrinsic::sadd_sat:
3639+
if (isSafeToSpeculativelyExecuteWithVariableReplaced(&CI) &&
3640+
isNotCrossLaneOperation(II))
36513641
for (Value *Op : II->args())
36523642
if (auto *Sel = dyn_cast<SelectInst>(Op))
36533643
if (Instruction *R = FoldOpIntoSelect(*II, Sel))
36543644
return R;
3655-
[[fallthrough]];
3656-
default:
3657-
break;
3658-
}
36593645

36603646
if (Instruction *Shuf = foldShuffledIntrinsicOperands(II, Builder))
36613647
return Shuf;

llvm/test/Transforms/InstCombine/ispow2.ll

+2-10
Original file line numberDiff line numberDiff line change
@@ -977,11 +977,7 @@ define i1 @is_pow2or0_ctpop_wrong_pred2_logical(i32 %x) {
977977

978978
define <2 x i1> @is_pow2or0_ctpop_commute_vec_wrong_pred3(<2 x i8> %x) {
979979
; CHECK-LABEL: @is_pow2or0_ctpop_commute_vec_wrong_pred3(
980-
; CHECK-NEXT: [[T0:%.*]] = tail call range(i8 0, 9) <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]])
981-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[T0]], <i8 1, i8 1>
982-
; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq <2 x i8> [[X]], zeroinitializer
983-
; CHECK-NEXT: [[R:%.*]] = and <2 x i1> [[CMP]], [[ISZERO]]
984-
; CHECK-NEXT: ret <2 x i1> [[R]]
980+
; CHECK-NEXT: ret <2 x i1> zeroinitializer
985981
;
986982
%t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x)
987983
%cmp = icmp eq <2 x i8> %t0, <i8 1, i8 1>
@@ -1174,11 +1170,7 @@ define i1 @isnot_pow2nor0_ctpop_wrong_pred2_logical(i32 %x) {
11741170

11751171
define <2 x i1> @isnot_pow2nor0_wrong_pred3_ctpop_commute_vec(<2 x i8> %x) {
11761172
; CHECK-LABEL: @isnot_pow2nor0_wrong_pred3_ctpop_commute_vec(
1177-
; CHECK-NEXT: [[T0:%.*]] = tail call range(i8 0, 9) <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]])
1178-
; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i8> [[T0]], <i8 1, i8 1>
1179-
; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne <2 x i8> [[X]], zeroinitializer
1180-
; CHECK-NEXT: [[R:%.*]] = or <2 x i1> [[CMP]], [[NOTZERO]]
1181-
; CHECK-NEXT: ret <2 x i1> [[R]]
1173+
; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
11821174
;
11831175
%t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x)
11841176
%cmp = icmp ne <2 x i8> %t0, <i8 1, i8 1>

llvm/test/Transforms/InstCombine/select-ctlz-to-cttz.ll

+1-3
Original file line numberDiff line numberDiff line change
@@ -208,10 +208,8 @@ define <2 x i32> @select_clz_to_ctz_vec_with_undef(<2 x i32> %a) {
208208
; CHECK-NEXT: [[SUB:%.*]] = sub <2 x i32> zeroinitializer, [[A:%.*]]
209209
; CHECK-NEXT: [[AND:%.*]] = and <2 x i32> [[A]], [[SUB]]
210210
; CHECK-NEXT: [[LZ:%.*]] = tail call range(i32 0, 33) <2 x i32> @llvm.ctlz.v2i32(<2 x i32> [[AND]], i1 true)
211-
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq <2 x i32> [[A]], zeroinitializer
212211
; CHECK-NEXT: [[SUB1:%.*]] = xor <2 x i32> [[LZ]], <i32 31, i32 undef>
213-
; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[TOBOOL]], <2 x i32> [[LZ]], <2 x i32> [[SUB1]]
214-
; CHECK-NEXT: ret <2 x i32> [[COND]]
212+
; CHECK-NEXT: ret <2 x i32> [[SUB1]]
215213
;
216214
%sub = sub <2 x i32> zeroinitializer, %a
217215
%and = and <2 x i32> %sub, %a

llvm/test/Transforms/InstSimplify/select.ll

+2-5
Original file line numberDiff line numberDiff line change
@@ -1087,13 +1087,10 @@ define i32 @select_ctpop_zero(i32 %x) {
10871087
ret i32 %sel
10881088
}
10891089

1090-
; FIXME: This is safe to fold.
10911090
define <2 x i32> @select_ctpop_zero_vec(<2 x i32> %x) {
10921091
; CHECK-LABEL: @select_ctpop_zero_vec(
1093-
; CHECK-NEXT: [[T0:%.*]] = icmp eq <2 x i32> [[X:%.*]], zeroinitializer
1094-
; CHECK-NEXT: [[T1:%.*]] = call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[X]])
1095-
; CHECK-NEXT: [[SEL:%.*]] = select <2 x i1> [[T0]], <2 x i32> zeroinitializer, <2 x i32> [[T1]]
1096-
; CHECK-NEXT: ret <2 x i32> [[SEL]]
1092+
; CHECK-NEXT: [[T1:%.*]] = call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[X:%.*]])
1093+
; CHECK-NEXT: ret <2 x i32> [[T1]]
10971094
;
10981095
%t0 = icmp eq <2 x i32> %x, zeroinitializer
10991096
%t1 = call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> %x)

0 commit comments

Comments
 (0)