From 289148afcb68b28e155ee87aa5a9efcf75adb444 Mon Sep 17 00:00:00 2001 From: Joe Groff Date: Mon, 14 Jan 2013 19:37:42 +0000 Subject: Fix DenseMap when LLVM_HAS_RVALUE_REFERENCES is defined but equals 0. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172454 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/ADT/DenseMap.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/llvm/ADT/DenseMap.h b/include/llvm/ADT/DenseMap.h index 04912c703c..12cba08a61 100644 --- a/include/llvm/ADT/DenseMap.h +++ b/include/llvm/ADT/DenseMap.h @@ -159,7 +159,7 @@ public: return std::make_pair(iterator(TheBucket, getBucketsEnd(), true), true); } -#ifdef LLVM_HAS_RVALUE_REFERENCES +#if LLVM_HAS_RVALUE_REFERENCES // Inserts key,value pair into the map if the key isn't already in the map. // If the key is already in the map, it returns false and doesn't update the // value. -- cgit v1.2.3-18-g5258 From 3735573343614644ead7a8bae674c312db8b1eb1 Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Mon, 14 Jan 2013 19:41:09 +0000 Subject: [ADT/StringMap] Add a constructor in StringMap that accepts both an initial size and an allocator. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172455 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/ADT/StringMap.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/llvm/ADT/StringMap.h b/include/llvm/ADT/StringMap.h index 0d68d11a12..978ec44303 100644 --- a/include/llvm/ADT/StringMap.h +++ b/include/llvm/ADT/StringMap.h @@ -237,6 +237,9 @@ public: explicit StringMap(AllocatorTy A) : StringMapImpl(static_cast(sizeof(MapEntryTy))), Allocator(A) {} + StringMap(unsigned InitialSize, AllocatorTy A) + : StringMapImpl(InitialSize), Allocator(A) {} + StringMap(const StringMap &RHS) : StringMapImpl(static_cast(sizeof(MapEntryTy))) { assert(RHS.empty() && -- cgit v1.2.3-18-g5258 From eb3ac4518e46ffaea978d40daf2b4b34b13c48dd Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Mon, 14 Jan 2013 20:56:10 +0000 Subject: Fix typo in comment. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172460 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/InstCombine/InstCombineCasts.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Transforms/InstCombine/InstCombineCasts.cpp b/lib/Transforms/InstCombine/InstCombineCasts.cpp index c782032c45..0c0864f2c0 100644 --- a/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ b/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -739,7 +739,7 @@ static bool CanEvaluateZExtd(Value *V, Type *Ty, unsigned &BitsToClear) { } Instruction *InstCombiner::visitZExt(ZExtInst &CI) { - // If this zero extend is only used by a truncate, let the truncate by + // If this zero extend is only used by a truncate, let the truncate be // eliminated before we try to optimize this zext. if (CI.hasOneUse() && isa(CI.use_back())) return 0; -- cgit v1.2.3-18-g5258 From 1ba5769676bb14078ddbdb9760523619726800c0 Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Mon, 14 Jan 2013 21:00:37 +0000 Subject: SCEVExpander fix. RAUW needs to update the InsertedExpressions cache. Note that this bug is only exposed because LTO fails to use TTI. Fixes self-LTO of clang. rdar://13007381. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172462 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Analysis/ScalarEvolutionExpander.h | 4 +- lib/Analysis/ScalarEvolutionExpander.cpp | 5 +- .../LoopStrengthReduce/2013-01-14-ReuseCast.ll | 84 ++++++++++++++++++++++ 3 files changed, 89 insertions(+), 4 deletions(-) create mode 100644 test/Transforms/LoopStrengthReduce/2013-01-14-ReuseCast.ll diff --git a/include/llvm/Analysis/ScalarEvolutionExpander.h b/include/llvm/Analysis/ScalarEvolutionExpander.h index 1708cccf33..00779fc329 100644 --- a/include/llvm/Analysis/ScalarEvolutionExpander.h +++ b/include/llvm/Analysis/ScalarEvolutionExpander.h @@ -40,8 +40,10 @@ namespace llvm { // New instructions receive a name to identifies them with the current pass. const char* IVName; - std::map, AssertingVH > + // InsertedExpressions caches Values for reuse, so must track RAUW. + std::map, TrackingVH > InsertedExpressions; + // InsertedValues only flags inserted instructions so needs no RAUW. std::set > InsertedValues; std::set > InsertedPostIncValues; diff --git a/lib/Analysis/ScalarEvolutionExpander.cpp b/lib/Analysis/ScalarEvolutionExpander.cpp index b87ad75389..fcd7ce272a 100644 --- a/lib/Analysis/ScalarEvolutionExpander.cpp +++ b/lib/Analysis/ScalarEvolutionExpander.cpp @@ -1523,9 +1523,8 @@ Value *SCEVExpander::expand(const SCEV *S) { } // Check to see if we already expanded this here. - std::map, - AssertingVH >::iterator I = - InsertedExpressions.find(std::make_pair(S, InsertPt)); + std::map, TrackingVH >::iterator + I = InsertedExpressions.find(std::make_pair(S, InsertPt)); if (I != InsertedExpressions.end()) return I->second; diff --git a/test/Transforms/LoopStrengthReduce/2013-01-14-ReuseCast.ll b/test/Transforms/LoopStrengthReduce/2013-01-14-ReuseCast.ll new file mode 100644 index 0000000000..8fbddf8ae4 --- /dev/null +++ b/test/Transforms/LoopStrengthReduce/2013-01-14-ReuseCast.ll @@ -0,0 +1,84 @@ +; RUN: opt -loop-reduce -S < %s | FileCheck %s +; +; LTO of clang, which mistakenly uses no TargetLoweringInfo, causes a +; miscompile. ReuseOrCreateCast replace ptrtoint operand with undef. +; Reproducing the miscompile requires no triple, hence no "TTI". +; rdar://13007381 + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" + +; Verify that nothing uses the "dead" ptrtoint from "undef". +; CHECK: @VerifyDiagnosticConsumerTest +; CHECK: bb: +; CHECK: %0 = ptrtoint i8* undef to i64 +; CHECK-NOT: %0 +; CHECK: .lr.ph +; CHECK-NOT: %0 +; CHECK: sub i64 %7, %tmp6 +; CHECK-NOT: %0 +; CHECK: ret void +define void @VerifyDiagnosticConsumerTest() unnamed_addr nounwind uwtable align 2 { +bb: + %tmp3 = call i8* @getCharData() nounwind + %tmp4 = call i8* @getCharData() nounwind + %tmp5 = ptrtoint i8* %tmp4 to i64 + %tmp6 = ptrtoint i8* %tmp3 to i64 + %tmp7 = sub i64 %tmp5, %tmp6 + br i1 undef, label %bb87, label %.preheader + +.preheader: ; preds = %bb10, %bb + br i1 undef, label %_ZNK4llvm9StringRef4findEcm.exit42.thread, label %bb10 + +bb10: ; preds = %.preheader + br i1 undef, label %_ZNK4llvm9StringRef4findEcm.exit42, label %.preheader + +_ZNK4llvm9StringRef4findEcm.exit42: ; preds = %bb10 + br i1 undef, label %_ZNK4llvm9StringRef4findEcm.exit42.thread, label %.lr.ph + +_ZNK4llvm9StringRef4findEcm.exit42.thread: ; preds = %_ZNK4llvm9StringRef4findEcm.exit42, %.preheader + unreachable + +.lr.ph: ; preds = %_ZNK4llvm9StringRef4findEcm.exit42 + br label %bb36 + +_ZNK4llvm9StringRef4findEcm.exit.loopexit: ; preds = %bb63 + %tmp21 = icmp eq i64 %i.0.i, -1 + br i1 %tmp21, label %_ZNK4llvm9StringRef4findEcm.exit._crit_edge, label %bb36 + +_ZNK4llvm9StringRef4findEcm.exit._crit_edge: ; preds = %bb61, %_ZNK4llvm9StringRef4findEcm.exit.loopexit + unreachable + +bb36: ; preds = %_ZNK4llvm9StringRef4findEcm.exit.loopexit, %.lr.ph + %loc.063 = phi i64 [ undef, %.lr.ph ], [ %i.0.i, %_ZNK4llvm9StringRef4findEcm.exit.loopexit ] + switch i8 undef, label %bb57 [ + i8 10, label %bb48 + i8 13, label %bb48 + ] + +bb48: ; preds = %bb36, %bb36 + br label %bb58 + +bb57: ; preds = %bb36 + br label %bb58 + +bb58: ; preds = %bb57, %bb48 + %tmp59 = icmp ugt i64 %tmp7, undef + %tmp60 = select i1 %tmp59, i64 undef, i64 %tmp7 + br label %bb61 + +bb61: ; preds = %bb63, %bb58 + %i.0.i = phi i64 [ %tmp60, %bb58 ], [ %tmp67, %bb63 ] + %tmp62 = icmp eq i64 %i.0.i, %tmp7 + br i1 %tmp62, label %_ZNK4llvm9StringRef4findEcm.exit._crit_edge, label %bb63 + +bb63: ; preds = %bb61 + %tmp64 = getelementptr inbounds i8* %tmp3, i64 %i.0.i + %tmp65 = load i8* %tmp64, align 1 + %tmp67 = add i64 %i.0.i, 1 + br i1 undef, label %_ZNK4llvm9StringRef4findEcm.exit.loopexit, label %bb61 + +bb87: ; preds = %bb + ret void +} + +declare i8* @getCharData() -- cgit v1.2.3-18-g5258 From c8be88ab562412da359f714502e30ff61459efa0 Mon Sep 17 00:00:00 2001 From: David Greene Date: Mon, 14 Jan 2013 21:04:35 +0000 Subject: Fix Casts Use const_cast<> to avoid cast-away-const errors. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172464 91177308-0d34-0410-b5e6-96231b3b80d8 --- unittests/IR/WaymarkTest.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/unittests/IR/WaymarkTest.cpp b/unittests/IR/WaymarkTest.cpp index 69fc4da5a6..1e9807554c 100644 --- a/unittests/IR/WaymarkTest.cpp +++ b/unittests/IR/WaymarkTest.cpp @@ -46,7 +46,8 @@ TEST(WaymarkTest, TwoBit) { Use::initTags(many, many + 8212); for (const Use *U = many, *Ue = many + 8212 - 1; U != Ue; ++U) { - EXPECT_EQ((User*)(Ue + 1), U->getUser()); + EXPECT_EQ(reinterpret_cast(const_cast(Ue + 1)), + U->getUser()); } } -- cgit v1.2.3-18-g5258 From 914d4a76fe0dd7aafb9f06f5af2dcf09c0b87ee7 Mon Sep 17 00:00:00 2001 From: David Greene Date: Mon, 14 Jan 2013 21:04:37 +0000 Subject: Fix Casting Stop a gcc warning about casting away const. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172465 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/IR/Use.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/IR/Use.cpp b/lib/IR/Use.cpp index 481cbab7c2..1d343e8030 100644 --- a/lib/IR/Use.cpp +++ b/lib/IR/Use.cpp @@ -139,7 +139,7 @@ User *Use::getUser() const { const UserRef *ref = reinterpret_cast(End); return ref->getInt() ? ref->getPointer() - : (User*)End; + : reinterpret_cast(const_cast(End)); } } // End llvm namespace -- cgit v1.2.3-18-g5258 From 5a80eefdf7ef9022cd148b9eed16aa3c14b59a56 Mon Sep 17 00:00:00 2001 From: David Greene Date: Mon, 14 Jan 2013 21:04:38 +0000 Subject: Fix More Casts Fix another cast-away-const cast. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172466 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Object/MachOObject.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/Object/MachOObject.cpp b/lib/Object/MachOObject.cpp index a64db1c60f..529bdf97e5 100644 --- a/lib/Object/MachOObject.cpp +++ b/lib/Object/MachOObject.cpp @@ -44,7 +44,8 @@ static void ReadInMemoryStruct(const MachOObject &MOO, } // Check whether we can return a direct pointer. - struct_type *Ptr = (struct_type *) (Buffer.data() + Base); + struct_type *Ptr = reinterpret_cast( + const_cast(Buffer.data() + Base)); if (!MOO.isSwappedEndian()) { Res = Ptr; return; -- cgit v1.2.3-18-g5258 From 4ee576fac3a84553c9342faea87ff0e13e8eb48d Mon Sep 17 00:00:00 2001 From: David Greene Date: Mon, 14 Jan 2013 21:04:40 +0000 Subject: Fix Casting Bug Add a const version of getFpValPtr to avoid a cast-away-const warning. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172467 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/InstCombine/InstCombineAddSub.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/lib/Transforms/InstCombine/InstCombineAddSub.cpp index f07c58d7d0..03be8ef6fb 100644 --- a/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -66,10 +66,12 @@ namespace { bool insaneIntVal(int V) { return V > 4 || V < -4; } APFloat *getFpValPtr(void) { return reinterpret_cast(&FpValBuf.buffer[0]); } + const APFloat *getFpValPtr(void) const + { return reinterpret_cast(&FpValBuf.buffer[0]); } const APFloat &getFpVal(void) const { assert(IsFp && BufHasFpVal && "Incorret state"); - return *reinterpret_cast(&FpValBuf.buffer[0]); + return *getFpValPtr(); } APFloat &getFpVal(void) -- cgit v1.2.3-18-g5258 From ef44c353599e0e2fd5b2ec2ae5d9bc0e2a355cad Mon Sep 17 00:00:00 2001 From: David Greene Date: Mon, 14 Jan 2013 21:04:42 +0000 Subject: Fix Another Cast Properly cast code to eliminate cast-away-const errors. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172468 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Hexagon/HexagonISelLowering.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/Target/Hexagon/HexagonISelLowering.cpp b/lib/Target/Hexagon/HexagonISelLowering.cpp index 16cec5cfe5..4c27d356bd 100644 --- a/lib/Target/Hexagon/HexagonISelLowering.cpp +++ b/lib/Target/Hexagon/HexagonISelLowering.cpp @@ -1017,7 +1017,8 @@ SDValue HexagonTargetLowering::LowerGLOBALADDRESS(SDValue Op, Result = DAG.getTargetGlobalAddress(GV, dl, getPointerTy(), Offset); HexagonTargetObjectFile &TLOF = - (HexagonTargetObjectFile&)getObjFileLowering(); + static_cast( + const_cast(getObjFileLowering())); if (TLOF.IsGlobalInSmallSection(GV, getTargetMachine())) { return DAG.getNode(HexagonISD::CONST32_GP, dl, getPointerTy(), Result); } -- cgit v1.2.3-18-g5258 From fe1215ef935f182cdca28b4af655fa0bfa0f47e6 Mon Sep 17 00:00:00 2001 From: David Greene Date: Mon, 14 Jan 2013 21:04:44 +0000 Subject: Fix More Casts Properly cast some more code that triggered cast-away-const errors. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172469 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/ExecutionEngine/JIT/JITMemoryManager.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/ExecutionEngine/JIT/JITMemoryManager.cpp b/lib/ExecutionEngine/JIT/JITMemoryManager.cpp index 353bebf84a..66aeb772dd 100644 --- a/lib/ExecutionEngine/JIT/JITMemoryManager.cpp +++ b/lib/ExecutionEngine/JIT/JITMemoryManager.cpp @@ -72,15 +72,20 @@ namespace { /// getBlockAfter - Return the memory block immediately after this one. /// MemoryRangeHeader &getBlockAfter() const { - return *(MemoryRangeHeader*)((char*)this+BlockSize); + return *reinterpret_cast( + reinterpret_cast( + const_cast(this))+BlockSize); } /// getFreeBlockBefore - If the block before this one is free, return it, /// otherwise return null. FreeRangeHeader *getFreeBlockBefore() const { if (PrevAllocated) return 0; - intptr_t PrevSize = ((intptr_t *)this)[-1]; - return (FreeRangeHeader*)((char*)this-PrevSize); + intptr_t PrevSize = reinterpret_cast( + const_cast(this))[-1]; + return reinterpret_cast( + reinterpret_cast( + const_cast(this))-PrevSize); } /// FreeBlock - Turn an allocated block into a free block, adjusting -- cgit v1.2.3-18-g5258 From c2680bef3b4994017d83293bc1337b26be54ac77 Mon Sep 17 00:00:00 2001 From: David Greene Date: Mon, 14 Jan 2013 21:04:45 +0000 Subject: Fix Casting Do proper casting to eliminate a const-away-cast compiler warning. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172470 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/ExecutionEngine/ExecutionEngine.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp index ef5f589896..6f71ffb2fa 100644 --- a/lib/ExecutionEngine/ExecutionEngine.cpp +++ b/lib/ExecutionEngine/ExecutionEngine.cpp @@ -893,7 +893,8 @@ void ExecutionEngine::StoreValueToMemory(const GenericValue &Val, /// from Src into IntVal, which is assumed to be wide enough and to hold zero. static void LoadIntFromMemory(APInt &IntVal, uint8_t *Src, unsigned LoadBytes) { assert((IntVal.getBitWidth()+7)/8 >= LoadBytes && "Integer too small!"); - uint8_t *Dst = (uint8_t *)IntVal.getRawData(); + uint8_t *Dst = reinterpret_cast( + const_cast(IntVal.getRawData())); if (sys::isLittleEndianHost()) // Little-endian host - the destination must be ordered from LSB to MSB. -- cgit v1.2.3-18-g5258 From b398cae1e501069c48456a4bfdf8bbf549aa9746 Mon Sep 17 00:00:00 2001 From: David Greene Date: Mon, 14 Jan 2013 21:04:47 +0000 Subject: Fix Casting Fix a casting-away-const compiler warning. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172471 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Mips/MipsCodeEmitter.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/Target/Mips/MipsCodeEmitter.cpp b/lib/Target/Mips/MipsCodeEmitter.cpp index 52fa95b182..8efcd3c9c8 100644 --- a/lib/Target/Mips/MipsCodeEmitter.cpp +++ b/lib/Target/Mips/MipsCodeEmitter.cpp @@ -120,7 +120,8 @@ class MipsCodeEmitter : public MachineFunctionPass { char MipsCodeEmitter::ID = 0; bool MipsCodeEmitter::runOnMachineFunction(MachineFunction &MF) { - JTI = ((MipsTargetMachine&) MF.getTarget()).getJITInfo(); + JTI = const_cast( + static_cast(MF.getTarget())).getJITInfo(); II = ((const MipsTargetMachine&) MF.getTarget()).getInstrInfo(); TD = ((const MipsTargetMachine&) MF.getTarget()).getDataLayout(); Subtarget = &TM.getSubtarget (); -- cgit v1.2.3-18-g5258 From 398db9368d72d1d60d40b2e18c16ca2c14aa7f39 Mon Sep 17 00:00:00 2001 From: Quentin Colombet Date: Mon, 14 Jan 2013 21:07:43 +0000 Subject: Complete the existing support of ARM v6m, v7m, and v7em, i.e., respectively cortex-m0, cortex-m3, and cortex-m4 on the backend side. Adds new subtype values for the MachO format and use them when the related triple are set. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172472 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/MachOFormat.h | 5 ++++- lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp | 9 +++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/include/llvm/Object/MachOFormat.h b/include/llvm/Object/MachOFormat.h index a17d58dae2..001cb6540a 100644 --- a/include/llvm/Object/MachOFormat.h +++ b/include/llvm/Object/MachOFormat.h @@ -64,7 +64,10 @@ namespace mach { CSARM_V7 = 9, CSARM_V7F = 10, CSARM_V7S = 11, - CSARM_V7K = 12 + CSARM_V7K = 12, + CSARM_V6M = 14, + CSARM_V7M = 15, + CSARM_V7EM = 16 }; /// \brief PowerPC Machine Subtypes. diff --git a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp index 1f1b334ea4..415dee3121 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp @@ -672,12 +672,21 @@ MCAsmBackend *llvm::createARMAsmBackend(const Target &T, StringRef TT, StringRef else if (TheTriple.getArchName() == "armv6" || TheTriple.getArchName() == "thumbv6") return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V6); + else if (TheTriple.getArchName() == "armv6m" || + TheTriple.getArchName() == "thumbv6m") + return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V6M); + else if (TheTriple.getArchName() == "armv7em" || + TheTriple.getArchName() == "thumbv7em") + return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V7EM); else if (TheTriple.getArchName() == "armv7f" || TheTriple.getArchName() == "thumbv7f") return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V7F); else if (TheTriple.getArchName() == "armv7k" || TheTriple.getArchName() == "thumbv7k") return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V7K); + else if (TheTriple.getArchName() == "armv7m" || + TheTriple.getArchName() == "thumbv7m") + return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V7M); else if (TheTriple.getArchName() == "armv7s" || TheTriple.getArchName() == "thumbv7s") return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V7S); -- cgit v1.2.3-18-g5258 From 31659fa066b00afeea38d36ba87b531a4d7313d7 Mon Sep 17 00:00:00 2001 From: Dmitri Gribenko Date: Mon, 14 Jan 2013 21:23:37 +0000 Subject: Improve r172464: const_cast is not needed if the variable is not const git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172474 91177308-0d34-0410-b5e6-96231b3b80d8 --- unittests/IR/WaymarkTest.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/unittests/IR/WaymarkTest.cpp b/unittests/IR/WaymarkTest.cpp index 1e9807554c..0fe0a431b2 100644 --- a/unittests/IR/WaymarkTest.cpp +++ b/unittests/IR/WaymarkTest.cpp @@ -44,10 +44,9 @@ TEST(WaymarkTest, TwoBit) { Use* many = (Use*)calloc(sizeof(Use), 8212 + 1); ASSERT_TRUE(many); Use::initTags(many, many + 8212); - for (const Use *U = many, *Ue = many + 8212 - 1; U != Ue; ++U) + for (Use *U = many, *Ue = many + 8212 - 1; U != Ue; ++U) { - EXPECT_EQ(reinterpret_cast(const_cast(Ue + 1)), - U->getUser()); + EXPECT_EQ(reinterpret_cast(Ue + 1), U->getUser()); } } -- cgit v1.2.3-18-g5258 From 19d54337169ae4af2d44ae39664d0bac1ae0309c Mon Sep 17 00:00:00 2001 From: Quentin Colombet Date: Mon, 14 Jan 2013 21:34:09 +0000 Subject: Follow up of commit r172472. Refactor the big if/else sequence into one string switch for ARM subtype selection. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172475 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp | 43 ++++++++++----------------- 1 file changed, 15 insertions(+), 28 deletions(-) diff --git a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp index 415dee3121..e66e985678 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp @@ -11,6 +11,7 @@ #include "MCTargetDesc/ARMAddressingModes.h" #include "MCTargetDesc/ARMBaseInfo.h" #include "MCTargetDesc/ARMFixupKinds.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCContext.h" @@ -663,34 +664,20 @@ MCAsmBackend *llvm::createARMAsmBackend(const Target &T, StringRef TT, StringRef Triple TheTriple(TT); if (TheTriple.isOSDarwin()) { - if (TheTriple.getArchName() == "armv4t" || - TheTriple.getArchName() == "thumbv4t") - return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V4T); - else if (TheTriple.getArchName() == "armv5e" || - TheTriple.getArchName() == "thumbv5e") - return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V5TEJ); - else if (TheTriple.getArchName() == "armv6" || - TheTriple.getArchName() == "thumbv6") - return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V6); - else if (TheTriple.getArchName() == "armv6m" || - TheTriple.getArchName() == "thumbv6m") - return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V6M); - else if (TheTriple.getArchName() == "armv7em" || - TheTriple.getArchName() == "thumbv7em") - return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V7EM); - else if (TheTriple.getArchName() == "armv7f" || - TheTriple.getArchName() == "thumbv7f") - return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V7F); - else if (TheTriple.getArchName() == "armv7k" || - TheTriple.getArchName() == "thumbv7k") - return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V7K); - else if (TheTriple.getArchName() == "armv7m" || - TheTriple.getArchName() == "thumbv7m") - return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V7M); - else if (TheTriple.getArchName() == "armv7s" || - TheTriple.getArchName() == "thumbv7s") - return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V7S); - return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V7); + object::mach::CPUSubtypeARM CS = + StringSwitch(TheTriple.getArchName()) + .Cases("armv4t", "thumbv4t", object::mach::CSARM_V4T) + .Cases("armv5e", "thumbv5e",object::mach::CSARM_V5TEJ) + .Cases("armv6", "thumbv6", object::mach::CSARM_V6) + .Cases("armv6m", "thumbv6m", object::mach::CSARM_V6M) + .Cases("armv7em", "thumbv7em", object::mach::CSARM_V7EM) + .Cases("armv7f", "thumbv7f", object::mach::CSARM_V7F) + .Cases("armv7k", "thumbv7k", object::mach::CSARM_V7K) + .Cases("armv7m", "thumbv7m", object::mach::CSARM_V7M) + .Cases("armv7s", "thumbv7s", object::mach::CSARM_V7S) + .Default(object::mach::CSARM_V7); + + return new DarwinARMAsmBackend(T, TT, CS); } if (TheTriple.isOSWindows()) -- cgit v1.2.3-18-g5258 From 89e88e30bff4a5f4303dc9e44d3faa89b81af5a8 Mon Sep 17 00:00:00 2001 From: Bill Schmidt Date: Mon, 14 Jan 2013 22:04:38 +0000 Subject: This patch addresses an incorrect transformation in the DAG combiner. The included test case is derived from one of the GCC compatibility tests. The problem arises after the selection DAG has been converted to type-legalized form. The combiner first sees a 64-bit load that can be converted into a pre-increment form. The original load feeds into a SRL that isolates the upper 32 bits of the loaded doubleword. This looks like an opportunity for DAGCombiner::ReduceLoadWidth() to replace the 64-bit load with a 32-bit load. However, this transformation is not valid, as the replacement load is not a pre-increment load. The pre-increment load produces an extra result, which feeds a subsequent add instruction. The replacement load only has one result value, and this value is propagated to all uses of the pre- increment load, including the add. Because the add is looking for the second result value as its operand, it ends up attempting to add a constant to a token chain, resulting in a crash. So the patch simply disables this transformation for any load with more than two result values. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172480 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 20 +++++++++++++----- test/CodeGen/PowerPC/load-shift-combine.ll | 34 ++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 test/CodeGen/PowerPC/load-shift-combine.ll diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 359c4cf8e4..a82410ae6a 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -5100,16 +5100,26 @@ SDValue DAGCombiner::ReduceLoadWidth(SDNode *N) { // If we haven't found a load, we can't narrow it. Don't transform one with // multiple uses, this would require adding a new load. - if (!isa(N0) || !N0.hasOneUse() || - // Don't change the width of a volatile load. - cast(N0)->isVolatile()) + if (!isa(N0) || !N0.hasOneUse()) + return SDValue(); + + // Don't change the width of a volatile load. + LoadSDNode *LN0 = cast(N0); + if (LN0->isVolatile()) return SDValue(); // Verify that we are actually reducing a load width here. - if (cast(N0)->getMemoryVT().getSizeInBits() < EVTBits) + if (LN0->getMemoryVT().getSizeInBits() < EVTBits) + return SDValue(); + + // For the transform to be legal, the load must produce only two values + // (the value loaded and the chain). Don't transform a pre-increment + // load, for example, which produces an extra value. Otherwise the + // transformation is not equivalent, and the downstream logic to replace + // uses gets things wrong. + if (LN0->getNumValues() > 2) return SDValue(); - LoadSDNode *LN0 = cast(N0); EVT PtrType = N0.getOperand(1).getValueType(); if (PtrType == MVT::Untyped || PtrType.isExtended()) diff --git a/test/CodeGen/PowerPC/load-shift-combine.ll b/test/CodeGen/PowerPC/load-shift-combine.ll new file mode 100644 index 0000000000..a5d1224864 --- /dev/null +++ b/test/CodeGen/PowerPC/load-shift-combine.ll @@ -0,0 +1,34 @@ +; RUN: llc < %s + +; This used to cause a crash. A standard load is converted to a pre-increment +; load. Later the pre-increment load is combined with a subsequent SRL to +; produce a smaller load. This transform invalidly created a standard load +; and propagated the produced value into uses of both produced values of the +; pre-increment load. The result was a crash when attempting to process an +; add with a token-chain operand. + +%struct.Info = type { i32, i32, i8*, i8*, i8*, [32 x i8*], i64, [32 x i64], i64, i64, i64, [32 x i64] } +%struct.S1847 = type { [12 x i8], [4 x i8], [8 x i8], [4 x i8], [8 x i8], [2 x i8], i8, [4 x i64], i8, [3 x i8], [4 x i8], i8, i16, [4 x %struct.anon.76], i16, i8, i8* } +%struct.anon.76 = type { i32 } +@info = common global %struct.Info zeroinitializer, align 8 +@fails = common global i32 0, align 4 +@a1847 = external global [5 x %struct.S1847] +define void @test1847() nounwind { +entry: + %j = alloca i32, align 4 + %0 = load i64* getelementptr inbounds (%struct.Info* @info, i32 0, i32 8), align 8 + %1 = load i32* @fails, align 4 + %bf.load1 = load i96* bitcast (%struct.S1847* getelementptr inbounds ([5 x %struct.S1847]* @a1847, i32 0, i64 2) to i96*), align 8 + %bf.clear2 = and i96 %bf.load1, 302231454903657293676543 + %bf.set3 = or i96 %bf.clear2, -38383394772764476296921088 + store i96 %bf.set3, i96* bitcast (%struct.S1847* getelementptr inbounds ([5 x %struct.S1847]* @a1847, i32 0, i64 2) to i96*), align 8 + %2 = load i32* %j, align 4 + %3 = load i32* %j, align 4 + %inc11 = add nsw i32 %3, 1 + store i32 %inc11, i32* %j, align 4 + %bf.load15 = load i96* bitcast (%struct.S1847* getelementptr inbounds ([5 x %struct.S1847]* @a1847, i32 0, i64 2) to i96*), align 8 + %bf.clear16 = and i96 %bf.load15, -18446744069414584321 + %bf.set17 = or i96 %bf.clear16, 18446743532543672320 + store i96 %bf.set17, i96* bitcast (%struct.S1847* getelementptr inbounds ([5 x %struct.S1847]* @a1847, i32 0, i64 2) to i96*), align 8 + ret void +} -- cgit v1.2.3-18-g5258 From 953cbfcd26fa59d80c8d9ca749b5dd8ef901d11a Mon Sep 17 00:00:00 2001 From: Dmitri Gribenko Date: Mon, 14 Jan 2013 22:08:37 +0000 Subject: Improve r172471: avoid all those extra casts on the lines nearby git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172481 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Mips/MipsCodeEmitter.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/Target/Mips/MipsCodeEmitter.cpp b/lib/Target/Mips/MipsCodeEmitter.cpp index 8efcd3c9c8..a24de60cd9 100644 --- a/lib/Target/Mips/MipsCodeEmitter.cpp +++ b/lib/Target/Mips/MipsCodeEmitter.cpp @@ -120,10 +120,12 @@ class MipsCodeEmitter : public MachineFunctionPass { char MipsCodeEmitter::ID = 0; bool MipsCodeEmitter::runOnMachineFunction(MachineFunction &MF) { - JTI = const_cast( - static_cast(MF.getTarget())).getJITInfo(); - II = ((const MipsTargetMachine&) MF.getTarget()).getInstrInfo(); - TD = ((const MipsTargetMachine&) MF.getTarget()).getDataLayout(); + MipsTargetMachine &Target = static_cast( + const_cast(MF.getTarget())); + + JTI = Target.getJITInfo(); + II = Target.getInstrInfo(); + TD = Target.getDataLayout(); Subtarget = &TM.getSubtarget (); MCPEs = &MF.getConstantPool()->getConstants(); MJTEs = 0; -- cgit v1.2.3-18-g5258 From 510db8bcb959fa69a93c42b58cb3e0ab28d03825 Mon Sep 17 00:00:00 2001 From: Dmitri Gribenko Date: Mon, 14 Jan 2013 22:18:18 +0000 Subject: Improve r172468: const_cast is not needed here git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172483 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Hexagon/HexagonISelLowering.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/Target/Hexagon/HexagonISelLowering.cpp b/lib/Target/Hexagon/HexagonISelLowering.cpp index 4c27d356bd..1a0e581051 100644 --- a/lib/Target/Hexagon/HexagonISelLowering.cpp +++ b/lib/Target/Hexagon/HexagonISelLowering.cpp @@ -1016,9 +1016,8 @@ SDValue HexagonTargetLowering::LowerGLOBALADDRESS(SDValue Op, DebugLoc dl = Op.getDebugLoc(); Result = DAG.getTargetGlobalAddress(GV, dl, getPointerTy(), Offset); - HexagonTargetObjectFile &TLOF = - static_cast( - const_cast(getObjFileLowering())); + const HexagonTargetObjectFile &TLOF = + static_cast(getObjFileLowering()); if (TLOF.IsGlobalInSmallSection(GV, getTargetMachine())) { return DAG.getNode(HexagonISD::CONST32_GP, dl, getPointerTy(), Result); } -- cgit v1.2.3-18-g5258 From dd2e8950222ab74157b1c083ffa77b0fbaf1d210 Mon Sep 17 00:00:00 2001 From: Chad Rosier Date: Mon, 14 Jan 2013 22:31:35 +0000 Subject: [ms-inline asm] Extend support for parsing Intel bracketed memory operands that have an arbitrary ordering of the base register, index register and displacement. rdar://12527141 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172484 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/AsmParser/X86AsmParser.cpp | 363 +++++++++++++++++++++++------- test/MC/X86/intel-syntax.s | 200 +++++++++++++++- 2 files changed, 468 insertions(+), 95 deletions(-) diff --git a/lib/Target/X86/AsmParser/X86AsmParser.cpp b/lib/Target/X86/AsmParser/X86AsmParser.cpp index 5ce258ed0f..05bb1e37e5 100644 --- a/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -684,115 +684,298 @@ static unsigned getIntelMemOperandSize(StringRef OpStr) { return Size; } +enum IntelBracExprState { + IBES_START, + IBES_LBRAC, + IBES_RBRAC, + IBES_REGISTER, + IBES_REGISTER_STAR, + IBES_REGISTER_STAR_INTEGER, + IBES_INTEGER, + IBES_INTEGER_STAR, + IBES_INDEX_REGISTER, + IBES_IDENTIFIER, + IBES_DISP_EXPR, + IBES_MINUS, + IBES_ERROR +}; + +class IntelBracExprStateMachine { + IntelBracExprState State; + unsigned BaseReg, IndexReg, Scale; + int64_t Disp; + + unsigned TmpReg; + int64_t TmpInteger; + + bool isPlus; + +public: + IntelBracExprStateMachine(MCAsmParser &parser) : + State(IBES_START), BaseReg(0), IndexReg(0), Scale(1), Disp(0), + TmpReg(0), TmpInteger(0), isPlus(true) {} + + unsigned getBaseReg() { return BaseReg; } + unsigned getIndexReg() { return IndexReg; } + unsigned getScale() { return Scale; } + int64_t getDisp() { return Disp; } + bool isValidEndState() { return State == IBES_RBRAC; } + + void onPlus() { + switch (State) { + default: + State = IBES_ERROR; + break; + case IBES_INTEGER: + State = IBES_START; + if (isPlus) + Disp += TmpInteger; + else + Disp -= TmpInteger; + break; + case IBES_REGISTER: + State = IBES_START; + // If we already have a BaseReg, then assume this is the IndexReg with a + // scale of 1. + if (!BaseReg) { + BaseReg = TmpReg; + } else { + assert (!IndexReg && "BaseReg/IndexReg already set!"); + IndexReg = TmpReg; + Scale = 1; + } + break; + case IBES_INDEX_REGISTER: + State = IBES_START; + break; + } + isPlus = true; + } + void onMinus() { + switch (State) { + default: + State = IBES_ERROR; + break; + case IBES_START: + State = IBES_MINUS; + break; + case IBES_INTEGER: + State = IBES_START; + if (isPlus) + Disp += TmpInteger; + else + Disp -= TmpInteger; + break; + case IBES_REGISTER: + State = IBES_START; + // If we already have a BaseReg, then assume this is the IndexReg with a + // scale of 1. + if (!BaseReg) { + BaseReg = TmpReg; + } else { + assert (!IndexReg && "BaseReg/IndexReg already set!"); + IndexReg = TmpReg; + Scale = 1; + } + break; + case IBES_INDEX_REGISTER: + State = IBES_START; + break; + } + isPlus = false; + } + void onRegister(unsigned Reg) { + switch (State) { + default: + State = IBES_ERROR; + break; + case IBES_START: + State = IBES_REGISTER; + TmpReg = Reg; + break; + case IBES_INTEGER_STAR: + assert (!IndexReg && "IndexReg already set!"); + State = IBES_INDEX_REGISTER; + IndexReg = Reg; + Scale = TmpInteger; + break; + } + } + void onDispExpr() { + switch (State) { + default: + State = IBES_ERROR; + break; + case IBES_START: + State = IBES_DISP_EXPR; + break; + } + } + void onInteger(int64_t TmpInt) { + switch (State) { + default: + State = IBES_ERROR; + break; + case IBES_START: + State = IBES_INTEGER; + TmpInteger = TmpInt; + break; + case IBES_MINUS: + State = IBES_INTEGER; + TmpInteger = TmpInt; + break; + case IBES_REGISTER_STAR: + assert (!IndexReg && "IndexReg already set!"); + State = IBES_INDEX_REGISTER; + IndexReg = TmpReg; + Scale = TmpInt; + break; + } + } + void onStar() { + switch (State) { + default: + State = IBES_ERROR; + break; + case IBES_INTEGER: + State = IBES_INTEGER_STAR; + break; + case IBES_REGISTER: + State = IBES_REGISTER_STAR; + break; + } + } + void onLBrac() { + switch (State) { + default: + State = IBES_ERROR; + break; + case IBES_RBRAC: + State = IBES_START; + isPlus = true; + break; + } + } + void onRBrac() { + switch (State) { + default: + State = IBES_ERROR; + break; + case IBES_DISP_EXPR: + State = IBES_RBRAC; + break; + case IBES_INTEGER: + State = IBES_RBRAC; + if (isPlus) + Disp += TmpInteger; + else + Disp -= TmpInteger; + break; + case IBES_REGISTER: + State = IBES_RBRAC; + // If we already have a BaseReg, then assume this is the IndexReg with a + // scale of 1. + if (!BaseReg) { + BaseReg = TmpReg; + } else { + assert (!IndexReg && "BaseReg/IndexReg already set!"); + IndexReg = TmpReg; + Scale = 1; + } + break; + case IBES_INDEX_REGISTER: + State = IBES_RBRAC; + break; + } + } +}; + X86Operand *X86AsmParser::ParseIntelBracExpression(unsigned SegReg, unsigned Size) { - unsigned BaseReg = 0, IndexReg = 0, Scale = 1; const AsmToken &Tok = Parser.getTok(); SMLoc Start = Tok.getLoc(), End = Tok.getEndLoc(); - const MCExpr *Disp = MCConstantExpr::Create(0, getContext()); - // Parse [ BaseReg + Scale*IndexReg + Disp ] or [ symbol ] - // Eat '[' if (getLexer().isNot(AsmToken::LBrac)) return ErrorOperand(Start, "Expected '[' token!"); Parser.Lex(); + unsigned TmpReg = 0; + + // Try to handle '[' 'symbol' ']' if (getLexer().is(AsmToken::Identifier)) { - // Parse BaseReg - if (ParseRegister(BaseReg, Start, End)) { - // Handle '[' 'symbol' ']' - if (getParser().ParseExpression(Disp, End)) return 0; + if (ParseRegister(TmpReg, Start, End)) { + const MCExpr *Disp; + if (getParser().ParseExpression(Disp, End)) + return 0; + if (getLexer().isNot(AsmToken::RBrac)) return ErrorOperand(Parser.getTok().getLoc(), "Expected ']' token!"); End = Parser.getTok().getEndLoc(); Parser.Lex(); return X86Operand::CreateMem(Disp, Start, End, Size); } - } else if (getLexer().is(AsmToken::Integer)) { - int64_t Val = Tok.getIntVal(); - Parser.Lex(); - SMLoc Loc = Tok.getLoc(); - if (getLexer().is(AsmToken::RBrac)) { - // Handle '[' number ']' - End = Parser.getTok().getEndLoc(); - Parser.Lex(); - const MCExpr *Disp = MCConstantExpr::Create(Val, getContext()); - if (SegReg) - return X86Operand::CreateMem(SegReg, Disp, 0, 0, Scale, - Start, End, Size); - return X86Operand::CreateMem(Disp, Start, End, Size); - } else if (getLexer().is(AsmToken::Star)) { - // Handle '[' Scale*IndexReg ']' - Parser.Lex(); - SMLoc IdxRegLoc = Tok.getLoc(); - if (ParseRegister(IndexReg, IdxRegLoc, End)) - return ErrorOperand(IdxRegLoc, "Expected register"); - Scale = Val; - } else - return ErrorOperand(Loc, "Unexpected token"); } - // Parse ][ as a plus. - bool ExpectRBrac = true; - if (getLexer().is(AsmToken::RBrac)) { - ExpectRBrac = false; - End = Parser.getTok().getEndLoc(); - Parser.Lex(); - } + // Parse [ BaseReg + Scale*IndexReg + Disp ]. + bool Done = false; + IntelBracExprStateMachine SM(Parser); + + // If we parsed a register, then the end loc has already been set and + // the identifier has already been lexed. We also need to update the + // state. + if (TmpReg) + SM.onRegister(TmpReg); + + const MCExpr *Disp = 0; + while (!Done) { + bool UpdateLocLex = true; - if (getLexer().is(AsmToken::Plus) || getLexer().is(AsmToken::Minus) || - getLexer().is(AsmToken::LBrac)) { - ExpectRBrac = true; - bool isPlus = getLexer().is(AsmToken::Plus) || - getLexer().is(AsmToken::LBrac); - Parser.Lex(); - SMLoc PlusLoc = Tok.getLoc(); - if (getLexer().is(AsmToken::Integer)) { + // The period in the dot operator (e.g., [ebx].foo.bar) is parsed as an + // identifier. Don't try an parse it as a register. + if (Tok.getString().startswith(".")) + break; + + switch (getLexer().getKind()) { + default: { + if (SM.isValidEndState()) { + Done = true; + break; + } + return ErrorOperand(Tok.getLoc(), "Unexpected token!"); + } + case AsmToken::Identifier: { + // This could be a register or a displacement expression. + if(!ParseRegister(TmpReg, Start, End)) { + SM.onRegister(TmpReg); + UpdateLocLex = false; + break; + } else if (!getParser().ParseExpression(Disp, End)) { + SM.onDispExpr(); + UpdateLocLex = false; + break; + } + return ErrorOperand(Tok.getLoc(), "Unexpected identifier!"); + } + case AsmToken::Integer: { int64_t Val = Tok.getIntVal(); - Parser.Lex(); - if (getLexer().is(AsmToken::Star)) { - Parser.Lex(); - SMLoc IdxRegLoc = Tok.getLoc(); - if (ParseRegister(IndexReg, IdxRegLoc, End)) - return ErrorOperand(IdxRegLoc, "Expected register"); - Scale = Val; - } else if (getLexer().is(AsmToken::RBrac)) { - const MCExpr *ValExpr = MCConstantExpr::Create(Val, getContext()); - Disp = isPlus ? ValExpr : MCConstantExpr::Create(0-Val, getContext()); - } else - return ErrorOperand(PlusLoc, "unexpected token after +"); - } else if (getLexer().is(AsmToken::Identifier)) { - // This could be an index register or a displacement expression. - if (!IndexReg) - ParseRegister(IndexReg, Start, End); - else if (getParser().ParseExpression(Disp, End)) - return 0; + SM.onInteger(Val); + break; } - } - - // Parse ][ as a plus. - if (getLexer().is(AsmToken::RBrac)) { - ExpectRBrac = false; - End = Parser.getTok().getEndLoc(); - Parser.Lex(); - if (getLexer().is(AsmToken::LBrac)) { - ExpectRBrac = true; - Parser.Lex(); - if (getParser().ParseExpression(Disp, End)) - return 0; + case AsmToken::Plus: SM.onPlus(); break; + case AsmToken::Minus: SM.onMinus(); break; + case AsmToken::Star: SM.onStar(); break; + case AsmToken::LBrac: SM.onLBrac(); break; + case AsmToken::RBrac: SM.onRBrac(); break; + } + if (!Done && UpdateLocLex) { + End = Tok.getLoc(); + Parser.Lex(); // Consume the token. } - } else if (ExpectRBrac) { - if (getParser().ParseExpression(Disp, End)) - return 0; } - if (ExpectRBrac) { - if (getLexer().isNot(AsmToken::RBrac)) - return ErrorOperand(End, "expected ']' token!"); - End = Parser.getTok().getEndLoc(); - Parser.Lex(); - } + if (!Disp) + Disp = MCConstantExpr::Create(SM.getDisp(), getContext()); // Parse the dot operator (e.g., [ebx].foo.bar). if (Tok.getString().startswith(".")) { @@ -806,10 +989,18 @@ X86Operand *X86AsmParser::ParseIntelBracExpression(unsigned SegReg, Disp = NewDisp; } + int BaseReg = SM.getBaseReg(); + int IndexReg = SM.getIndexReg(); + // handle [-42] - if (!BaseReg && !IndexReg) - return X86Operand::CreateMem(Disp, Start, End, Size); + if (!BaseReg && !IndexReg) { + if (!SegReg) + return X86Operand::CreateMem(Disp, Start, End); + else + return X86Operand::CreateMem(SegReg, Disp, 0, 0, 1, Start, End, Size); + } + int Scale = SM.getScale(); return X86Operand::CreateMem(SegReg, Disp, BaseReg, IndexReg, Scale, Start, End, Size); } diff --git a/test/MC/X86/intel-syntax.s b/test/MC/X86/intel-syntax.s index 7edd26a138..8bfa58a4be 100644 --- a/test/MC/X86/intel-syntax.s +++ b/test/MC/X86/intel-syntax.s @@ -56,13 +56,195 @@ _main: // CHECK: fld %st(0) fld ST(0) // CHECK: movl %fs:(%rdi), %eax - mov EAX, DWORD PTR FS:[RDI] -// CHECK: leal (,%rdi,4), %r8d - lea R8D, DWORD PTR [4*RDI] -// CHECK: movl _fnan(,%ecx,4), %ecx - mov ECX, DWORD PTR [4*ECX + _fnan] -// CHECK: movq %fs:320, %rax - mov RAX, QWORD PTR FS:[320] -// CHECK: vpgatherdd %xmm8, (%r15,%xmm9,2), %xmm1 - vpgatherdd XMM10, DWORD PTR [R15 + 2*XMM9], XMM8 + mov EAX, DWORD PTR FS:[RDI] +// CHECK: leal (,%rdi,4), %r8d + lea R8D, DWORD PTR [4*RDI] +// CHECK: movl _fnan(,%ecx,4), %ecx + mov ECX, DWORD PTR [4*ECX + _fnan] +// CHECK: movq %fs:320, %rax + mov RAX, QWORD PTR FS:[320] +// CHECK: vpgatherdd %xmm8, (%r15,%xmm9,2), %xmm1 + vpgatherdd XMM10, DWORD PTR [R15 + 2*XMM9], XMM8 +// CHECK: movsd -8, %xmm5 + movsd XMM5, QWORD PTR [-8] +// CHECK: movl %ecx, (%eax) + mov [eax], ecx +// CHECK: movl %ecx, (,%ebx,4) + mov [4*ebx], ecx + // CHECK: movl %ecx, (,%ebx,4) + mov [ebx*4], ecx +// CHECK: movl %ecx, 1024 + mov [1024], ecx +// CHECK: movl %ecx, 4132 + mov [0x1024], ecx +// CHECK: movl %ecx, 32 + mov [16 + 16], ecx +// CHECK: movl %ecx, 0 + mov [16 - 16], ecx +// CHECK: movl %ecx, 32 + mov [16][16], ecx +// CHECK: movl %ecx, (%eax,%ebx,4) + mov [eax + 4*ebx], ecx +// CHECK: movl %ecx, (%eax,%ebx,4) + mov [eax + ebx*4], ecx +// CHECK: movl %ecx, (%eax,%ebx,4) + mov [4*ebx + eax], ecx +// CHECK: movl %ecx, (%eax,%ebx,4) + mov [ebx*4 + eax], ecx +// CHECK: movl %ecx, (%eax,%ebx,4) + mov [eax][4*ebx], ecx +// CHECK: movl %ecx, (%eax,%ebx,4) + mov [eax][ebx*4], ecx +// CHECK: movl %ecx, (%eax,%ebx,4) + mov [4*ebx][eax], ecx +// CHECK: movl %ecx, (%eax,%ebx,4) + mov [ebx*4][eax], ecx +// CHECK: movl %ecx, 12(%eax) + mov [eax + 12], ecx +// CHECK: movl %ecx, 12(%eax) + mov [12 + eax], ecx +// CHECK: movl %ecx, 32(%eax) + mov [eax + 16 + 16], ecx +// CHECK: movl %ecx, 32(%eax) + mov [16 + eax + 16], ecx +// CHECK: movl %ecx, 32(%eax) + mov [16 + 16 + eax], ecx +// CHECK: movl %ecx, 12(%eax) + mov [eax][12], ecx +// CHECK: movl %ecx, 12(%eax) + mov [12][eax], ecx +// CHECK: movl %ecx, 32(%eax) + mov [eax][16 + 16], ecx +// CHECK: movl %ecx, 32(%eax) + mov [eax + 16][16], ecx +// CHECK: movl %ecx, 32(%eax) + mov [eax][16][16], ecx +// CHECK: movl %ecx, 32(%eax) + mov [16][eax + 16], ecx +// CHECK: movl %ecx, 32(%eax) + mov [16 + eax][16], ecx +// CHECK: movl %ecx, 32(%eax) + mov [16][16 + eax], ecx +// CHECK: movl %ecx, 32(%eax) + mov [16 + 16][eax], ecx +// CHECK: movl %ecx, 32(%eax) + mov [eax][16][16], ecx +// CHECK: movl %ecx, 32(%eax) + mov [16][eax][16], ecx +// CHECK: movl %ecx, 32(%eax) + mov [16][16][eax], ecx +// CHECK: movl %ecx, 16(,%ebx,4) + mov [4*ebx + 16], ecx +// CHECK: movl %ecx, 16(,%ebx,4) + mov [ebx*4 + 16], ecx +// CHECK: movl %ecx, 16(,%ebx,4) + mov [4*ebx][16], ecx +// CHECK: movl %ecx, 16(,%ebx,4) + mov [ebx*4][16], ecx +// CHECK: movl %ecx, 16(,%ebx,4) + mov [16 + 4*ebx], ecx +// CHECK: movl %ecx, 16(,%ebx,4) + mov [16 + ebx*4], ecx +// CHECK: movl %ecx, 16(,%ebx,4) + mov [16][4*ebx], ecx +// CHECK: movl %ecx, 16(,%ebx,4) + mov [16][ebx*4], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [eax + 4*ebx + 16], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [eax + 16 + 4*ebx], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [4*ebx + eax + 16], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [4*ebx + 16 + eax], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [16 + eax + 4*ebx], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [16 + eax + 4*ebx], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [eax][4*ebx + 16], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [eax][16 + 4*ebx], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [4*ebx][eax + 16], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [4*ebx][16 + eax], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [16][eax + 4*ebx], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [16][eax + 4*ebx], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [eax + 4*ebx][16], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [eax + 16][4*ebx], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [4*ebx + eax][16], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [4*ebx + 16][eax], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [16 + eax][4*ebx], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [16 + eax][4*ebx], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [eax][4*ebx][16], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [eax][16][4*ebx], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [4*ebx][eax][16], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [4*ebx][16][eax], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [16][eax][4*ebx], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [16][eax][4*ebx], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [eax + ebx*4 + 16], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [eax + 16 + ebx*4], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [ebx*4 + eax + 16], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [ebx*4 + 16 + eax], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [16 + eax + ebx*4], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [16 + eax + ebx*4], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [eax][ebx*4 + 16], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [eax][16 + ebx*4], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [ebx*4][eax + 16], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [ebx*4][16 + eax], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [16][eax + ebx*4], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [16][eax + ebx*4], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [eax + ebx*4][16], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [eax + 16][ebx*4], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [ebx*4 + eax][16], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [ebx*4 + 16][eax], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [16 + eax][ebx*4], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [16 + eax][ebx*4], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [eax][ebx*4][16], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [eax][16][ebx*4], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [ebx*4][eax][16], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [ebx*4][16][eax], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [16][eax][ebx*4], ecx +// CHECK: movl %ecx, 16(%eax,%ebx,4) + mov [16][eax][ebx*4], ecx +// CHECK: movl %ecx, -16(%eax,%ebx,4) + mov [eax][ebx*4 - 16], ecx ret -- cgit v1.2.3-18-g5258 From 7d72cf892ec745d916af34cf9e68703010b4ded8 Mon Sep 17 00:00:00 2001 From: Shuxin Yang Date: Mon, 14 Jan 2013 22:48:41 +0000 Subject: This change is to implement following rules under the condition C_A and/or C_R --------------------------------------------------------------------------- C_A: reassociation is allowed C_R: reciprocal of a constant C is appropriate, which means - 1/C is exact, or - reciprocal is allowed and 1/C is neither a special value nor a denormal. ----------------------------------------------------------------------------- rule1: (X/C1) / C2 => X / (C2*C1) (if C_A) => X * (1/(C2*C1)) (if C_A && C_R) rule 2: X*C1 / C2 => X * (C1/C2) if C_A rule 3: (X/Y)/Z = > X/(Y*Z) (if C_A && at least one of Y and Z is symbolic value) rule 4: Z/(X/Y) = > (Z*Y)/X (similar to rule3) rule 5: C1/(X*C2) => (C1/C2) / X (if C_A) rule 6: C1/(X/C2) => (C1*C2) / X (if C_A) rule 7: C1/(C2/X) => (C1/C2) * X (if C_A) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172488 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../InstCombine/InstCombineMulDivRem.cpp | 135 +++++++++++++++++++-- test/Transforms/InstCombine/fast-math.ll | 96 +++++++++++++++ 2 files changed, 223 insertions(+), 8 deletions(-) diff --git a/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index d0f43928c3..29846c156c 100644 --- a/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -784,21 +784,140 @@ Instruction *InstCombiner::visitSDiv(BinaryOperator &I) { return 0; } +/// CvtFDivConstToReciprocal tries to convert X/C into X*1/C if C not a special +/// FP value and: +/// 1) 1/C is exact, or +/// 2) reciprocal is allowed. +/// If the convertion was successful, the simplified expression "X * 1/C" is +/// returned; otherwise, NULL is returned. +/// +static Instruction *CvtFDivConstToReciprocal(Value *Dividend, + ConstantFP *Divisor, + bool AllowReciprocal) { + const APFloat &FpVal = Divisor->getValueAPF(); + APFloat Reciprocal(FpVal.getSemantics()); + bool Cvt = FpVal.getExactInverse(&Reciprocal); + + if (!Cvt && AllowReciprocal && FpVal.isNormal()) { + Reciprocal = APFloat(FpVal.getSemantics(), 1.0f); + (void)Reciprocal.divide(FpVal, APFloat::rmNearestTiesToEven); + Cvt = !Reciprocal.isDenormal(); + } + + if (!Cvt) + return 0; + + ConstantFP *R; + R = ConstantFP::get(Dividend->getType()->getContext(), Reciprocal); + return BinaryOperator::CreateFMul(Dividend, R); +} + Instruction *InstCombiner::visitFDiv(BinaryOperator &I) { Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); if (Value *V = SimplifyFDivInst(Op0, Op1, TD)) return ReplaceInstUsesWith(I, V); + bool AllowReassociate = I.hasUnsafeAlgebra(); + bool AllowReciprocal = I.hasAllowReciprocal(); + if (ConstantFP *Op1C = dyn_cast(Op1)) { - const APFloat &Op1F = Op1C->getValueAPF(); - - // If the divisor has an exact multiplicative inverse we can turn the fdiv - // into a cheaper fmul. - APFloat Reciprocal(Op1F.getSemantics()); - if (Op1F.getExactInverse(&Reciprocal)) { - ConstantFP *RFP = ConstantFP::get(Builder->getContext(), Reciprocal); - return BinaryOperator::CreateFMul(Op0, RFP); + if (AllowReassociate) { + ConstantFP *C1 = 0; + ConstantFP *C2 = Op1C; + Value *X; + Instruction *Res = 0; + + if (match(Op0, m_FMul(m_Value(X), m_ConstantFP(C1)))) { + // (X*C1)/C2 => X * (C1/C2) + // + Constant *C = ConstantExpr::getFDiv(C1, C2); + const APFloat &F = cast(C)->getValueAPF(); + if (F.isNormal() && !F.isDenormal()) + Res = BinaryOperator::CreateFMul(X, C); + } else if (match(Op0, m_FDiv(m_Value(X), m_ConstantFP(C1)))) { + // (X/C1)/C2 => X /(C2*C1) [=> X * 1/(C2*C1) if reciprocal is allowed] + // + Constant *C = ConstantExpr::getFMul(C1, C2); + const APFloat &F = cast(C)->getValueAPF(); + if (F.isNormal() && !F.isDenormal()) { + Res = CvtFDivConstToReciprocal(X, cast(C), + AllowReciprocal); + if (!Res) + Res = BinaryOperator::CreateFDiv(X, C); + } + } + + if (Res) { + Res->setFastMathFlags(I.getFastMathFlags()); + return Res; + } + } + + // X / C => X * 1/C + if (Instruction *T = CvtFDivConstToReciprocal(Op0, Op1C, AllowReciprocal)) + return T; + + return 0; + } + + if (AllowReassociate && isa(Op0)) { + ConstantFP *C1 = cast(Op0), *C2; + Constant *Fold = 0; + Value *X; + bool CreateDiv = true; + + // C1 / (X*C2) => (C1/C2) / X + if (match(Op1, m_FMul(m_Value(X), m_ConstantFP(C2)))) + Fold = ConstantExpr::getFDiv(C1, C2); + else if (match(Op1, m_FDiv(m_Value(X), m_ConstantFP(C2)))) { + // C1 / (X/C2) => (C1*C2) / X + Fold = ConstantExpr::getFMul(C1, C2); + } else if (match(Op1, m_FDiv(m_ConstantFP(C2), m_Value(X)))) { + // C1 / (C2/X) => (C1/C2) * X + Fold = ConstantExpr::getFDiv(C1, C2); + CreateDiv = false; + } + + if (Fold) { + const APFloat &FoldC = cast(Fold)->getValueAPF(); + if (FoldC.isNormal() && !FoldC.isDenormal()) { + Instruction *R = CreateDiv ? + BinaryOperator::CreateFDiv(Fold, X) : + BinaryOperator::CreateFMul(X, Fold); + R->setFastMathFlags(I.getFastMathFlags()); + return R; + } + } + return 0; + } + + if (AllowReassociate) { + Value *X, *Y; + Value *NewInst = 0; + Instruction *SimpR = 0; + + if (Op0->hasOneUse() && match(Op0, m_FDiv(m_Value(X), m_Value(Y)))) { + // (X/Y) / Z => X / (Y*Z) + // + if (!isa(Y) || !isa(Op1)) { + NewInst = Builder->CreateFMul(Y, Op1); + SimpR = BinaryOperator::CreateFDiv(X, NewInst); + } + } else if (Op1->hasOneUse() && match(Op1, m_FDiv(m_Value(X), m_Value(Y)))) { + // Z / (X/Y) => Z*Y / X + // + if (!isa(Y) || !isa(Op0)) { + NewInst = Builder->CreateFMul(Op0, Y); + SimpR = BinaryOperator::CreateFDiv(NewInst, X); + } + } + + if (NewInst) { + if (Instruction *T = dyn_cast(NewInst)) + T->setDebugLoc(I.getDebugLoc()); + SimpR->setFastMathFlags(I.getFastMathFlags()); + return SimpR; } } diff --git a/test/Transforms/InstCombine/fast-math.ll b/test/Transforms/InstCombine/fast-math.ll index df0455a203..5a1ad5e6db 100644 --- a/test/Transforms/InstCombine/fast-math.ll +++ b/test/Transforms/InstCombine/fast-math.ll @@ -256,3 +256,99 @@ define float @fneg1(float %f1, float %f2) { ; CHECK: @fneg1 ; CHECK: fmul float %f1, %f2 } + +; ========================================================================= +; +; Testing-cases about div +; +; ========================================================================= +; X/C1 / C2 => X * (1/(C2*C1)) + +define float @fdiv1(float %x) { + %div = fdiv float %x, 0x3FF3333340000000 + %div1 = fdiv fast float %div, 0x4002666660000000 + ret float %div1 +; 0x3FF3333340000000 = 1.2f +; 0x4002666660000000 = 2.3f +; 0x3FD7303B60000000 = 0.36231884057971014492 +; CHECK: @fdiv1 +; CHECK: fmul fast float %x, 0x3FD7303B60000000 +} + +; X*C1 / C2 => X * (C1/C2) +define float @fdiv2(float %x) { + %mul = fmul float %x, 0x3FF3333340000000 + %div1 = fdiv fast float %mul, 0x4002666660000000 + ret float %div1 + +; 0x3FF3333340000000 = 1.2f +; 0x4002666660000000 = 2.3f +; 0x3FE0B21660000000 = 0.52173918485641479492 +; CHECK: @fdiv2 +; CHECK: fmul fast float %x, 0x3FE0B21660000000 +} + +; "X/C1 / C2 => X * (1/(C2*C1))" is disabled (for now) is C2/C1 is a denormal +; +define float @fdiv3(float %x) { + %div = fdiv float %x, 0x47EFFFFFE0000000 + %div1 = fdiv fast float %div, 0x4002666660000000 + ret float %div1 +; CHECK: @fdiv3 +; CHECK: fdiv float %x, 0x47EFFFFFE0000000 +} + +; "X*C1 / C2 => X * (C1/C2)" is disabled if C1/C2 is a denormal +define float @fdiv4(float %x) { + %mul = fmul float %x, 0x47EFFFFFE0000000 + %div = fdiv float %mul, 0x3FC99999A0000000 + ret float %div +; CHECK: @fdiv4 +; CHECK: fmul float %x, 0x47EFFFFFE0000000 +} + +; (X/Y)/Z = > X/(Y*Z) +define float @fdiv5(float %f1, float %f2, float %f3) { + %t1 = fdiv float %f1, %f2 + %t2 = fdiv fast float %t1, %f3 + ret float %t2 +; CHECK: @fdiv5 +; CHECK: fmul float %f2, %f3 +} + +; Z/(X/Y) = > (Z*Y)/X +define float @fdiv6(float %f1, float %f2, float %f3) { + %t1 = fdiv float %f1, %f2 + %t2 = fdiv fast float %f3, %t1 + ret float %t2 +; CHECK: @fdiv6 +; CHECK: fmul float %f3, %f2 +} + +; C1/(X*C2) => (C1/C2) / X +define float @fdiv7(float %x) { + %t1 = fmul float %x, 3.0e0 + %t2 = fdiv fast float 15.0e0, %t1 + ret float %t2 +; CHECK: @fdiv7 +; CHECK: fdiv fast float 5.000000e+00, %x +} + +; C1/(X/C2) => (C1*C2) / X +define float @fdiv8(float %x) { + %t1 = fdiv float %x, 3.0e0 + %t2 = fdiv fast float 15.0e0, %t1 + ret float %t2 +; CHECK: @fdiv8 +; CHECK: fdiv fast float 4.500000e+01, %x +} + +; C1/(C2/X) => (C1/C2) * X +define float @fdiv9(float %x) { + %t1 = fdiv float 3.0e0, %x + %t2 = fdiv fast float 15.0e0, %t1 + ret float %t2 +; CHECK: @fdiv9 +; CHECK: fmul fast float %x, 5.000000e+00 +} + -- cgit v1.2.3-18-g5258 From e673b54bdde4b538cbd67eadac80a15d238c926f Mon Sep 17 00:00:00 2001 From: Jakub Staszak Date: Mon, 14 Jan 2013 23:16:36 +0000 Subject: Remove trailing spaces. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172489 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/InstCombine/InstCombine.h | 50 ++++++++-------- lib/Transforms/InstCombine/InstCombineWorklist.h | 30 +++++----- lib/Transforms/Utils/BasicBlockUtils.cpp | 76 ++++++++++++------------ 3 files changed, 78 insertions(+), 78 deletions(-) diff --git a/lib/Transforms/InstCombine/InstCombine.h b/lib/Transforms/InstCombine/InstCombine.h index a36b1e6b9e..1f6a3a5e33 100644 --- a/lib/Transforms/InstCombine/InstCombine.h +++ b/lib/Transforms/InstCombine/InstCombine.h @@ -27,7 +27,7 @@ namespace llvm { class DbgDeclareInst; class MemIntrinsic; class MemSetInst; - + /// SelectPatternFlavor - We can match a variety of different patterns for /// select operations. enum SelectPatternFlavor { @@ -36,7 +36,7 @@ enum SelectPatternFlavor { SPF_SMAX, SPF_UMAX //SPF_ABS - TODO. }; - + /// getComplexity: Assign a complexity or rank value to LLVM Values... /// 0 -> undef, 1 -> Const, 2 -> Other, 3 -> Arg, 3 -> Unary, 4 -> OtherInst static inline unsigned getComplexity(Value *V) { @@ -51,23 +51,23 @@ static inline unsigned getComplexity(Value *V) { return isa(V) ? (isa(V) ? 0 : 1) : 2; } - + /// InstCombineIRInserter - This is an IRBuilder insertion helper that works /// just like the normal insertion helper, but also adds any new instructions /// to the instcombine worklist. -class LLVM_LIBRARY_VISIBILITY InstCombineIRInserter +class LLVM_LIBRARY_VISIBILITY InstCombineIRInserter : public IRBuilderDefaultInserter { InstCombineWorklist &Worklist; public: InstCombineIRInserter(InstCombineWorklist &WL) : Worklist(WL) {} - + void InsertHelper(Instruction *I, const Twine &Name, BasicBlock *BB, BasicBlock::iterator InsertPt) const { IRBuilderDefaultInserter::InsertHelpe