From 1c043a9f28629929719c7262c74f837476416d43 Mon Sep 17 00:00:00 2001 From: Bjorn Pettersson Date: Tue, 24 Oct 2017 12:08:11 +0000 Subject: [PATCH] [ConstantFolding] Avoid assert when folding ptrtoint of vectorized GEP Summary: Got asserts in llvm::CastInst::getCastOpcode saying: `DestBits == SrcBits && "Illegal cast to vector (wrong type or size)"' failed. Problem seemed to be that llvm::ConstantFoldCastInstruction did not handle ptrtoint cast of a getelementptr returning a vector correctly. I assume such situations are quite rare, since the GEP needs to be considered as a constant value (base pointer being null). The solution used here is to simply avoid the constant fold of ptrtoint when the value is a vector. It is not supported, and by bailing out we do not fail on assertions later on. Reviewers: craig.topper, majnemer, davide, filcab, efriedma Reviewed By: efriedma Subscribers: efriedma, filcab, llvm-commits Differential Revision: https://reviews.llvm.org/D38546 llvm-svn: 316430 --- llvm/lib/IR/ConstantFold.cpp | 9 +++++++ llvm/test/Analysis/ConstantFolding/cast-vector.ll | 32 +++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 llvm/test/Analysis/ConstantFolding/cast-vector.ll diff --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp index 60dd20e..044cc1f 100644 --- a/llvm/lib/IR/ConstantFold.cpp +++ b/llvm/lib/IR/ConstantFold.cpp @@ -629,6 +629,15 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V, if (ConstantExpr *CE = dyn_cast(V)) if (CE->getOpcode() == Instruction::GetElementPtr && CE->getOperand(0)->isNullValue()) { + // FIXME: Looks like getFoldedSizeOf(), getFoldedOffsetOf() and + // getFoldedAlignOf() don't handle the case when DestTy is a vector of + // pointers yet. We end up in asserts in CastInst::getCastOpcode (see + // test/Analysis/ConstantFolding/cast-vector.ll). I've only seen this + // happen in one "real" C-code test case, so it does not seem to be an + // important optimization to handle vectors here. For now, simply bail + // out. + if (DestTy->isVectorTy()) + return nullptr; GEPOperator *GEPO = cast(CE); Type *Ty = GEPO->getSourceElementType(); if (CE->getNumOperands() == 2) { diff --git a/llvm/test/Analysis/ConstantFolding/cast-vector.ll b/llvm/test/Analysis/ConstantFolding/cast-vector.ll new file mode 100644 index 0000000..1aaf55a --- /dev/null +++ b/llvm/test/Analysis/ConstantFolding/cast-vector.ll @@ -0,0 +1,32 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -instsimplify -S | FileCheck %s + +; Test constant fold of constant expression GEP used by ptrtoint (the +; "offsetof-like expression" case). +; This used to hit an assert due to not supporting vectors in +; llvm::ConstantFoldCastInstruction when handling ptrtoint. +define <2 x i16> @test1() { +; CHECK-LABEL: @test1( +; CHECK-NEXT: entry: +; CHECK-NEXT: ret <2 x i16> ptrtoint (<2 x i32*> getelementptr ([10 x i32], [10 x i32]* null, <2 x i64> zeroinitializer, <2 x i64> ) to <2 x i16>) +; +entry: + %gep = getelementptr inbounds [10 x i32], [10 x i32]* null, i16 0, <2 x i16> + %vec = ptrtoint <2 x i32*> %gep to <2 x i16> + ret <2 x i16> %vec +} + +; Test constant fold of constant expression GEP used by ptrtoint (the +; "sizeof-like expression" case). +; This used to hit an assert due to not supporting vectors in +; llvm::ConstantFoldCastInstruction when handling ptrtoint. +define <2 x i16> @test2() { +; CHECK-LABEL: @test2( +; CHECK-NEXT: entry: +; CHECK-NEXT: ret <2 x i16> ptrtoint (<2 x i32*> getelementptr (i32, i32* null, <2 x i64> ) to <2 x i16>) +; +entry: + %gep = getelementptr i32, i32* null, <2 x i16> + %vec = ptrtoint <2 x i32*> %gep to <2 x i16> + ret <2 x i16> %vec +} -- 2.7.4