From c59d95f6a47c81e0f9eae37625b6ee14022e06a2 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Tue, 26 Apr 2022 13:16:02 +0100 Subject: [PATCH] [ConstraintElimination] Check if const. is small enough before using it Check if the value of a ConstantInt is small enough to be used for solving before calling getSExtValue. Fixes #55085 --- .../Transforms/Scalar/ConstraintElimination.cpp | 29 ++- llvm/test/Transforms/ConstraintElimination/i128.ll | 71 ------ .../ConstraintElimination/large-constant-ints.ll | 283 +++++++++++++++++++++ 3 files changed, 301 insertions(+), 82 deletions(-) delete mode 100644 llvm/test/Transforms/ConstraintElimination/i128.ll create mode 100644 llvm/test/Transforms/ConstraintElimination/large-constant-ints.ll diff --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp index f963114..ba6e4ee 100644 --- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp +++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp @@ -143,13 +143,15 @@ static SmallVector, 4> decompose(Value *V, SmallVector &Preconditions, bool IsSigned) { + auto CanUseSExt = [](ConstantInt *CI) { + const APInt &Val = CI->getValue(); + return Val.sgt(MinSignedConstraintValue) && Val.slt(MaxConstraintValue); + }; // Decompose \p V used with a signed predicate. if (IsSigned) { if (auto *CI = dyn_cast(V)) { - const APInt &Val = CI->getValue(); - if (Val.sle(MinSignedConstraintValue) || Val.sge(MaxConstraintValue)) - return {}; - return {{CI->getSExtValue(), nullptr}}; + if (CanUseSExt(CI)) + return {{CI->getSExtValue(), nullptr}}; } return {{0, nullptr}, {1, V}}; @@ -168,11 +170,13 @@ decompose(Value *V, SmallVector &Preconditions, // If the index is zero-extended, it is guaranteed to be positive. if (match(GEP->getOperand(GEP->getNumOperands() - 1), m_ZExt(m_Value(Op0)))) { - if (match(Op0, m_NUWShl(m_Value(Op1), m_ConstantInt(CI)))) + if (match(Op0, m_NUWShl(m_Value(Op1), m_ConstantInt(CI))) && + CanUseSExt(CI)) return {{0, nullptr}, {1, GEP->getPointerOperand()}, {std::pow(int64_t(2), CI->getSExtValue()), Op1}}; - if (match(Op0, m_NSWAdd(m_Value(Op1), m_ConstantInt(CI)))) + if (match(Op0, m_NSWAdd(m_Value(Op1), m_ConstantInt(CI))) && + CanUseSExt(CI)) return {{CI->getSExtValue(), nullptr}, {1, GEP->getPointerOperand()}, {1, Op1}}; @@ -180,17 +184,19 @@ decompose(Value *V, SmallVector &Preconditions, } if (match(GEP->getOperand(GEP->getNumOperands() - 1), m_ConstantInt(CI)) && - !CI->isNegative()) + !CI->isNegative() && CanUseSExt(CI)) return {{CI->getSExtValue(), nullptr}, {1, GEP->getPointerOperand()}}; SmallVector, 4> Result; if (match(GEP->getOperand(GEP->getNumOperands() - 1), - m_NUWShl(m_Value(Op0), m_ConstantInt(CI)))) + m_NUWShl(m_Value(Op0), m_ConstantInt(CI))) && + CanUseSExt(CI)) Result = {{0, nullptr}, {1, GEP->getPointerOperand()}, {std::pow(int64_t(2), CI->getSExtValue()), Op0}}; else if (match(GEP->getOperand(GEP->getNumOperands() - 1), - m_NSWAdd(m_Value(Op0), m_ConstantInt(CI)))) + m_NSWAdd(m_Value(Op0), m_ConstantInt(CI))) && + CanUseSExt(CI)) Result = {{CI->getSExtValue(), nullptr}, {1, GEP->getPointerOperand()}, {1, Op0}}; @@ -214,7 +220,8 @@ decompose(Value *V, SmallVector &Preconditions, if (match(V, m_NUWAdd(m_Value(Op0), m_ConstantInt(CI))) && !CI->uge(MaxConstraintValue)) return {{CI->getZExtValue(), nullptr}, {1, Op0}}; - if (match(V, m_Add(m_Value(Op0), m_ConstantInt(CI))) && CI->isNegative()) { + if (match(V, m_Add(m_Value(Op0), m_ConstantInt(CI))) && CI->isNegative() && + CanUseSExt(CI)) { Preconditions.emplace_back( CmpInst::ICMP_UGE, Op0, ConstantInt::get(Op0->getType(), CI->getSExtValue() * -1)); @@ -223,7 +230,7 @@ decompose(Value *V, SmallVector &Preconditions, if (match(V, m_NUWAdd(m_Value(Op0), m_Value(Op1)))) return {{0, nullptr}, {1, Op0}, {1, Op1}}; - if (match(V, m_NUWSub(m_Value(Op0), m_ConstantInt(CI)))) + if (match(V, m_NUWSub(m_Value(Op0), m_ConstantInt(CI))) && CanUseSExt(CI)) return {{-1 * CI->getSExtValue(), nullptr}, {1, Op0}}; if (match(V, m_NUWSub(m_Value(Op0), m_Value(Op1)))) return {{0, nullptr}, {1, Op0}, {-1, Op1}}; diff --git a/llvm/test/Transforms/ConstraintElimination/i128.ll b/llvm/test/Transforms/ConstraintElimination/i128.ll deleted file mode 100644 index 8a4b9d8..0000000 --- a/llvm/test/Transforms/ConstraintElimination/i128.ll +++ /dev/null @@ -1,71 +0,0 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s - -declare void @use(i1) - -define void @test_unsigned_too_large(i128 %x) { -; CHECK-LABEL: @test_unsigned_too_large( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[C_1:%.*]] = icmp ule i128 [[X:%.*]], 12345678901234123123123 -; CHECK-NEXT: br i1 [[C_1]], label [[BB1:%.*]], label [[BB2:%.*]] -; CHECK: bb1: -; CHECK-NEXT: [[C_2:%.*]] = icmp ult i128 [[X]], -12345678901234123123123 -; CHECK-NEXT: call void @use(i1 [[C_2]]) -; CHECK-NEXT: [[C_3:%.*]] = icmp uge i128 [[X]], -12345678901234123123123 -; CHECK-NEXT: call void @use(i1 [[C_3]]) -; CHECK-NEXT: [[C_4:%.*]] = icmp uge i128 [[X]], -12345678901234123123123 -; CHECK-NEXT: call void @use(i1 [[C_4]]) -; CHECK-NEXT: ret void -; CHECK: bb2: -; CHECK-NEXT: ret void -; -entry: - %c.1 = icmp ule i128 %x, 12345678901234123123123 - br i1 %c.1, label %bb1, label %bb2 - -bb1: - %c.2 = icmp ult i128 %x, -12345678901234123123123 - call void @use(i1 %c.2) - %c.3 = icmp uge i128 %x, -12345678901234123123123 - call void @use(i1 %c.3) - %c.4 = icmp uge i128 %x, -12345678901234123123123 - call void @use(i1 %c.4) - ret void - -bb2: - ret void -} - - -define void @test_signed_too_large(i128 %x) { -; CHECK-LABEL: @test_signed_too_large( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[C_1:%.*]] = icmp sle i128 [[X:%.*]], 12345678901234123123123 -; CHECK-NEXT: br i1 [[C_1]], label [[BB1:%.*]], label [[BB2:%.*]] -; CHECK: bb1: -; CHECK-NEXT: [[C_2:%.*]] = icmp slt i128 [[X]], -12345678901234123123123 -; CHECK-NEXT: call void @use(i1 [[C_2]]) -; CHECK-NEXT: [[C_3:%.*]] = icmp sge i128 [[X]], -12345678901234123123123 -; CHECK-NEXT: call void @use(i1 [[C_3]]) -; CHECK-NEXT: [[C_4:%.*]] = icmp sge i128 [[X]], -12345678901234123123123 -; CHECK-NEXT: call void @use(i1 [[C_4]]) -; CHECK-NEXT: ret void -; CHECK: bb2: -; CHECK-NEXT: ret void -; -entry: - %c.1 = icmp sle i128 %x, 12345678901234123123123 - br i1 %c.1, label %bb1, label %bb2 - -bb1: - %c.2 = icmp slt i128 %x, -12345678901234123123123 - call void @use(i1 %c.2) - %c.3 = icmp sge i128 %x, -12345678901234123123123 - call void @use(i1 %c.3) - %c.4 = icmp sge i128 %x, -12345678901234123123123 - call void @use(i1 %c.4) - ret void - -bb2: - ret void -} diff --git a/llvm/test/Transforms/ConstraintElimination/large-constant-ints.ll b/llvm/test/Transforms/ConstraintElimination/large-constant-ints.ll new file mode 100644 index 0000000..889edbe --- /dev/null +++ b/llvm/test/Transforms/ConstraintElimination/large-constant-ints.ll @@ -0,0 +1,283 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s + +declare void @use(i1) + +define void @test_unsigned_too_large(i128 %x) { +; CHECK-LABEL: @test_unsigned_too_large( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[C_1:%.*]] = icmp ule i128 [[X:%.*]], 12345678901234123123123 +; CHECK-NEXT: br i1 [[C_1]], label [[BB1:%.*]], label [[BB2:%.*]] +; CHECK: bb1: +; CHECK-NEXT: [[C_2:%.*]] = icmp ult i128 [[X]], -12345678901234123123123 +; CHECK-NEXT: call void @use(i1 [[C_2]]) +; CHECK-NEXT: [[C_3:%.*]] = icmp uge i128 [[X]], -12345678901234123123123 +; CHECK-NEXT: call void @use(i1 [[C_3]]) +; CHECK-NEXT: [[C_4:%.*]] = icmp uge i128 [[X]], -12345678901234123123123 +; CHECK-NEXT: call void @use(i1 [[C_4]]) +; CHECK-NEXT: ret void +; CHECK: bb2: +; CHECK-NEXT: ret void +; +entry: + %c.1 = icmp ule i128 %x, 12345678901234123123123 + br i1 %c.1, label %bb1, label %bb2 + +bb1: + %c.2 = icmp ult i128 %x, -12345678901234123123123 + call void @use(i1 %c.2) + %c.3 = icmp uge i128 %x, -12345678901234123123123 + call void @use(i1 %c.3) + %c.4 = icmp uge i128 %x, -12345678901234123123123 + call void @use(i1 %c.4) + ret void + +bb2: + ret void +} + +define void @test_signed_too_large(i128 %x) { +; CHECK-LABEL: @test_signed_too_large( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[C_1:%.*]] = icmp sle i128 [[X:%.*]], 12345678901234123123123 +; CHECK-NEXT: br i1 [[C_1]], label [[BB1:%.*]], label [[BB2:%.*]] +; CHECK: bb1: +; CHECK-NEXT: [[C_2:%.*]] = icmp slt i128 [[X]], -12345678901234123123123 +; CHECK-NEXT: call void @use(i1 [[C_2]]) +; CHECK-NEXT: [[C_3:%.*]] = icmp sge i128 [[X]], -12345678901234123123123 +; CHECK-NEXT: call void @use(i1 [[C_3]]) +; CHECK-NEXT: [[C_4:%.*]] = icmp sge i128 [[X]], -12345678901234123123123 +; CHECK-NEXT: call void @use(i1 [[C_4]]) +; CHECK-NEXT: ret void +; CHECK: bb2: +; CHECK-NEXT: ret void +; +entry: + %c.1 = icmp sle i128 %x, 12345678901234123123123 + br i1 %c.1, label %bb1, label %bb2 + +bb1: + %c.2 = icmp slt i128 %x, -12345678901234123123123 + call void @use(i1 %c.2) + %c.3 = icmp sge i128 %x, -12345678901234123123123 + call void @use(i1 %c.3) + %c.4 = icmp sge i128 %x, -12345678901234123123123 + call void @use(i1 %c.4) + ret void + +bb2: + ret void +} + +define i1 @add_decomp_i80(i80 %a) { +; CHECK-LABEL: @add_decomp_i80( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[ADD:%.*]] = add nsw i80 [[A:%.*]], -1973801615886922022913 +; CHECK-NEXT: [[C:%.*]] = icmp ult i80 [[ADD]], 1346612317380797267967 +; CHECK-NEXT: br i1 [[C]], label [[THEN:%.*]], label [[ELSE:%.*]] +; CHECK: then: +; CHECK-NEXT: [[ADD_1:%.*]] = add nsw i80 [[A]], -1973801615886922022913 +; CHECK-NEXT: [[C_1:%.*]] = icmp ult i80 [[ADD_1]], 1346612317380797267967 +; CHECK-NEXT: ret i1 [[C_1]] +; CHECK: else: +; CHECK-NEXT: ret i1 false +; +entry: + %add = add nsw i80 %a, -1973801615886922022913 + %c = icmp ult i80 %add, 1346612317380797267967 + br i1 %c, label %then, label %else + +then: + %add.1 = add nsw i80 %a, -1973801615886922022913 + %c.1 = icmp ult i80 %add.1, 1346612317380797267967 + ret i1 %c.1 + +else: + ret i1 false +} + +define i1 @sub_decomp_i80(i80 %a) { +; CHECK-LABEL: @sub_decomp_i80( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[SUB:%.*]] = sub nuw i80 [[A:%.*]], 1973801615886922022913 +; CHECK-NEXT: [[C:%.*]] = icmp ult i80 [[SUB]], 1346612317380797267967 +; CHECK-NEXT: br i1 [[C]], label [[THEN:%.*]], label [[ELSE:%.*]] +; CHECK: then: +; CHECK-NEXT: [[SUB_1:%.*]] = sub nuw i80 [[A]], 1973801615886922022913 +; CHECK-NEXT: [[C_1:%.*]] = icmp ult i80 [[SUB_1]], 1346612317380797267967 +; CHECK-NEXT: ret i1 [[C_1]] +; CHECK: else: +; CHECK-NEXT: ret i1 false +; +entry: + %sub = sub nuw i80 %a, 1973801615886922022913 + %c = icmp ult i80 %sub, 1346612317380797267967 + br i1 %c, label %then, label %else + +then: + %sub.1 = sub nuw i80 %a, 1973801615886922022913 + %c.1 = icmp ult i80 %sub.1, 1346612317380797267967 + ret i1 %c.1 + +else: + ret i1 false +} + +define i1 @gep_decomp_i80(i8* %a) { +; CHECK-LABEL: @gep_decomp_i80( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, i8* [[A:%.*]], i80 1973801615886922022913 +; CHECK-NEXT: [[C:%.*]] = icmp eq i8* [[GEP]], null +; CHECK-NEXT: br i1 [[C]], label [[THEN:%.*]], label [[ELSE:%.*]] +; CHECK: then: +; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds i8, i8* [[A]], i80 1973801615886922022913 +; CHECK-NEXT: [[C_1:%.*]] = icmp eq i8* [[GEP_1]], null +; CHECK-NEXT: ret i1 [[C_1]] +; CHECK: else: +; CHECK-NEXT: ret i1 false +; +entry: + %gep = getelementptr inbounds i8, i8* %a, i80 1973801615886922022913 + %c = icmp eq i8* %gep, null + br i1 %c, label %then, label %else + +then: + %gep.1 = getelementptr inbounds i8, i8* %a, i80 1973801615886922022913 + %c.1 = icmp eq i8* %gep.1, null + ret i1 %c.1 + +else: + ret i1 false +} + +define i1 @gep_zext_shl_decomp_i80(i8* %a, i80 %v) { +; CHECK-LABEL: @gep_zext_shl_decomp_i80( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[SHL:%.*]] = shl nuw i80 [[V:%.*]], 1973801615886922022913 +; CHECK-NEXT: [[EXT:%.*]] = zext i80 [[SHL]] to i128 +; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, i8* [[A:%.*]], i128 [[EXT]] +; CHECK-NEXT: [[C:%.*]] = icmp eq i8* [[GEP]], null +; CHECK-NEXT: br i1 [[C]], label [[THEN:%.*]], label [[ELSE:%.*]] +; CHECK: then: +; CHECK-NEXT: [[SHL_1:%.*]] = shl nuw i80 [[V]], 1973801615886922022913 +; CHECK-NEXT: [[EXT_1:%.*]] = zext i80 [[SHL_1]] to i128 +; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds i8, i8* [[A]], i128 [[EXT_1]] +; CHECK-NEXT: [[C_1:%.*]] = icmp eq i8* [[GEP_1]], null +; CHECK-NEXT: ret i1 [[C_1]] +; CHECK: else: +; CHECK-NEXT: ret i1 false +; +entry: + %shl = shl nuw i80 %v, 1973801615886922022913 + %ext = zext i80 %shl to i128 + %gep = getelementptr inbounds i8, i8* %a, i128 %ext + %c = icmp eq i8* %gep, null + br i1 %c, label %then, label %else + +then: + %shl.1 = shl nuw i80 %v, 1973801615886922022913 + %ext.1 = zext i80 %shl.1 to i128 + %gep.1 = getelementptr inbounds i8, i8* %a, i128 %ext.1 + %c.1 = icmp eq i8* %gep.1, null + ret i1 %c.1 + +else: + ret i1 false +} + +define i1 @gep_zext_add_decomp_i80(i8* %a, i80 %v) { +; CHECK-LABEL: @gep_zext_add_decomp_i80( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[ADD:%.*]] = add nsw i80 [[V:%.*]], 1973801615886922022913 +; CHECK-NEXT: [[EXT:%.*]] = zext i80 [[ADD]] to i128 +; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, i8* [[A:%.*]], i128 [[EXT]] +; CHECK-NEXT: [[C:%.*]] = icmp eq i8* [[GEP]], null +; CHECK-NEXT: br i1 [[C]], label [[THEN:%.*]], label [[ELSE:%.*]] +; CHECK: then: +; CHECK-NEXT: [[ADD_1:%.*]] = add nsw i80 [[V]], 1973801615886922022913 +; CHECK-NEXT: [[EXT_1:%.*]] = zext i80 [[ADD_1]] to i128 +; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds i8, i8* [[A]], i128 [[EXT_1]] +; CHECK-NEXT: [[C_1:%.*]] = icmp eq i8* [[GEP_1]], null +; CHECK-NEXT: ret i1 [[C_1]] +; CHECK: else: +; CHECK-NEXT: ret i1 false +; +entry: + %add = add nsw i80 %v, 1973801615886922022913 + %ext = zext i80 %add to i128 + %gep = getelementptr inbounds i8, i8* %a, i128 %ext + %c = icmp eq i8* %gep, null + br i1 %c, label %then, label %else + +then: + %add.1 = add nsw i80 %v, 1973801615886922022913 + %ext.1 = zext i80 %add.1 to i128 + %gep.1 = getelementptr inbounds i8, i8* %a, i128 %ext.1 + %c.1 = icmp eq i8* %gep.1, null + ret i1 %c.1 + +else: + ret i1 false +} + +define i1 @gep_shl_decomp_i80(i8* %a, i80 %v) { +; CHECK-LABEL: @gep_shl_decomp_i80( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[SHL:%.*]] = shl nuw i80 [[V:%.*]], 1973801615886922022913 +; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, i8* [[A:%.*]], i80 [[SHL]] +; CHECK-NEXT: [[C:%.*]] = icmp eq i8* [[GEP]], null +; CHECK-NEXT: br i1 [[C]], label [[THEN:%.*]], label [[ELSE:%.*]] +; CHECK: then: +; CHECK-NEXT: [[SHL_1:%.*]] = shl nuw i80 [[V]], 1973801615886922022913 +; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds i8, i8* [[A]], i80 [[SHL_1]] +; CHECK-NEXT: [[C_1:%.*]] = icmp eq i8* [[GEP_1]], null +; CHECK-NEXT: ret i1 [[C_1]] +; CHECK: else: +; CHECK-NEXT: ret i1 false +; +entry: + %shl = shl nuw i80 %v, 1973801615886922022913 + %gep = getelementptr inbounds i8, i8* %a, i80 %shl + %c = icmp eq i8* %gep, null + br i1 %c, label %then, label %else + +then: + %shl.1 = shl nuw i80 %v, 1973801615886922022913 + %gep.1 = getelementptr inbounds i8, i8* %a, i80 %shl.1 + %c.1 = icmp eq i8* %gep.1, null + ret i1 %c.1 + +else: + ret i1 false +} + +define i1 @gep_add_decomp_i80(i8* %a, i80 %v) { +; CHECK-LABEL: @gep_add_decomp_i80( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[ADD:%.*]] = add nsw i80 [[V:%.*]], 1973801615886922022913 +; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, i8* [[A:%.*]], i80 [[ADD]] +; CHECK-NEXT: [[C:%.*]] = icmp eq i8* [[GEP]], null +; CHECK-NEXT: br i1 [[C]], label [[THEN:%.*]], label [[ELSE:%.*]] +; CHECK: then: +; CHECK-NEXT: [[ADD_1:%.*]] = add nsw i80 [[V]], 1973801615886922022913 +; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds i8, i8* [[A]], i80 [[ADD_1]] +; CHECK-NEXT: [[C_1:%.*]] = icmp eq i8* [[GEP_1]], null +; CHECK-NEXT: ret i1 [[C_1]] +; CHECK: else: +; CHECK-NEXT: ret i1 false +; +entry: + %add = add nsw i80 %v, 1973801615886922022913 + %gep = getelementptr inbounds i8, i8* %a, i80 %add + %c = icmp eq i8* %gep, null + br i1 %c, label %then, label %else + +then: + %add.1 = add nsw i80 %v, 1973801615886922022913 + %gep.1 = getelementptr inbounds i8, i8* %a, i80 %add.1 + %c.1 = icmp eq i8* %gep.1, null + ret i1 %c.1 + +else: + ret i1 false +} -- 2.7.4