Description
Consider a testcase like that:
; ModuleID = 'test.bc'
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-sie-ps5"
; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.smin.i32(i32, i32) #0
; Function Attrs: strictfp
define i32 @baz(i32 %arg, i32 %arg1) local_unnamed_addr #1 {
bb:
%call = call i32 @llvm.smin.i32(i32 %arg, i32 %arg1) #1
%call2 = call i32 @llvm.smin.i32(i32 %arg1, i32 %arg)
%or = or i32 %call2, %call
ret i32 %or
}
attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
attributes #1 = { strictfp }
If you run early-cse test, it triggers the assertion (note: make sure to reproduce with version of the compiler with assertions enabled):
opt.exe -f test.ll --passes=early-cse
opt.exe -f test.ll --passes=early-cse
Assertion failed: Success && "Failed to intersect attributes in callsites that " "passed identical check", file D:\Dev\UPSTREAM\llvm-project\llvm\lib\Transforms\Scalar\EarlyCSE.cpp, line 1312 PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace. Stack dump: 0. Program arguments: opt.exe -f test.ll --passes=early-cse 1. Running pass "function(early-cse<>)" on module "test.ll" 2. Running pass "early-cse<>" on function "baz" Exception Code: 0x80000003 0x00007FF77F8639BC, D:\Dev\Testing\TOOLCHAIN-19080\opt.exe(0x00007FF778600000) + 0x72639BC byte(s)
Here is the analysis why the failure happens.
Function EarlyCSE::processNode determines that these two instructions are common subexpression and one of them could be replaced with another.
%call = call i32 @llvm.smin.i32(i32 %arg, i32 %arg1) #1
%call2 = call i32 @llvm.smin.i32(i32 %arg1, i32 %arg)
attributes #1 ={ strictfp }
The piece of code below determines that these two instructions have the same value.
// See if the instruction has an available value. If so, use it.
if (Value *V = AvailableValues.lookup(&Inst))
However, one of these instructions has 'strictfp' attribute, which signifies that optimizations to libm function calls should be prevented.
I think that because of this attribute is present, these two instructions should have had different values. Hence the bug.
The actual failure happens later in the function combineIRFlags(Inst, V) that is trying to combine attributes for these two function calls.
Function tryIntersectAttributes determines the intersection of attributes for these two function calls. This intersection is empty, so it returns false.
Later, the assertion is triggered.
bool Success =
cast<CallBase>(To)->tryIntersectAttributes(cast<CallBase>(&From));
assert(Success && "Failed to intersect attributes in callsites that "
"passed identical check");