diff --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp index e0861fbedc560..78252ffa7ec78 100644 --- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp +++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp @@ -562,6 +562,18 @@ static Decomposition decompose(Value *V, } } + // (x | y) < 0 => (x < 0) || (y < 0) + if (match(V, m_Or(m_Value(Op0), m_Value(Op1)))) { + if (!isKnownNonNegative(Op0, DL) || !isKnownNonNegative(Op1, DL)) + return MergeResults(Op0, Op1, IsSigned); + } + + // (x & y) < 0 => (x < 0) && (y < 0) + if (match(V, m_And(m_Value(Op0), m_Value(Op1)))) { + if (!isKnownNonNegative(Op0, DL) && !isKnownNonNegative(Op1, DL)) + return MergeResults(Op0, Op1, IsSigned); + } + return {V, IsKnownNonNegative}; } diff --git a/llvm/test/Transforms/ConstraintElimination/and.ll b/llvm/test/Transforms/ConstraintElimination/and.ll index f9824df3975e9..9d89f8e5d3721 100644 --- a/llvm/test/Transforms/ConstraintElimination/and.ll +++ b/llvm/test/Transforms/ConstraintElimination/and.ll @@ -603,3 +603,91 @@ exit: ret i1 %r.10 } + +define void @test_decompose_bitwise_and(i4 %x, i4 %y) { +; CHECK-LABEL: @test_decompose_bitwise_and( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = and i4 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: [[AND:%.*]] = icmp slt i4 [[TMP0]], 0 +; CHECK-NEXT: br i1 [[AND]], label [[BB1:%.*]], label [[EXIT:%.*]] +; CHECK: bb1: +; CHECK-NEXT: [[F_1:%.*]] = icmp sge i4 [[X]], 0 +; CHECK-NEXT: [[F_2:%.*]] = icmp sge i4 [[Y]], 0 +; CHECK-NEXT: [[F_AND:%.*]] = and i1 false, [[F_2]] +; CHECK-NEXT: call void @use(i1 [[F_AND]]) +; CHECK-NEXT: ret void +; CHECK: exit: +; CHECK-NEXT: [[F_3:%.*]] = icmp slt i4 [[X]], 0 +; CHECK-NEXT: [[F_4:%.*]] = icmp slt i4 [[Y]], 0 +; CHECK-NEXT: [[F_AND_2:%.*]] = and i1 false, [[F_4]] +; CHECK-NEXT: call void @use(i1 [[F_AND_2]]) +; CHECK-NEXT: ret void +; +entry: + %1 = and i4 %y, %x + %and = icmp slt i4 %1, 0 + br i1 %and, label %bb1, label %exit + +bb1: + %f.1 = icmp sge i4 %x, 0 + %f.2 = icmp sge i4 %y, 0 + %f.and = and i1 %f.1, %f.2 + call void @use(i1 %f.and) + ret void + +exit: + %f.3 = icmp slt i4 %x, 0 + %f.4 = icmp slt i4 %y, 0 + %f.and.2 = and i1 %f.3, %f.4 + call void @use(i1 %f.and.2) + ret void +} + +define void @test_decompose_nested_bitwise_and(i4 %x, i4 %y, i4 %z) { +; CHECK-LABEL: @test_decompose_nested_bitwise_and( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = and i4 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[TMP0]], [[Z:%.*]] +; CHECK-NEXT: [[AND:%.*]] = icmp slt i4 [[TMP1]], 0 +; CHECK-NEXT: br i1 [[AND]], label [[BB1:%.*]], label [[EXIT:%.*]] +; CHECK: bb1: +; CHECK-NEXT: [[F_1:%.*]] = icmp sge i4 [[X]], 0 +; CHECK-NEXT: [[F_2:%.*]] = icmp sge i4 [[Y]], 0 +; CHECK-NEXT: [[F_3:%.*]] = icmp sge i4 [[Z]], 0 +; CHECK-NEXT: [[F_AND:%.*]] = and i1 [[F_1]], [[F_2]] +; CHECK-NEXT: [[F_AND_2:%.*]] = and i1 [[F_AND]], false +; CHECK-NEXT: call void @use(i1 [[F_AND]]) +; CHECK-NEXT: ret void +; CHECK: exit: +; CHECK-NEXT: [[F_4:%.*]] = icmp slt i4 [[X]], 0 +; CHECK-NEXT: [[F_5:%.*]] = icmp slt i4 [[Y]], 0 +; CHECK-NEXT: [[F_6:%.*]] = icmp slt i4 [[Z]], 0 +; CHECK-NEXT: [[F_AND_3:%.*]] = and i1 [[F_4]], [[F_5]] +; CHECK-NEXT: [[F_AND_4:%.*]] = and i1 [[F_AND_3]], false +; CHECK-NEXT: call void @use(i1 [[F_AND_4]]) +; CHECK-NEXT: ret void +; +entry: + %1 = and i4 %y, %x + %2 = and i4 %1, %z + %and = icmp slt i4 %2, 0 + br i1 %and, label %bb1, label %exit + +bb1: + %f.1 = icmp sge i4 %x, 0 + %f.2 = icmp sge i4 %y, 0 + %f.3 = icmp sge i4 %z, 0 + %f.and = and i1 %f.1, %f.2 + %f.and.2 = and i1 %f.and, %f.3 + call void @use(i1 %f.and) + ret void + +exit: + %f.4 = icmp slt i4 %x, 0 + %f.5 = icmp slt i4 %y, 0 + %f.6 = icmp slt i4 %z, 0 + %f.and.3 = and i1 %f.4, %f.5 + %f.and.4 = and i1 %f.and.3, %f.6 + call void @use(i1 %f.and.4) + ret void +} diff --git a/llvm/test/Transforms/ConstraintElimination/or.ll b/llvm/test/Transforms/ConstraintElimination/or.ll index b401d6f181369..37fecb0348b3b 100644 --- a/llvm/test/Transforms/ConstraintElimination/or.ll +++ b/llvm/test/Transforms/ConstraintElimination/or.ll @@ -808,3 +808,91 @@ end: ; preds = %entry ret void } + +define void @test_decompose_bitwise_or(i4 %x, i4 %y) { +; CHECK-LABEL: @test_decompose_bitwise_or( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = or i4 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: [[OR:%.*]] = icmp slt i4 [[TMP0]], 0 +; CHECK-NEXT: br i1 [[OR]], label [[BB1:%.*]], label [[EXIT:%.*]] +; CHECK: bb1: +; CHECK-NEXT: [[F_1:%.*]] = icmp slt i4 [[X]], 0 +; CHECK-NEXT: [[F_2:%.*]] = icmp slt i4 [[Y]], 0 +; CHECK-NEXT: [[F_OR:%.*]] = or i1 true, [[F_2]] +; CHECK-NEXT: call void @use(i1 [[F_OR]]) +; CHECK-NEXT: ret void +; CHECK: exit: +; CHECK-NEXT: [[F_3:%.*]] = icmp sge i4 [[X]], 0 +; CHECK-NEXT: [[F_4:%.*]] = icmp sge i4 [[Y]], 0 +; CHECK-NEXT: [[F_OR_2:%.*]] = or i1 true, [[F_4]] +; CHECK-NEXT: call void @use(i1 [[F_OR_2]]) +; CHECK-NEXT: ret void +; +entry: + %1 = or i4 %y, %x + %or = icmp slt i4 %1, 0 + br i1 %or, label %bb1, label %exit + +bb1: + %f.1 = icmp slt i4 %x, 0 + %f.2 = icmp slt i4 %y, 0 + %f.or = or i1 %f.1, %f.2 + call void @use(i1 %f.or) + ret void + +exit: + %f.3 = icmp sge i4 %x, 0 + %f.4 = icmp sge i4 %y, 0 + %f.or.2 = or i1 %f.3, %f.4 + call void @use(i1 %f.or.2) + ret void +} + +define void @test_decompose_nested_bitwise_or(i4 %x, i4 %y, i4 %z) { +; CHECK-LABEL: @test_decompose_nested_bitwise_or( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = or i4 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = or i4 [[TMP0]], [[Z:%.*]] +; CHECK-NEXT: [[OR:%.*]] = icmp slt i4 [[TMP1]], 0 +; CHECK-NEXT: br i1 [[OR]], label [[BB1:%.*]], label [[EXIT:%.*]] +; CHECK: bb1: +; CHECK-NEXT: [[F_1:%.*]] = icmp slt i4 [[X]], 0 +; CHECK-NEXT: [[F_2:%.*]] = icmp slt i4 [[Y]], 0 +; CHECK-NEXT: [[F_3:%.*]] = icmp slt i4 [[Z]], 0 +; CHECK-NEXT: [[F_OR:%.*]] = or i1 [[F_1]], [[F_2]] +; CHECK-NEXT: [[F_OR_2:%.*]] = or i1 [[F_OR]], true +; CHECK-NEXT: call void @use(i1 [[F_OR_2]]) +; CHECK-NEXT: ret void +; CHECK: exit: +; CHECK-NEXT: [[F_4:%.*]] = icmp sge i4 [[X]], 0 +; CHECK-NEXT: [[F_5:%.*]] = icmp sge i4 [[Y]], 0 +; CHECK-NEXT: [[F_6:%.*]] = icmp sge i4 [[Z]], 0 +; CHECK-NEXT: [[F_OR_3:%.*]] = or i1 [[F_4]], [[F_5]] +; CHECK-NEXT: [[F_OR_4:%.*]] = or i1 [[F_OR_3]], true +; CHECK-NEXT: call void @use(i1 [[F_OR_4]]) +; CHECK-NEXT: ret void +; +entry: + %1 = or i4 %y, %x + %2 = or i4 %1, %z + %or = icmp slt i4 %2, 0 + br i1 %or, label %bb1, label %exit + +bb1: + %f.1 = icmp slt i4 %x, 0 + %f.2 = icmp slt i4 %y, 0 + %f.3 = icmp slt i4 %z, 0 + %f.or = or i1 %f.1, %f.2 + %f.or.2 = or i1 %f.or, %f.3 + call void @use(i1 %f.or.2) + ret void + +exit: + %f.4 = icmp sge i4 %x, 0 + %f.5 = icmp sge i4 %y, 0 + %f.6 = icmp sge i4 %z, 0 + %f.or.3 = or i1 %f.4, %f.5 + %f.or.4 = or i1 %f.or.3, %f.6 + call void @use(i1 %f.or.4) + ret void +}