From: Ahmed Bougacha Date: Tue, 7 Mar 2017 20:53:06 +0000 (+0000) Subject: [GlobalISel] Avoid invalidating ValToVReg when translating no-op bitcast. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=12a80e817aafa0f0b11abe6c2c5bc829fcebf947;p=llvm [GlobalISel] Avoid invalidating ValToVReg when translating no-op bitcast. When we translate a no-op (same type) bitcast, we try to be clever and only emit a COPY if we already assigned a vreg to the defined value. However, when we didn't, we tried to assign to a reference into the ValToVReg DenseMap, even though the RHS of the assignment (getOrCreateVReg) could potentially grow that DenseMap, invalidating the reference. Avoid that by getting the source vreg first. I audited the rest of the translator; this is the only tricky case. The test is quite unwieldy, as the problem is caused by the DenseMap growing, which happens after the 47th mapped value. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@297208 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/GlobalISel/IRTranslator.cpp b/lib/CodeGen/GlobalISel/IRTranslator.cpp index 70333057a76..1a70947a4aa 100644 --- a/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ b/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -396,12 +396,17 @@ bool IRTranslator::translateSelect(const User &U, bool IRTranslator::translateBitCast(const User &U, MachineIRBuilder &MIRBuilder) { + // If we're bitcasting to the source type, we can reuse the source vreg. if (LLT{*U.getOperand(0)->getType(), *DL} == LLT{*U.getType(), *DL}) { + // Get the source vreg now, to avoid invalidating ValToVReg. + unsigned SrcReg = getOrCreateVReg(*U.getOperand(0)); unsigned &Reg = ValToVReg[&U]; + // If we already assigned a vreg for this bitcast, we can't change that. + // Emit a copy to satisfy the users we already emitted. if (Reg) - MIRBuilder.buildCopy(Reg, getOrCreateVReg(*U.getOperand(0))); + MIRBuilder.buildCopy(Reg, SrcReg); else - Reg = getOrCreateVReg(*U.getOperand(0)); + Reg = SrcReg; return true; } return translateCast(TargetOpcode::G_BITCAST, U, MIRBuilder); diff --git a/test/CodeGen/AArch64/GlobalISel/irtranslator-bitcast.ll b/test/CodeGen/AArch64/GlobalISel/irtranslator-bitcast.ll new file mode 100644 index 00000000000..8d1b02216ea --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/irtranslator-bitcast.ll @@ -0,0 +1,30 @@ +; RUN: llc -O0 -mtriple=aarch64-apple-ios -global-isel -stop-after=irtranslator %s -o - | FileCheck %s + +; Check that we don't invalidate the vreg map. +; This test is brittle: the invalidation only triggers when we grow the map. + +; CHECK-LABEL: name: test_bitcast_invalid_vreg +define i32 @test_bitcast_invalid_vreg() { + %tmp0 = add i32 1, 2 + %tmp1 = add i32 3, 4 + %tmp2 = add i32 5, 6 + %tmp3 = add i32 7, 8 + %tmp4 = add i32 9, 10 + %tmp5 = add i32 11, 12 + %tmp6 = add i32 13, 14 + %tmp7 = add i32 15, 16 + %tmp8 = add i32 17, 18 + %tmp9 = add i32 19, 20 + %tmp10 = add i32 21, 22 + %tmp11 = add i32 23, 24 + %tmp12 = add i32 25, 26 + %tmp13 = add i32 27, 28 + %tmp14 = add i32 29, 30 + %tmp15 = add i32 30, 30 + +; At this point we mapped 46 values. The 'i32 100' constant will grow the map. +; CHECK: %46(s32) = G_CONSTANT i32 100 +; CHECK: %w0 = COPY %46(s32) + %res = bitcast i32 100 to i32 + ret i32 %res +}