From 95fedfab6cfb82a2fe1010d266b1269425f5eb46 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 2 May 2022 17:52:02 +0200 Subject: [PATCH] [InstCombine] Handle non-canonical GEP index in indexed compare fold (PR55228) Normally the index type will already be canonicalized here, but this is not guaranteed depending on visitation order. The code was already accounting for a potentially needed sext, but a trunc may also be needed. Add a ConstantExpr::getSExtOrTrunc() helper method to make this simpler. This matches the corresponding IRBuilder method in behavior. Fixes https://github.com/llvm/llvm-project/issues/55228. --- llvm/include/llvm/IR/Constants.h | 5 +++++ llvm/lib/IR/Constants.cpp | 11 ++++++++++ .../InstCombine/InstCombineCompares.cpp | 2 +- llvm/test/Transforms/InstCombine/pr55228.ll | 21 +++++++++++++++++++ 4 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 llvm/test/Transforms/InstCombine/pr55228.ll diff --git a/llvm/include/llvm/IR/Constants.h b/llvm/include/llvm/IR/Constants.h index fb884912b318..6c655407cb5e 100644 --- a/llvm/include/llvm/IR/Constants.h +++ b/llvm/include/llvm/IR/Constants.h @@ -1160,6 +1160,11 @@ public: Type *Ty ///< The type to trunc or bitcast C to ); + /// Create either an sext, trunc or nothing, depending on whether Ty is + /// wider, narrower or the same as C->getType(). This only works with + /// integer or vector of integer types. + static Constant *getSExtOrTrunc(Constant *C, Type *Ty); + /// Create a BitCast, AddrSpaceCast, or a PtrToInt cast constant /// expression. static Constant * diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp index 5dcf1bab1dbb..c182513fc1d1 100644 --- a/llvm/lib/IR/Constants.cpp +++ b/llvm/lib/IR/Constants.cpp @@ -2068,6 +2068,17 @@ Constant *ConstantExpr::getTruncOrBitCast(Constant *C, Type *Ty) { return getTrunc(C, Ty); } +Constant *ConstantExpr::getSExtOrTrunc(Constant *C, Type *Ty) { + assert(C->getType()->isIntOrIntVectorTy() && Ty->isIntOrIntVectorTy() && + "Can only sign extend/truncate integers!"); + Type *CTy = C->getType(); + if (CTy->getScalarSizeInBits() < Ty->getScalarSizeInBits()) + return getSExt(C, Ty); + if (CTy->getScalarSizeInBits() > Ty->getScalarSizeInBits()) + return getTrunc(C, Ty); + return C; +} + Constant *ConstantExpr::getPointerCast(Constant *S, Type *Ty) { assert(S->getType()->isPtrOrPtrVectorTy() && "Invalid cast"); assert((Ty->isIntOrIntVectorTy() || Ty->isPtrOrPtrVectorTy()) && diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 4a62afce19be..39a32e526d71 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -759,7 +759,7 @@ getAsConstantIndexedAddress(Type *ElemTy, Value *V, const DataLayout &DL) { V = GEP->getOperand(0); Constant *GEPIndex = static_cast(GEP->getOperand(1)); Index = ConstantExpr::getAdd( - Index, ConstantExpr::getSExtOrBitCast(GEPIndex, IndexType)); + Index, ConstantExpr::getSExtOrTrunc(GEPIndex, IndexType)); continue; } break; diff --git a/llvm/test/Transforms/InstCombine/pr55228.ll b/llvm/test/Transforms/InstCombine/pr55228.ll new file mode 100644 index 000000000000..5ef9f00035da --- /dev/null +++ b/llvm/test/Transforms/InstCombine/pr55228.ll @@ -0,0 +1,21 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -S -instcombine < %s | FileCheck %s + +target datalayout = "p:8:8" + +@g = external global i8 +@c = constant ptr getelementptr inbounds (i8, ptr @g, i64 1) + +define i1 @test(ptr %p) { +; CHECK-LABEL: @test( +; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[P:%.*]], getelementptr inbounds (i8, ptr @g, i8 1) +; CHECK-NEXT: ret i1 [[CMP]] +; + %alloca = alloca ptr + call void @llvm.memcpy.p0.p0.i32(ptr %alloca, ptr @c, i32 0, i1 false) + %load = load ptr, ptr %alloca + %cmp = icmp eq ptr %p, %load + ret i1 %cmp +} + +declare void @llvm.memcpy.p0.p0.i32(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i32, i1 immarg)