Skip to content

Commit 1cf6f21

Browse files
committed
[IR] Disable select ? C : undef -> C fold in ConstantFoldSelectInstruction unless we know C isn't poison.
This matches the recent change to InstSimplify from D83440. Differential Revision: https://reviews.llvm.org/D83535
1 parent 954db63 commit 1cf6f21

File tree

3 files changed

+93
-3
lines changed

3 files changed

+93
-3
lines changed

llvm/lib/IR/ConstantFold.cpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -779,10 +779,30 @@ Constant *llvm::ConstantFoldSelectInstruction(Constant *Cond,
779779
if (isa<UndefValue>(V1)) return V1;
780780
return V2;
781781
}
782-
if (isa<UndefValue>(V1)) return V2;
783-
if (isa<UndefValue>(V2)) return V1;
782+
784783
if (V1 == V2) return V1;
785784

785+
// If the true or false value is undef, we can fold to the other value as
786+
// long as the other value isn't poison.
787+
auto NotPoison = [](Constant *C) {
788+
// TODO: We can analyze ConstExpr by opcode to determine if there is any
789+
// possibility of poison.
790+
if (isa<ConstantExpr>(C))
791+
return false;
792+
793+
if (isa<ConstantInt>(C) || isa<GlobalVariable>(C) || isa<ConstantFP>(C) ||
794+
isa<ConstantPointerNull>(C) || isa<Function>(C))
795+
return true;
796+
797+
if (C->getType()->isVectorTy())
798+
return !C->containsUndefElement() && !C->containsConstantExpression();
799+
800+
// TODO: Recursively analyze aggregates or other constants.
801+
return false;
802+
};
803+
if (isa<UndefValue>(V1) && NotPoison(V2)) return V2;
804+
if (isa<UndefValue>(V2) && NotPoison(V1)) return V1;
805+
786806
if (ConstantExpr *TrueVal = dyn_cast<ConstantExpr>(V1)) {
787807
if (TrueVal->getOpcode() == Instruction::Select)
788808
if (TrueVal->getOperand(0) == Cond)

llvm/test/Transforms/InferAddressSpaces/AMDGPU/select.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ define amdgpu_kernel void @store_select_group_global_mismatch_inttoptr_flat_null
221221
}
222222

223223
; CHECK-LABEL: @store_select_group_global_mismatch_undef_undef_constexpr(
224-
; CHECK: store i32 7, i32 addrspace(3)* null
224+
; CHECK: store i32 7, i32* select (i1 icmp eq (i32 ptrtoint (i32 addrspace(3)* @lds1 to i32), i32 4), i32* addrspacecast (i32 addrspace(3)* null to i32*), i32* undef), align 4
225225
define amdgpu_kernel void @store_select_group_global_mismatch_undef_undef_constexpr() #0 {
226226
store i32 7, i32* select (i1 icmp eq (i32 ptrtoint (i32 addrspace(3)* @lds1 to i32), i32 4), i32* addrspacecast (i32 addrspace(3)* null to i32*), i32* addrspacecast (i32 addrspace(1)* undef to i32*)), align 4
227227
ret void

llvm/test/Transforms/InstSimplify/select.ll

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -858,3 +858,73 @@ define <2 x i32> @false_undef_true_constextpr_vec(i1 %cond) {
858858
%s = select i1 %cond, <2 x i32> <i32 undef, i32 ptrtoint (i32* @g to i32)>, <2 x i32> <i32 ptrtoint (i32* @g to i32), i32 undef>
859859
ret <2 x i32> %s
860860
}
861+
862+
define i32 @all_constant_true_undef() {
863+
; CHECK-LABEL: @all_constant_true_undef(
864+
; CHECK-NEXT: ret i32 1
865+
;
866+
%s = select i1 ptrtoint (i32 ()* @all_constant_true_undef to i1), i32 undef, i32 1
867+
ret i32 %s
868+
}
869+
870+
define float @all_constant_false_undef() {
871+
; CHECK-LABEL: @all_constant_false_undef(
872+
; CHECK-NEXT: ret float 1.000000e+00
873+
;
874+
%s = select i1 ptrtoint (float ()* @all_constant_false_undef to i1), float undef, float 1.0
875+
ret float %s
876+
}
877+
878+
define <2 x i32> @all_constant_true_undef_vec() {
879+
; CHECK-LABEL: @all_constant_true_undef_vec(
880+
; CHECK-NEXT: ret <2 x i32> <i32 1, i32 -1>
881+
;
882+
%s = select i1 ptrtoint (<2 x i32> ()* @all_constant_true_undef_vec to i1), <2 x i32> undef, <2 x i32> <i32 1, i32 -1>
883+
ret <2 x i32> %s
884+
}
885+
886+
define <2 x float> @all_constant_false_undef_vec() {
887+
; CHECK-LABEL: @all_constant_false_undef_vec(
888+
; CHECK-NEXT: ret <2 x float> <float 1.000000e+00, float -1.000000e+00>
889+
;
890+
%s = select i1 ptrtoint (<2 x float> ()* @all_constant_false_undef_vec to i1), <2 x float> undef, <2 x float> <float 1.0, float -1.0>
891+
ret <2 x float> %s
892+
}
893+
894+
; Negative tests. Don't fold if the non-undef operand is a constexpr.
895+
define i32 @all_constant_false_undef_true_constexpr() {
896+
; CHECK-LABEL: @all_constant_false_undef_true_constexpr(
897+
; CHECK-NEXT: [[S:%.*]] = select i1 ptrtoint (i32 ()* @all_constant_false_undef_true_constexpr to i1), i32 ptrtoint (i32 ()* @all_constant_false_undef_true_constexpr to i32), i32 undef
898+
; CHECK-NEXT: ret i32 [[S]]
899+
;
900+
%s = select i1 ptrtoint (i32 ()* @all_constant_false_undef_true_constexpr to i1), i32 ptrtoint (i32 ()* @all_constant_false_undef_true_constexpr to i32), i32 undef
901+
ret i32 %s
902+
}
903+
904+
define i32 @all_constant_true_undef_false_constexpr() {
905+
; CHECK-LABEL: @all_constant_true_undef_false_constexpr(
906+
; CHECK-NEXT: [[S:%.*]] = select i1 ptrtoint (i32 ()* @all_constant_true_undef_false_constexpr to i1), i32 undef, i32 ptrtoint (i32 ()* @all_constant_true_undef_false_constexpr to i32)
907+
; CHECK-NEXT: ret i32 [[S]]
908+
;
909+
%s = select i1 ptrtoint (i32 ()* @all_constant_true_undef_false_constexpr to i1), i32 undef, i32 ptrtoint (i32 ()* @all_constant_true_undef_false_constexpr to i32)
910+
ret i32 %s
911+
}
912+
913+
; Negative tests. Don't fold if the non-undef operand is a vector containing a constexpr.
914+
define <2 x i32> @all_constant_false_undef_true_constexpr_vec() {
915+
; CHECK-LABEL: @all_constant_false_undef_true_constexpr_vec(
916+
; CHECK-NEXT: [[S:%.*]] = select i1 ptrtoint (<2 x i32> ()* @all_constant_false_undef_true_constexpr_vec to i1), <2 x i32> <i32 ptrtoint (<2 x i32> ()* @all_constant_false_undef_true_constexpr_vec to i32), i32 -1>, <2 x i32> undef
917+
; CHECK-NEXT: ret <2 x i32> [[S]]
918+
;
919+
%s = select i1 ptrtoint (<2 x i32> ()* @all_constant_false_undef_true_constexpr_vec to i1), <2 x i32> <i32 ptrtoint (<2 x i32> ()* @all_constant_false_undef_true_constexpr_vec to i32), i32 -1>, <2 x i32> undef
920+
ret <2 x i32> %s
921+
}
922+
923+
define <2 x i32> @all_constant_true_undef_false_constexpr_vec() {
924+
; CHECK-LABEL: @all_constant_true_undef_false_constexpr_vec(
925+
; CHECK-NEXT: [[S:%.*]] = select i1 ptrtoint (<2 x i32> ()* @all_constant_true_undef_false_constexpr_vec to i1), <2 x i32> undef, <2 x i32> <i32 -1, i32 ptrtoint (<2 x i32> ()* @all_constant_true_undef_false_constexpr_vec to i32)>
926+
; CHECK-NEXT: ret <2 x i32> [[S]]
927+
;
928+
%s = select i1 ptrtoint (<2 x i32> ()* @all_constant_true_undef_false_constexpr_vec to i1), <2 x i32> undef, <2 x i32><i32 -1, i32 ptrtoint (<2 x i32> ()* @all_constant_true_undef_false_constexpr_vec to i32)>
929+
ret <2 x i32> %s
930+
}

0 commit comments

Comments
 (0)