This is a simple patch that folds freeze(undef) into a proper constant after inspecting its uses.
Reviewed By: nikic
Differential Revision: https://reviews.llvm.org/D84948
return NV;
}
+ if (match(Op0, m_Undef())) {
+ // If I is freeze(undef), see its uses and fold it to the best constant.
+ // - or: pick -1
+ // - select's condition: pick the value that leads to choosing a constant
+ // - other ops: pick 0
+ Constant *BestValue = nullptr;
+ Constant *NullValue = Constant::getNullValue(I.getType());
+ for (const auto *U : I.users()) {
+ Constant *C = NullValue;
+
+ if (match(U, m_Or(m_Value(), m_Value())))
+ C = Constant::getAllOnesValue(I.getType());
+ else if (const auto *SI = dyn_cast<SelectInst>(U)) {
+ if (SI->getCondition() == &I) {
+ APInt CondVal(1, isa<Constant>(SI->getFalseValue()) ? 0 : 1);
+ C = Constant::getIntegerValue(I.getType(), CondVal);
+ }
+ }
+
+ if (!BestValue)
+ BestValue = C;
+ else if (BestValue != C)
+ BestValue = NullValue;
+ }
+
+ return replaceInstUsesWith(I, BestValue);
+ }
+
return nullptr;
}
; CHECK-NEXT: i8 1, label [[C:%.*]]
; CHECK-NEXT: ]
; CHECK: A:
-; CHECK-NEXT: [[PHI_FR:%.*]] = freeze i32 undef
; CHECK-NEXT: br label [[D:%.*]]
; CHECK: B:
; CHECK-NEXT: br label [[D]]
; CHECK: C:
; CHECK-NEXT: br label [[D]]
; CHECK: D:
-; CHECK-NEXT: [[Y:%.*]] = phi i32 [ [[PHI_FR]], [[A]] ], [ 32, [[B]] ], [ 0, [[C]] ]
+; CHECK-NEXT: [[Y:%.*]] = phi i32 [ 0, [[A]] ], [ 32, [[B]] ], [ 0, [[C]] ]
; CHECK-NEXT: ret i32 [[Y]]
;
switch i8 %cond, label %A [
define i32 @and_freeze_undef(i32 %x) {
; CHECK-LABEL: @and_freeze_undef(
-; CHECK-NEXT: [[F:%.*]] = freeze i32 undef
-; CHECK-NEXT: [[RES:%.*]] = and i32 [[F]], [[X:%.*]]
-; CHECK-NEXT: ret i32 [[RES]]
+; CHECK-NEXT: ret i32 0
;
%f = freeze i32 undef
%res = and i32 %x, %f
define i32 @and_freeze_undef_multipleuses(i32 %x) {
; CHECK-LABEL: @and_freeze_undef_multipleuses(
-; CHECK-NEXT: [[F:%.*]] = freeze i32 undef
-; CHECK-NEXT: [[RES:%.*]] = and i32 [[F]], [[X:%.*]]
-; CHECK-NEXT: call void @use_i32(i32 [[F]])
-; CHECK-NEXT: ret i32 [[RES]]
+; CHECK-NEXT: call void @use_i32(i32 0)
+; CHECK-NEXT: ret i32 0
;
%f = freeze i32 undef
%res = and i32 %x, %f
define i32 @or_freeze_undef(i32 %x) {
; CHECK-LABEL: @or_freeze_undef(
-; CHECK-NEXT: [[F:%.*]] = freeze i32 undef
-; CHECK-NEXT: [[RES:%.*]] = or i32 [[F]], [[X:%.*]]
-; CHECK-NEXT: ret i32 [[RES]]
+; CHECK-NEXT: ret i32 -1
;
%f = freeze i32 undef
%res = or i32 %x, %f
define i32 @or_freeze_undef_multipleuses(i32 %x) {
; CHECK-LABEL: @or_freeze_undef_multipleuses(
-; CHECK-NEXT: [[F:%.*]] = freeze i32 undef
-; CHECK-NEXT: [[RES:%.*]] = or i32 [[F]], [[X:%.*]]
-; CHECK-NEXT: call void @use_i32(i32 [[F]])
-; CHECK-NEXT: ret i32 [[RES]]
+; CHECK-NEXT: call void @use_i32(i32 0)
+; CHECK-NEXT: ret i32 [[X:%.*]]
;
%f = freeze i32 undef
%res = or i32 %x, %f
define void @or_select_multipleuses(i32 %x, i1 %y) {
; CHECK-LABEL: @or_select_multipleuses(
-; CHECK-NEXT: [[F:%.*]] = freeze i1 undef
-; CHECK-NEXT: [[A:%.*]] = select i1 [[F]], i32 [[X:%.*]], i32 32
-; CHECK-NEXT: [[B:%.*]] = or i1 [[F]], [[Y:%.*]]
-; CHECK-NEXT: call void @use_i32_i1(i32 [[A]], i1 [[B]])
+; CHECK-NEXT: call void @use_i32_i1(i32 32, i1 [[Y:%.*]])
; CHECK-NEXT: ret void
;
%f = freeze i1 undef
define i8 @cond_freeze(i8 %x, i8 %y) {
; CHECK-LABEL: @cond_freeze(
-; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 undef
-; CHECK-NEXT: [[S:%.*]] = select i1 [[COND_FR]], i8 [[X:%.*]], i8 [[Y:%.*]]
-; CHECK-NEXT: ret i8 [[S]]
+; CHECK-NEXT: ret i8 [[X:%.*]]
;
%cond.fr = freeze i1 undef
%s = select i1 %cond.fr, i8 %x, i8 %y
define i8 @cond_freeze2(i8 %x, i8 %y) {
; CHECK-LABEL: @cond_freeze2(
-; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 undef
-; CHECK-NEXT: [[S:%.*]] = select i1 [[COND_FR]], i8 [[X:%.*]], i8 1
-; CHECK-NEXT: ret i8 [[S]]
+; CHECK-NEXT: ret i8 1
;
%cond.fr = freeze i1 undef
%s = select i1 %cond.fr, i8 %x, i8 1
define i8 @cond_freeze3(i8 %x) {
; CHECK-LABEL: @cond_freeze3(
-; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 undef
-; CHECK-NEXT: [[S:%.*]] = select i1 [[COND_FR]], i8 1, i8 [[X:%.*]]
-; CHECK-NEXT: ret i8 [[S]]
+; CHECK-NEXT: ret i8 1
;
%cond.fr = freeze i1 undef
%s = select i1 %cond.fr, i8 1, i8 %x
define <2 x i8> @cond_freeze_vec(<2 x i8> %x) {
; CHECK-LABEL: @cond_freeze_vec(
-; CHECK-NEXT: [[COND_FR:%.*]] = freeze <2 x i1> undef
-; CHECK-NEXT: [[S:%.*]] = select <2 x i1> [[COND_FR]], <2 x i8> <i8 1, i8 2>, <2 x i8> [[X:%.*]]
-; CHECK-NEXT: ret <2 x i8> [[S]]
+; CHECK-NEXT: ret <2 x i8> <i8 1, i8 2>
;
%cond.fr = freeze <2 x i1> <i1 undef, i1 undef>
%s = select <2 x i1> %cond.fr, <2 x i8> <i8 1, i8 2>, <2 x i8> %x
define void @cond_freeze_multipleuses(i8 %x, i8 %y) {
; CHECK-LABEL: @cond_freeze_multipleuses(
-; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 undef
-; CHECK-NEXT: [[S:%.*]] = select i1 [[COND_FR]], i8 [[X:%.*]], i8 [[Y:%.*]]
-; CHECK-NEXT: [[S2:%.*]] = select i1 [[COND_FR]], i8 [[Y]], i8 [[X]]
-; CHECK-NEXT: call void @foo2(i8 [[S]], i8 [[S2]])
+; CHECK-NEXT: call void @foo2(i8 [[X:%.*]], i8 [[Y:%.*]])
; CHECK-NEXT: ret void
;
%cond.fr = freeze i1 undef